Guest User

Untitled

a guest
Jun 30th, 2018
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. PROGRAM poisson
  2. USE MPI
  3. IMPLICIT NONE
  4. !******************************************************************************
  5. !*  Solution of Poisson Equation on a rectangular domain
  6. !*      x=(0,...,XMAX) y=(0,...,YMAX)
  7. !* by means of Jacobi iteretion method (to be parallelized with MPI)
  8. !* the source term is rho(x,y) and the psi is zero on the boundary
  9. !*  10 nov 2005             by Andrea Bertoni
  10. !*
  11. !* Dividiamo il dominio in numprocs sottodomini. Ciascun processore
  12. !* calcolerà il psi relativo al proprio dominio. I vari psi verranno
  13. !* poi raccolti dal master(processore 0). I nodi comunicheranno
  14. !* tra di loro per implementare l'algoritmo di Jacobi.
  15. !******************************************************************************
  16.  
  17. !Dimensioni dominio
  18. REAL, PARAMETER    :: XMAX= 1., YMAX= 1.    
  19. !Punti sulla griglia
  20. INTEGER, PARAMETER :: NUMX= 100, NUMY= 100
  21. !Max numero di iterazioni  
  22. INTEGER, PARAMETER :: NITERMAX=50000   
  23. !Errore massimo permesso(serve per terminare il ciclo) 
  24. REAL, PARAMETER    :: MAXERROR= 1e-6
  25.  
  26. REAL*8, ALLOCATABLE :: psi (:,:)    ! potenziale
  27. REAL*8, ALLOCATABLE :: psinew (:,:)
  28. !rho: rappresenta la densità di carica
  29. REAL*8 :: rho(NUMX, NUMY)
  30. !Locazione sulla griglia
  31. REAL*8 :: x (NUMX), y(NUMY)
  32. !Rappresentano h lungo x e lungo y
  33. REAL*8 :: deltax, deltay
  34. !Sommatori che tengono conto della differenza della psinew
  35. !tra un'iterazione e l'altra
  36. REAL*8 :: sumdiff, sumdiff2
  37.  
  38. INTEGER :: nx, ny, niter, i, j
  39. INTEGER :: myid,numprocs,ierr
  40. INTEGER :: STATUS(MPI_STATUS_SIZE)
  41. !Dimensione dei sottodomini affidati ai processi
  42. INTEGER :: fetta_dominio
  43. INTEGER :: resto
  44. !Per ogni processo corrispondono alla prima e ultima riga
  45. INTEGER, ALLOCATABLE :: riga_inizio(:), riga_fine (:)
  46.  
  47.  
  48.  
  49.  CALL MPI_INIT( ierr )
  50.  CALL MPI_COMM_RANK( MPI_COMM_WORLD, myid, ierr )
  51.  CALL MPI_COMM_SIZE( MPI_COMM_WORLD, numprocs, ierr ) ! il numero di processori
  52.  
  53.  ALLOCATE(riga_inizio(0:numprocs-1),riga_fine(0:numprocs-1),stat=ierr)
  54.  
  55.  !Come viene ripartito il dominio
  56.  fetta_dominio= NUMY / numprocs
  57.  resto= mod(NUMY,numprocs)
  58.  
  59.  DO i=0, numprocs-1
  60.      IF (i==0) THEN
  61.        riga_inizio(i)=1
  62.      ELSE
  63.        riga_inizio(i)=riga_fine(i-1)+1
  64.      END IF
  65.  
  66.      IF (i<resto) THEN
  67.        riga_fine(i)=riga_inizio(i)+fetta_dominio
  68.      ELSE
  69.        riga_fine(i)=riga_inizio(i)+fetta_dominio-1
  70.      END IF
  71.  
  72.  END DO
  73.  
  74.  DO i=0, resto-1
  75.     IF (myid==i) fetta_dominio=fetta_dominio+1
  76.  END DO
  77.  
  78.  
  79.  
  80.  !alloco psinew
  81.  ALLOCATE(psinew(0:NUMX+1,0:fetta_dominio+1), stat=ierr)
  82.  !alloco psi con dimensioni diverse in base al processore
  83.  IF (myid==0) THEN
  84.     ALLOCATE(psi(0:NUMX+1,0:NUMY+1), stat=ierr)
  85.  ELSE
  86.     ALLOCATE(psi(0:NUMX+1,0:fetta_dominio+1), stat=ierr)
  87.  END IF
  88.  
  89.  !inizializzo psinew e psi
  90.  psinew(:,:)=0.0
  91.  psi(:,:)=0.0
  92.  
  93.  !calcolo h lungo x e y
  94.  deltax = XMAX / NUMX
  95.  deltay= YMAX / NUMY
  96.  
  97.  !definisco le posizioni dei punti
  98.  DO nx = 1, NUMX
  99.     x (nx)= nx * deltax
  100.  END DO
  101.  
  102.  DO ny= 1, NUMY
  103.     y(ny)= ny * deltay
  104.  END DO
  105.  
  106.  !la densità viene messa a zero
  107.  rho(:,:)=0.0
  108.  
  109.  !se mi trovo nell'intervallo [0.4,0.2] e [0.6,0.5]
  110.  !imposto la rho
  111.  
  112.  
  113. IF (myid==0) THEN
  114.  
  115.   DO nx= 1, NUMX    !inizializza la matrice di densità di carica
  116.     DO ny= 1, NUMY  !per il processo zero
  117.       IF (x(nx) >= 0.4 .AND. x(nx) <= 0.6) THEN
  118.     IF (y(ny) >= 0.2 .AND. y(ny) <= 0.5) THEN
  119.       rho(nx,ny)= -(4.*3.1415926) * (- 2.)
  120.     END IF
  121.       END IF
  122.     END DO
  123.   END DO
  124.  
  125.  ELSE
  126.  
  127.   DO nx= 1, NUMX    !inizializza la matrice di densità di carica
  128.     DO ny= riga_inizio(myid), riga_fine(myid)
  129.       IF (x(nx) >= 0.4 .AND. x(nx) <= 0.6) THEN
  130.     IF (y(ny) >= 0.2 .AND. y(ny) <= 0.5) THEN
  131.        rho(nx,(ny-riga_inizio(myid)+1))=-(4.*3.1415926)*(-2.)
  132.     END IF
  133.       END IF
  134.     END DO
  135.   END DO
  136.  
  137.  END IF
  138.  
  139. !Setto la psi uguale alla psinew del ciclo precedente e la
  140. !aggiorno.
  141.  
  142.  DO niter = 1, NITERMAX
  143.  
  144.     DO i=1,NUMX
  145.     DO j=1,fetta_dominio
  146.            psi(i,j)=psinew(i,j)
  147.     END DO
  148.     END DO
  149.  
  150.  sumdiff = 0.    
  151.  
  152.  !il processo zero spedisce la sua riga più
  153.  !alta al processo successivo(1) e riceve
  154.  !la più bassa del processo successivo        
  155.  IF (myid==0) THEN
  156.  
  157.     CALL MPI_RECV(psi(:,fetta_dominio+1),NUMX,MPI_DOUBLE_PRECISION,1,0, MPI_COMM_WORLD,STATUS,ierr )
  158.     CALL MPI_SEND(psi(:,fetta_dominio),NUMX,MPI_DOUBLE_PRECISION,1,1,MPI_COMM_WORLD,ierr)
  159.  
  160.  !l'ultimo processo spedisce la sua riga
  161.  !più bassa al processo precedente e
  162.  !riceve la più alta del processo precedente
  163.  ELSE IF (myid==numprocs-1) THEN
  164.  
  165.     CALL MPI_SEND(psi(:,1),NUMX,MPI_DOUBLE_PRECISION,myid-1,0,MPI_COMM_WORLD,ierr)
  166.     CALL MPI_RECV(psi(:,0),NUMX,MPI_DOUBLE_PRECISION,myid-1,1, MPI_COMM_WORLD,STATUS,ierr )
  167.  
  168.  ELSE
  169.  
  170.  !tutti i processi devono inviare la loro riga
  171.  !più bassa al processo precedente e ricevere
  172.  !la riga più bassa del processo successivo
  173.  CALL MPI_SENDRECV(psi(:,1),NUMX, MPI_DOUBLE_PRECISION, myid-1,0,  &
  174.                 &     psi(:,fetta_dominio+1),NUMX, MPI_DOUBLE_PRECISION, myid+1,0,  &
  175.                 &     MPI_COMM_WORLD, STATUS, ierr)
  176.  !tutti i processi devono inviare la loro riga più
  177.  !alta al processo successivo e ricevere la riga
  178.  !più alta del processo precedente
  179.  CALL MPI_SENDRECV(psi(:,fetta_dominio),NUMX, MPI_DOUBLE_PRECISION, myid+1,1,  &
  180.                 &     psi(:,0),NUMX, MPI_DOUBLE_PRECISION, myid-1,1,  &
  181.                 &     MPI_COMM_WORLD, STATUS, ierr)
  182.  
  183. END IF
  184.  
  185.   DO nx = 1,NUMX
  186.     DO ny = 1,fetta_dominio
  187.     psinew(nx,ny)= 0.25 * (-deltax*deltay*rho(nx,ny) + psi(nx-1,ny) + psi(nx,ny-1) + psi(nx,ny+1) + psi(nx+1,ny))
  188.     sumdiff= sumdiff + ABS(psi(nx,ny) - psinew(nx,ny))
  189.     END DO
  190.   END DO
  191.  
  192.   !raccolgo in sumdiff2 i vari sumdiff
  193.   CALL MPI_REDUCE(sumdiff,sumdiff2,1,MPI_DOUBLE_PRECISION,MPI_SUM,0,MPI_COMM_WORLD,ierr)
  194.  
  195.   !se sono il processo zero calcolo sumdiff2
  196.   IF (myid==0) THEN
  197.     sumdiff2=sumdiff2/(NUMX*NUMY)   ! per trovare la media delle differenze
  198.     write (*,*) myid, "sumdiff2= ",sumdiff2
  199.   END IF
  200.  
  201.   CALL MPI_BCAST(sumdiff2,1,MPI_DOUBLE_PRECISION,0,MPI_COMM_WORLD,ierr)
  202.  
  203.   IF (sumdiff2<MAXERROR) then
  204.     write(*,*) myid,": sumddiff= ",sumdiff2
  205.     write(*,*) "num: 8155 "
  206.     EXIT
  207.   END IF
  208.  
  209. END DO
  210.  
  211.  
  212.   IF (myid==0) THEN
  213.     !stampo il numero di iterazioni
  214.     WRITE (*,*) "niter = ", NITER
  215.     !
  216.     DO j=fetta_dominio+1,NUMY
  217.     CALL MPI_RECV(psi(:,j),NUMX,MPI_DOUBLE_PRECISION,MPI_ANY_SOURCE,j, MPI_COMM_WORLD,STATUS,ierr )
  218.     END DO
  219.  
  220.     OPEN(23, FILE="psi.dat", STATUS="UNKNOWN", FORM= "FORMATTED")
  221.     DO nx= 1, NUMX  !salva la matrice dei risultati
  222.       DO ny= 1, NUMY
  223.     WRITE(23,*) x(nx), y(ny), psi(nx,ny)
  224.       END DO
  225.       WRITE(23,*)
  226.     END DO
  227.     CLOSE(23)
  228.  
  229.     OPEN(24, FILE="rho.dat", STATUS="UNKNOWN", FORM= "FORMATTED")
  230.     DO nx= 1, NUMX
  231.       DO ny= 1, NUMY
  232.     WRITE(24,*) x(nx), y(ny), rho(nx,ny)/(-4.*3.1415)
  233.       END DO
  234.       WRITE(24,*)
  235.     END DO
  236.     CLOSE(24)
  237.  
  238.  ELSE
  239.  
  240.  !spedisco il risultato al processo zero
  241.     DO i=1,fetta_dominio
  242.     CALL MPI_SEND(psi(:,i),NUMX,MPI_DOUBLE_PRECISION,0,(riga_inizio(myid)+i-1),MPI_COMM_WORLD,ierr)
  243.     END DO
  244.  END IF
  245.  
  246.  CALL MPI_FINALIZE(ierr)
  247.  
  248.   DEALLOCATE(psi)
  249.   DEALLOCATE(psinew)
  250.   DEALLOCATE(riga_inizio,riga_fine)
  251.  
  252. END PROGRAM
Add Comment
Please, Sign In to add comment