!module_parallel_mpi.f90
!!!!
!!subroutine initialisation_mpi
!!subroutine creation_topologie
!!subroutine domaine
!!subroutine voisinage
!!subroutine type_derive
!!subroutine communication
!!function erreur_globale
!!subroutine ecrire_mpi
!!subroutine finalisation_mpi
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

MODULE parallel
  USE TYPE_PARAMS
  USE MPI
  IMPLICIT NONE

  !Numero du sous domaine
  INTEGER                                   :: rang
  !Nombre de processus
  INTEGER                                   :: nb_procs
  !Communicateur de la topologie cartesienne
  INTEGER                                   :: comm2d
  !Nombre de dimensions de la grille 
  INTEGER, PARAMETER                        :: ndims = 2
  !Nombre de processus dans chaque dimension definissant la topologie
  INTEGER, DIMENSION(ndims)                 :: dims
  !Periodicite de  la topologie
  LOGICAL, DIMENSION(ndims)                 :: periods
  ! Coordonnees des points dans la grille
  INTEGER, DIMENSION(ndims)                 :: coords
  ! Tableau definissant les voisins de chaque processus
  INTEGER, PARAMETER                        :: NB_VOISINS = 4
  INTEGER, PARAMETER                        :: N=1, E=2, S=3, W=4
  INTEGER, DIMENSION(NB_VOISINS)            :: voisin
  ! Types derives
  INTEGER                                   :: type_ligne,type_colonne
  !Constantes MPI
  INTEGER                                   :: code  

CONTAINS

  SUBROUTINE initialisation_mpi
    !************
    !Initialisation pour chaque processus de son rang et du 
    !nombre total de processus nb_procs
    !************

    !Initialisation de MPI
    

    !Savoir quel processus je suis
    

    !Connaitre le nombre total de processus
    

  END SUBROUTINE initialisation_mpi

  SUBROUTINE creation_topologie
    !************
    !Creation de la topologie cartesienne
    !************

    !Constantes MPI
    LOGICAL, PARAMETER                        :: reorganisation = .FALSE.

    ! Lecture du nombre de points ntx en x et nty en y 
    OPEN(10,FILE='poisson.data',STATUS='OLD')
    READ(10,*) ntx
    READ(10,*) nty
    CLOSE(10)
   
    !Connaitre le nombre de processus selon x et le nombre de processus
    !selon y en fonction du nombre total de processus
 
    !Creation de la grille de processus 2D sans periodicite

    IF (rang == 0) then
       PRINT *,'Execution code poisson avec ', nb_procs, ' processus MPI'
       PRINT *,'Taille du domaine : ntx=',ntx,'nty=',nty
       PRINT *,'Dimension de la topologie : ',&
                dims(1),' suivant x,',dims(2),' suivant y'
       PRINT *,'-----------------------------------------'
    END IF

  END SUBROUTINE  creation_topologie


  SUBROUTINE domaine
    !************
    !Calcul du nombre de points dans les directions x et y pour chaque sous domaine
    !************
    
    ! Connaitre mes coordonnees dans la topologie
    

    !Calcul pour chaque processus de ses indices de debut et de fin suivant x
    sx = (coords(1)*ntx)/dims(1)+1
    ex = ((coords(1)+1)*ntx)/dims(1)

    !Calcul pour chaque processus de ses indices de debut et de fin suivant y
    sy = (coords(2)*nty)/dims(2)+1
    ey = ((coords(2)+1)*nty)/dims(2)

    PRINT *, 'Rang dans la topologie : ',rang,&
         'Indice des tableaux :',  sx,' a',ex,'suivant x, ',&
         sy,' a',ey,' suivant y'

  END SUBROUTINE domaine

  SUBROUTINE voisinage
    !************
    !Calcul des processus voisins pour chaque processus
    !************

    !Initialisation du tableau voisin
   

    !Recherche des voisins Nord et Sud 
    

    !Recherche des voisins Ouest et Est
   

    PRINT *, "Processus ", rang, " a pour voisin : N",voisin(N),"E",voisin(E),&
            "S",voisin(S),"W",voisin(W)

  END SUBROUTINE voisinage


  SUBROUTINE type_derive
    !************
    !Creation des types derives type_ligne et type_colonne
    !************

    !Creation du type type_ligne pour echanger les points 
    !au nord et au sud


    !Creation du type type_colonne pour echanger 
    !les points  a l'ouest et a l'est  
  

  END SUBROUTINE type_derive


  SUBROUTINE communication(u)
    !************
    !Echange des points aux interfaces
    !************

    REAL(kind=8),ALLOCATABLE,DIMENSION(:,:), INTENT(inout) :: u

    !Constantes MPI
    INTEGER, PARAMETER                   :: etiquette=100
    INTEGER, DIMENSION(MPI_STATUS_SIZE)  :: statut

    !Envoi au voisin N et reception du voisin S
    

    !Envoi au voisin S et reception du voisin N
    

    !Envoi au voisin W et  reception du voisin E 
    

    !Envoi au voisin E et  reception du voisin W 
 

  END SUBROUTINE communication

  FUNCTION erreur_globale (u, u_nouveau)
    !************
    !Calcul de l'erreur globale (maximum des erreurs locales)
    !************
    REAL(kind=8),ALLOCATABLE,DIMENSION(:,:), INTENT(in) :: u, u_nouveau

    REAL(kind=8)              :: erreur_globale,erreur_locale
    REAL(kind=8)              :: diffnorm

    erreur_locale = MAXVAL (ABS(u(sx:ex,sy:ey)&
                             -u_nouveau(sx:ex,sy:ey)))
   
    !Calcul de l'erreur sur tous les sous-domaines
   

    erreur_globale = diffnorm

  END FUNCTION erreur_globale

  SUBROUTINE ecrire_mpi(u)
    !********************
    ! Ecriture du tableau u a l'interieur d'un domaine pour chaque processus
    ! dans le fichier donnees.dat
    !********************
    REAL(kind=8),ALLOCATABLE,DIMENSION(:,:), INTENT(inout) :: u

    !Constantes MPI
    INTEGER,DIMENSION(MPI_STATUS_SIZE)   :: statut
    INTEGER                              :: descripteur
    LOGICAL                              :: existence
    INTEGER(kind = MPI_OFFSET_KIND)      :: deplacement_initial
    INTEGER,PARAMETER                    :: rang_tableau=2
    INTEGER,DIMENSION(rang_tableau)      :: profil_tab,profil_sous_tab,coord_debut
    INTEGER,DIMENSION(rang_tableau)      :: profil_tab_vue,profil_sous_tab_vue,coord_debut_vue
    INTEGER                              :: type_sous_tab,type_sous_tab_vue
    INTEGER                              :: nb_octets_double_precision,&
                                            taille_type_sous_tab,&
                                            taille_type_sous_tab_vue

    !Taille du type de base MPI_DOUBLE_PRECISION
    

    !Ouverture du fichier "donnees.dat" en écriture
   
    !Test pour savoir si ouverture du fichier est correcte
    IF (code /= MPI_SUCCESS) THEN
       PRINT *,'ATTENTION erreur lors ouverture du fichier'
       CALL MPI_ABORT(comm2d,2,code)
       CALL finalisation_mpi
    END IF

    !Creation du type derive type_sous_tab qui definit la matrice u 
    !sans les cellules fantomes
    !Profil du tableau u 
    

    !Profil du sous tableau
   

    !Coordonnees de depart du sous tableau 
    

    !Creation du type_derive type_sous_tab
   

    !Validation du type_derive type_sous_tab
    

    !Taille  du type_derive type_sous_tab
    

    !Creation du type type_sous_tab_vue  pour la vue sur le fichier
    !Profil du tableau global
   

    !Profil du sous tableau  
    

    !Coordonnees de depart du sous tableau 
    

    !Creation du type_derive type_sous_tab_vue
    

    !Validation du type_derive type_sous_tab_vue
    

    !Taille du type_derive type_sous_tab_vue
   

    PRINT *,'Nombre elements de base ',taille_type_sous_tab/nb_octets_double_precision, &
         'Nombre elements vue',taille_type_sous_tab_vue/nb_octets_double_precision,&
         ' pour le processus ', rang

    !Définition de la vue sur le fichier a partir du debut

    !Ecriture du tableau u par tous les processus avec la vue

    ! Fermeture du fichier

  END SUBROUTINE ecrire_mpi

  SUBROUTINE finalisation_mpi
    !************
    !Desactivation de l'environnement MPI
    !************

    ! Desactivation de MPI
    

  END SUBROUTINE  finalisation_mpi

END MODULE parallel

