       PROGRAM  PRODUIT_SHMEM
!
!===============================================================================
!===============================================================================
! CRIHAN     10/99
! Utilisation de la bibliotheque d'echange de messages SHMEM (SGI/CRAY)
!
! Programme SPMD
!
! 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
!
!===============================================================================
!===============================================================================
!
      USE numerics
!
      IMPLICIT NONE
!
! COMMON(S) NECESSAIRE(S)
!
      INCLUDE 'mpp/shmem.fh'
!
      INCLUDE 'cdim.h'
!
! DECLARATION DES VARIABLES
!
      INTEGER, SAVE, DIMENSION (SHMEM_COLLECT_SYNC_SIZE)  ::  process_collect_sync
      INTEGER, SAVE, DIMENSION (SHMEM_BARRIER_SYNC_SIZE)  ::  process_barrier_sync
!
      REAL(rp), SAVE, DIMENSION (N, N)  ::  MAT
      REAL(rp), SAVE, DIMENSION (N)     ::  RESULT, TEMP
!
      REAL(rp), DIMENSION (N)  ::  VECT
      REAL(rp), DIMENSION (N)  ::  U, V
!
      REAL(rp), DIMENSION (N, N)   ::   A, B
!
      REAL(rp)   ::  LAMBDA, scal
!
      INTEGER    ::  NPROCS, ME, num_pes, my_pe
      INTEGER    ::  I, J, K
      INTEGER    ::  INDMIN, INDMAX
      INTEGER    ::  INTERV, NVAL, NV
!
!
!===============================================================================
!===============================================================================
!
!     DEBUT DU PROGRAMME
!
!===============================================================================
!===============================================================================
!
!
!----Demarrage de l'application SHMEM
      CALL START_PES (0)
!
!----Nombre total de processus
      NPROCS = NUM_PES ()
!
!----Mon numero de processus
      ME = MY_PE ()
!
!----Synchronisation shmem_fcollect et shmem_barrier sur ensemble des processus
      process_collect_sync (:) = SHMEM_SYNC_VALUE
      process_barrier_sync (:) = SHMEM_SYNC_VALUE
!
!----Determine les indices de calcul
      INTERV = N / NPROCS
      INDMIN = ME * INTERV + 1
      INDMAX = INDMIN + INTERV - 1
      IF ( ME == NPROCS - 1 ) INDMAX = N
      NVAL = INDMAX - INDMIN + 1
      WRITE (6,1010) 'ME = ', ME, ' : ', &
                      INDMIN, ' => ', INDMAX, ' NVAL = ', NVAL
 1010 FORMAT ( 4(A, I4) )
!
!----Initialisation de VECT et LAMBDA par tous les processus
      scal = 5.0_rp / 12.0_rp
      DO I = 1, N
         U (I) = scal
         V (I) = 0.2_rp * un + REAL (I,rp)
      END DO
!
      DO I = 1, N
         VECT (I) = V (I) + U (I)
      END DO
!
      LAMBDA = zero
      DO I = 1, N
         LAMBDA = LAMBDA + U (I) * V (I)
      END DO
!
      RESULT = zero
      TEMP = zero
!
!----Initialisation des ligne de la matrice MAT par chaque proc
!----MAT = (tU)*U + LAMBDA*(tV)*V
      DO I = INDMIN, INDMAX
         DO J = 1, N
            MAT (I, J) = U (I) * U (J) + LAMBDA * V (I) * V (J)
         END DO
      END DO
!
!----Chaque processus realise son produit partiel
      TEMP = zero
      K = 1
      DO I = INDMIN, INDMAX
         DO J = 1, N
            TEMP (K) = TEMP (K) + MAT (I,J) * VECT (J)
         END DO
         K = K + 1
      END DO
      NV = MOD (N, NPROCS)
!
!----Synchronisation de tous les procs
      CALL SHMEM_BARRIER (0, 0, NPROCS, process_barrier_sync)
!
!---Tous les processus recuperent dans RESULT le produit partiel
      IF ( NV == 0 ) THEN
	 CALL SHMEM_FCOLLECT8 (RESULT, TEMP, NVAL, 0, 0, NPROCS, process_collect_sync)
      ELSE
         CALL SHMEM_FCOLLECT8 (RESULT, TEMP, INTERV, 0, 0, NPROCS, process_collect_sync)
         CALL SHMEM_IGET8 ( RESULT(NPROCS*INTERV+1), TEMP(INTERV+1), 1, 1, NV, NPROCS-1)
      ENDIF
!
!---Affiche le resultat
      WRITE (6, 1020) 'MAT    : PROC = ', ME, MAT (1, 1)
      WRITE (6, 1020) 'RESULT : PROC = ', ME, RESULT (1), RESULT (N)
 1020 FORMAT ( A, I5, 2E12.4 )
!
!===============================================================================
!===============================================================================
!
!     FIN DU PROGRAMME
!
!===============================================================================
!===============================================================================
!
      STOP 
      END PROGRAM PRODUIT_SHMEM
