	PROGRAM SLAVE_PVM
!=================================================================================
!=================================================================================
! CRIHAN     11/2000
! Guy Moebs   Guy.Moebs@crihan.fr
!
! Utilisation de la bibliotheque d'echange de messages PVM
! (www.epm.ornl.gov/pvm/pvm_home.html)
!
! Programme MPMD (maitre/esclave) : code de l'esclave
!
! Calcul du vecteur R = ( U*(tU) + LAMBDA*V*(tV) )  *  ( U + V )
!
!              i.e. RESULT = MAT * VECT
!
! 1.  Initialisation du vecteur par tous les processus
! 2.  Initialisation distribuee des ligne de la matrice par chaque processus
! 3.  Calcul du produit partiel par chaque processus :
!          lignes matrice * vecteur
! 4.  Tous les processus se redistribuent les produits partiels pour avoir
!     le resultat complet
!
!
!=================================================================================
!=================================================================================
!
!     DECLARATIONS
!
!=================================================================================
!=================================================================================
!
! MODULE(S) NECESSAIRE(S)
!
      use modscal
!
      IMPLICIT NONE
!
! COMMON(S) NECESSAIRE(S)
!
      INCLUDE 'fpvm3.h'
!
! DECLARATION DES CONSTANTES
!
      INTEGER      ITYPE_REAL
!
! DECLARATION DES VARIABLES
!
      REAL(rp),  ALLOCATABLE,  DIMENSION(:,:)  ::  MAT
      REAL(rp),  ALLOCATABLE,  DIMENSION(:)    ::  VECT
      REAL(rp),  ALLOCATABLE,  DIMENSION(:)    ::  RESULT
!
      INTEGER    ::  NPROC, MYTID, INFO
      INTEGER    ::  MSGTYPE
      INTEGER    ::  INTERV, NVAL, IDEBUT
      INTEGER    ::  N, I, IERR = 0
!
      INTEGER    ::  NPROC, MYTID, ME
      INTEGER    ::  MSTTID, NUMTID
      INTEGER    ::  MSGTYPE, INFO
      INTEGER    ::  INDMIN, INDMAX
      INTEGER    ::  INTERV, NVAL
      INTEGER    ::  I, N, IERR = 0
!
!
!=================================================================================
!=================================================================================
!
!     DEBUT DU PROGRAMME
!
!=================================================================================
!=================================================================================
!
!
!----Type de donnees
!
      IF ( rp == dp ) THEN
         ITYPE_REAL = REAL8
      ELSE
         ITYPE_REAL = REAL4
      END IF
!
!-----Routage des communications
      CALL PVMFSETOPT (PVMROUTE, PvmRouteDirect, INFO)
      WRITE (6,1010) 'PVMFSETOP = ', INFO
 1010 FORMAT ( 3(A, I4) )
!
!
!----Identificateur du Processus
      CALL PVMFMYTID (MYTID)
!
!
!----TID du processus PERE
      CALL PVMFPARENT (MSTTID)
!
!
!----Insertion dans le groupe 'GROUPE'
      CALL PVMFJOINGROUP ('GROUPE', ME)
!
!
!----Reception du Nombre de slaves crees par le PERE
      MSGTYPE = 0
      CALL PVMFRECV (MSTTID, MSGTYPE, INFO)
      CALL PVMFUNPACK (INTEGER4, NPROC, 1, 1, INFO)
      CALL PVMFUNPACK (INTEGER4, N,     1, 1, INFO)
!
!
!----Point de synchronisation
      CALL PVMFBARRIER ('GROUPE', NPROC, INFO)
!
!
!----Envoi au PERE de son numero dans le groupe 'GROUPE' + son TID
      MSGTYPE = 1
      CALL PVMFINITSEND (PVMDATADEFAULT, INFO)
      CALL PVMFPACK (INTEGER4, ME, 1, 1, INFO)
      CALL PVMFPACK (INTEGER4, MYTID, 1, 1, INFO)
      CALL PVMFSEND (MSTTID, MSGTYPE, INFO)
!
!
!----Determine les indices de calcul
      INTERV = N / NPROC
      INDMIN = ME * INTERV + 1
      INDMAX = INDMIN + INTERV - 1
      IF ( ME == (NPROC-1) ) INDMAX = N
      NVAL = INDMAX - INDMIN + 1
      WRITE (6,1010) 'PROC : ', ME, ' CALCUL ', INDMIN, ' => ', INDMAX
!
      ALLOCATE ( MAT(N,N), RESULT(INDMIN:INDMAX), VECT(N), STAT = IERR )
      IF (ierr /= 0) THEN
!
         WRITE (6,'(A)') ' Probleme allocation MAT, RESULT, VECT'
         WRITE (6,1010) ' IERR = ', IERR
         STOP
!
      END IF
!
!-----Reception du vecteur et de la matrice
      MSGTYPE = 2
      CALL PVMFRECV (MSTTID, MSGTYPE, INFO)
      CALL PVMFUNPACK (ITYPE_REAL, VECT, N, 1, INFO)
      CALL PVMFUNPACK (ITYPE_REAL, MAT, N*N, 1, INFO)
!
!
!-----Calcul du produit
      CALL PROD_LIGNE (MAT, VECT, RESULT, INDMIN, INDMAX, N)
!
!
!-----Envoi de son resultat au PERE
      MSGTYPE = 3
      CALL PVMFINITSEND (PVMDEFAULT, INFO)
      CALL PVMFPACK (INTEGER4, ME, 1, 1, INFO)
      CALL PVMFPACK (INTEGER4, NVAL, 1, 1, INFO)
      CALL PVMFPACK (ITYPE_REAL, RESULT (INDMIN), NVAL, 1, INFO)
      CALL PVMFSEND (MSTTID, MSGTYPE, INFO)
!
!
!-----Liberation de la memoire
!
      DEALLOCATE ( MAT, VECT, RESULT )
!
!
!-----Quitter le groupe 'GROUPE'
      CALL PVMFLVGROUP ('GROUPE', INFO)
!
!
!-----Quitter PVM
      CALL PVMFEXIT (INFO)
!
!
!=================================================================================
!=================================================================================
!
!     FIN DU PROGRAMME
!
!=================================================================================
!=================================================================================
!
      STOP
      END PROGRAM SLAVE_PVM
!
!
!
!
!===============================================================
!
!     SUBROUTINE PROD_LIGNE : produit matrice vecteur distribue
!
!     MAT       (R ,E ) Matrice  du produit matriciel
!     VECT      (R ,E ) Vecteur  du produit matriciel
!     RESULT    (R, S ) Resultat du produit matriciel
!     INDMIN    (I ,E ) Indice initial des lignes distribuees
!     INDMAX    (I ,E ) Indice final   des lignes distribuees
!
!===============================================================
!
        SUBROUTINE PROD_LIGNE (MAT, VECT, RESULT, INDMIN, INDMAX, N)
!
! MODULE(S) NECESSAIRE(S)
!
      use modscal
!
      IMPLICIT NONE
!
! DECLARATION DES ARGUMENTS
!
      INTEGER, INTENT (IN)  ::  N
      INTEGER, INTENT (IN)  ::  INDMIN
      INTEGER, INTENT (IN)  ::  INDMAX
!
      REAL(rp),  DIMENSION(N,N),             INTENT (IN)   ::  MAT
      REAL(rp),  DIMENSION(N),               INTENT (IN)   ::  VECT
      REAL(rp),  DIMENSION(INDMIN:INDMAX),   INTENT (OUT)  ::  RESULT
!
! DECLARATION DES VARIABLES LOCALES
!
      INTEGER  ::  I
      INTEGER  ::  J
!
! DEBUT DE LA SUBROUTINE
!
!
      RESULT (INDMIN:INDMAX) = zero
!
!
!------Produit en ligne : RESULT = MAT * VECT
!
      DO J = 1, N
         DO I = INDMIN, INDMAX
            RESULT (I) = RESULT (I) + MAT (I,J) * VECT (J)
         END DO
      END DO
!
! FIN DE LA SUBROUTINE
!
      RETURN
      END SUBROUTINE PROD_LIGNE

