! This programme determines the surface flows of the sun from the
! motions of granule; 
! 9 Novembre 2012  Thierry Roudier

        program cst

        use param_run
        use segmentation
        use thename
        use readfits
        use interpolationroutine
        use moyenne
        use m_time_set
        use OMP_LIB
        
        implicit none

        character strg*4,strgx*4,strgy*4,suff*3,fichier*100

	character fichier2*100

        integer, parameter:: n_six = 1
        integer, parameter:: n_siy = 1
        integer, parameter:: aire_max = 70  ! taille maxi en aire SDO
!       pour l'exemple sinon pour SDO fen= 5,fenetre pour extraction des granules
!!        integer, parameter:: aire_max = 700  ! taille maxi en aire test simu
!!       integer, parameter:: fen = 20
        integer, parameter:: fen = 5 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!        integer, parameter:: volume = 5000000 ! dimensionne poursequence de  30min 
!!        integer, parameter:: volume = 10000000 ! dimensionne poursequence de  60min 
!        integer, parameter:: volume = 20000000 ! dimensionne poursequence de  120min 
        integer  nunu,numero_gran,num_gran,fen2,npp,soma,soma2
        integer   numbermax,debut,ll,BIN
        integer  i,ii,ic,ip,ipp,k,kk,nn,n,f,g,h,mini,maxi,kks,numkks
        integer  ngmax,lifetime,maxim,maximum,numero_a_arreter,maximum1
        integer  xmin,xmax,ymin,ymax,maxi_objp2,maxigran,minigran
        integer  gran,gran2,posx,posy,fusion,nombre_de_granules
        integer  maxi_obj,xn,yn,nouv,nouvv  !!!!,nx,ny
        integer  gran2t,minum,maxnum,comptgrantemp,gran3,comptgrantemp2

        integer, dimension(:),allocatable ::  numero_granule
        integer, dimension(:),allocatable ::  numgrantemp
        integer, dimension(:,:),allocatable :: image,image2
        integer, dimension (:,:),allocatable :: temporaire, image_tmoins1 
        integer, dimension(:,:),allocatable :: temporaire3, temporaire2
        integer, dimension(:,:),allocatable :: masque,masque2,masque_sun
        integer, dimension(:,:),allocatable :: obj_a_tplus1,obj_a_t,obj_a_tmoins1
        integer, dimension(:,:),allocatable :: obj0,obj1,obj2,obj,obj3
        integer, dimension(:,:),allocatable :: image_t,image_tplus1
        
        real hscale,velo_scale,dt,vvx,vvy,xl,yl,cgx,cgy,cgx1,cgy1,t1,t2
        real dist,R_sol,x_cent,y_cent
 
        real, dimension (:),  allocatable :: x,y,vx,vy,dv
        real, dimension(:,:), allocatable :: xtraj0,ytraj0,duree0
        real, dimension(:),allocatable :: XGRAN,YGRAN

        real, dimension(:),allocatable :: XGRANmoins,YGRANmoins   
        real, dimension(:),allocatable :: XGRANfin,YGRANfin
        real, dimension(:,:), allocatable :: YY,XX,XXtemp,YYtemp 
        real, dimension (:) , allocatable :: comptgran,comptgran2,comptgranfin,comptgrant,comptgran3

       include 'form_num.inc'

 ! For reading the image
       real, pointer :: a(:,:)
       real, pointer :: imagesup(:,:)

       integer naxes(2)          
       character numero*4,frame*128
!! Mesure temps de calcul
!N. Renon 23/05/2011
  integer                      :: ir, t_1, t_2
  real(kind=8)                 :: t_cpu_0, t_cpu_1, t_cpu,temps


  
! read the data from standard input
        call input(ngmax,hscale)

! Save the inputfile in the results directory
        call system('cp '//trim(adjustl(input_file))//' '//postprocessingpath)

!pour definir nx et ny on lit la premiere image

! Find the file
        
       ip=1
       nullify(a)
       write(numero,444) ip_start+istep*(ip-1)
       numero=adjustl(numero)
       frame=trim(prefix)//trim(numero)//suffix
        call readimage(frame,a,naxes)  
        nx=naxes(1) 
        ny=naxes(2)
!
       print*,'nx=',nx,'    ny=',ny

        open(unit=16,file=trim(adjustl(postprocessingpath))//'/nb_gran',position='append')
        write(16,*)  v_thres, arcsec, pixel, seuil

! Prepare the index of the traject files
         write(strg,"(i4)") n_six
         strgx=adjustl(strg)
         write(strg,"(i4)") n_siy
         strgy=adjustl(strg)

! Allocations
          fen2=1+2*fen

         allocate(xtraj0(ngmax,2),ytraj0(ngmax,2),duree0(ngmax,2))
         xtraj0=0.; ytraj0=0.;  duree0=0.
     
         allocate(numero_granule(ngmax0)) ; numero_granule=0

         allocate(XGRAN(ngmax0),YGRAN(ngmax0)) ; XGRAN=0 ; YGRAN=0

         allocate(XGRANmoins(ngmax0),YGRANmoins(ngmax0))   
         XGRANmoins=0 ; YGRANmoins=0

         allocate(XGRANfin(ngmax0),YGRANfin(ngmax0)) 
         XGRANfin=0 ; YGRANfin=0

         allocate(image(nx,ny)) ; image=0 
         allocate(image2(fen2,fen2)) ; image2=0 

         allocate(comptgran(ngmax0), comptgran2(ngmax0))
         allocate(comptgran3(ngmax0))
         allocate(comptgranfin(ngmax0),comptgrant(ngmax0))
         allocate(numgrantemp(ngmax0))                     
         
!         allocate(x(volume),y(volume), vx(volume),vy(volume),dv(volume))
         allocate(x(ngmax),y(ngmax), vx(ngmax),vy(ngmax),dv(ngmax))

           x=0 ; y=0 ; vx=0 ;  vy=0 ; dv=0
        
          allocate(image_t(nx,ny)) ; image_t=0
          allocate(masque_sun(nx,ny)) ; masque_sun=0

          allocate(image_tmoins1(nx,ny),temporaire(nx,ny)) 
          image_tmoins1=0 ; temporaire=0  
          allocate(temporaire3(nx,ny)) 
          temporaire3=0 

          allocate(temporaire2(nx,ny))
          temporaire2=0
        
          allocate(image_tplus1(nx,ny)) ; image_tplus1=0

                
          allocate(YY(ngmax0,aire_max)) ; YY=0
          allocate(XX(ngmax0,aire_max)) ; XX=0 

  
          allocate(XXtemp(ngmax0,aire_max),YYtemp(ngmax0,aire_max))
          XXtemp=0 ; YYtemp=0
    !!Modif N Renon 05/2011    
!! Les tableaux sont alloués dans la région parallèle OpenMP  
#ifndef _OPENMP 
print*, "NON OPENMP"  
         allocate(obj_a_tplus1(fen2,fen2)) ; obj_a_tplus1=0
         allocate(obj_a_t(fen2,fen2))      ; obj_a_t=0
         allocate(obj_a_tmoins1(fen2,fen2)) ; obj_a_tmoins1=0
         allocate(masque(fen2,fen2)) ; masque=0
         allocate(masque2(fen2,fen2)) ; masque2=0
         allocate(obj(fen2,fen2),obj1(fen2,fen2)) ; obj=0 ; obj1=0
         allocate(obj2(fen2,fen2)) ; obj2=0 
         allocate(obj0(fen2,fen2)) ; obj0=0 
         allocate(obj3(fen2,fen2)) ; obj3=0 
#endif
!!Fin modif   

!fabrication d'un masque pour isoler le soleil


         
            R_sol=1873.
            x_cent= 2054.47
            y_cent= 2048.21

             do yl=1,ny 
              do xl=1,nx  
                dist=sqrt((xl - x_cent)*(xl - x_cent) + (yl - y_cent)*(yl - y_cent))
                if(dist.lt.R_sol) masque_sun(xl,yl)=1
               end do 
              end do


! *********** BOUCLE SUR TOUTES LES IMAGES -1  ******

         do ip=1,np-1 
          print*,'======================================================='
          print*,'t=',ip
          call cpu_time(t1)

! ======================= PREMIERE IMAGE ====
           if (ip == 1) then
              nullify(a)
             write(numero,444) ip_start+istep*(ip-1)
             numero=adjustl(numero)
             frame=trim(prefix)//trim(numero)//suffix


             call readimage(frame,a,naxes)  ! nx=naxes(1); ny=naxes(2)
             print*,frame


             a=a*real(masque_sun)

             
             call segmentlab(a,nx,ny,ngmax,image_t)       


! image labellisee: image_t 

             deallocate(a)

             nombre_de_granules=maxval(image_t)
             print*,'nombre_de_granules=',nombre_de_granules
             
            print*,'debut du calcul du masque' 


             comptgran(:)=0 

! Centre de gravite - debut calcul -  
             do yl=1,ny 
              do xl=1,nx  
                if(image_t(xl,yl).gt.0) then
                 gran=0
                 gran= image_t(xl,yl)
                 XGRAN(gran)= real(xl)+ XGRAN(gran)
                 YGRAN(gran)= real(yl)+ YGRAN(gran)            
                 comptgran(gran)= comptgran(gran) + 1
                endif
               end do 
              end do
             
              do i=1,nombre_de_granules   
               if(XGRAN(i) .gt. 0)  then  ! pour eviter les numeros non presents
                xtraj0(i,1)= XGRAN(i)/ real(comptgran(i))       ! cgx du debut
                ytraj0(i,1)= YGRAN(i)/ real(comptgran(i)) 
                duree0(i,1)=1  ! debut en temps  
               endif
              enddo                

! Centre de gravite  - fin calcul -  

! on initialise le nombre de granule maximum

              maximum=nombre_de_granules
              temporaire=image_t

!         image t+1      
              ipp= 1+ip
  ! on remet le pointeur bien en place
              nullify(imagesup) 
             write(numero,444) ip_start+istep*(ipp-1)
             numero=adjustl(numero)
             frame=trim(prefix)//trim(numero)//suffix
             print*,frame

              call readimage(frame,imagesup,naxes)  
              
              imagesup=imagesup*real(masque_sun)
         
              call segmentlab(imagesup,nx,ny,ngmax,image_tplus1) ! image labellisee:  image_tplus
              deallocate(imagesup)

              goto 1111
   
            endif                
!===================  FIN PREMIERE IMAGE ====================

           print*,' debut boucle sur les images'

!lecture de l'image a t+1

            ipp=ip+1
          

            nullify(imagesup)
             write(numero,444) ip_start+istep*(ipp-1)
             numero=adjustl(numero)
             frame=trim(prefix)//trim(numero)//suffix
             print*,frame             

           call readimage(frame,imagesup,naxes)   
         
           imagesup=imagesup*real(masque_sun)

           call segmentlab(imagesup,nx,ny,ngmax,image_tplus1) ! image labellisee:  image_tplus1
           deallocate(imagesup)


!image_t        image labellisee a t
!image_tmoins1  image avec la bonne labellisation dans le temps t-1
!
!=======debut de la boucle sur les ndeallocate(imagesup)umeros 
!de granule a t ==============

! on repere les coordonnees a la  tranche t   
! -----------------------------------------

            comptgran(:)=0 

            XGRAN=0
            YGRAN=0

           do yl=1,ny 
             do xl=1,nx    
              if(image_t(xl,yl).gt.0) then
                gran= image_t(xl,yl)

                XGRAN(gran)= real(xl)+ XGRAN(gran)
                YGRAN(gran)= real(yl)+ YGRAN(gran)
                comptgran(gran)= comptgran(gran) +1
              if ( comptgran(gran) .gt. aire_max-1) goto 1010  
               XX(gran,comptgran(gran))=xl 
               YY(gran,comptgran(gran))=yl
              endif
1010       continue
             end do
            end do

    
              nombre_de_granules=maxval(image_t)
 print*,'             nombre_de_granules a t=',maxval(image_t)

! on repere les coordonnees des granules a t-1
! --------------------------------------------
           numbermax=0                  

            temporaire2=0
            comptgran2=0
 
              where(image_tmoins1 .gt. 0)   
               temporaire2=1                         
              endwhere 
                  
            call label(real(temporaire2),nx,ny,ngmax,temporaire2)
            numbermax= maxval(temporaire2)

           do yl=1,ny         
             do xl=1,nx      
              if(temporaire2(xl,yl).gt.0) then           
               gran=temporaire2(xl,yl) 
               numero_granule(gran)= image_tmoins1(xl,yl)                         
               XGRANmoins(gran)= real(xl)+ XGRANmoins(gran)
               YGRANmoins(gran)= real(yl)+ YGRANmoins(gran)
               comptgran2(gran)= comptgran2(gran) +1
              end if
             end do
           end do


! on travaille sur l'image a t
 ! Temps CPU de calcul initial.
  call cpu_time(t_cpu_0)
  ! Temps CPU de restitution initial.
  call system_clock(count=t_1, count_rate=ir)
 
numgrantemp(:)=0
comptgrantemp=0

!$OMP PARALLEL DEFAULT(FIRSTPRIVATE) SHARED(numgrantemp,comptgrantemp,ip,temporaire,nx,ny,XX,YY,XGRAN,YGRAN,XGRANmoins,YGRANmoins,comptgran,comptgran2,comptgranfin,xtraj0,ytraj0,duree0,ngmax0,image_tplus1,image_t,image_tmoins1,nombre_de_granules,maximum,numero_granule,temporaire2,temporaire3)
#ifdef _OPENMP
print*, "IN OPENMP"
       allocate(obj_a_tplus1(fen2,fen2)) ; obj_a_tplus1=0
         allocate(obj_a_t(fen2,fen2))      ; obj_a_t=0
         allocate(obj_a_tmoins1(fen2,fen2)) ; obj_a_tmoins1=0
         allocate(masque(fen2,fen2)) ; masque=0
         allocate(masque2(fen2,fen2)) ; masque2=0
         allocate(obj(fen2,fen2),obj1(fen2,fen2)) ; obj=0 ; obj1=0
         allocate(obj2(fen2,fen2)) ; obj2=0 
         allocate(obj0(fen2,fen2)) ; obj0=0 
         allocate(obj3(fen2,fen2)) ; obj3=0 
!$OMP BARRIER
#endif
!$OMP DO SCHEDULE(RUNTIME)


  do kk= 1, nombre_de_granules  
!  1)on repere le granule dans la tranche t ici ip
            cgx= XGRAN(kk)/ real(comptgran(kk))       ! cgx 
            cgy= YGRAN(kk)/ real(comptgran(kk))       ! cgy

! on prend comme espace de localisation de chaque granule une boite de fen x fen pixels:

            xmin=cgx-fen       !-5 pixels 
            xmax=cgx+fen       !5
            ymin=cgy-fen       !-5  
            ymax=cgy+fen       !5
        
            if(xmin .lt. 1)  goto 123 
            if(xmax .gt. nx) goto 123 
            if(ymin .lt. 1)  goto 123 
            if(ymax .gt. ny) goto 123 
            
          obj_a_t =0 ; obj_a_tmoins1=0

          obj_a_t=image_t(xmin:xmax,ymin:ymax)
          obj_a_tmoins1=temporaire2(xmin:xmax,ymin:ymax)  
  
!           on prend les dimensions du fichier objet
             xn=0  ; yn=0
             xn=size(obj_a_t,1); yn=size(obj_a_t,2) 

!*********************************
!         nouveaux granules      *
!*********************************
! on regarde les numeros de granule dans la tranche t en liaison
! avec le granules a t-1 

!    fabrication d'un masque
!
           masque=0

            where(obj_a_t .eq. kk)    
             masque=1.                          
            endwhere 
! 
            obj=0 
            obj=obj_a_tmoins1*masque     
!                                                        
 

! NOUVEAU GRANULE
           if( sum(obj) .eq.0) then 
             
             do nn= 1, comptgran(kk)      
                if(nn .gt. aire_max-1) goto 5000 
                temporaire(XX(kk,nn),YY(kk,nn))= 1  
             enddo
5000         continue
             goto 123
          endif
          
! SINON on regarde si un granule ou plusieurs t-1
          maxi_obj=0

          if( sum(obj) .gt. 0) then        
                                            
             xn=size(obj,1); yn=size(obj,2) 
             call label(real(obj),xn,yn,ngmax0,obj0)                  
             f=0
             g=0                            
             f=minval(obj0,mask=obj0 .ne.0)  
             g=maxval(obj0,mask=obj0 .ne.0)   
             if (f.eq.g) then               
                maxi_obj=1.
             else
                maxi_obj=g
             endif
        endif
!
!************************************
!  Meme numero de granule qu'a t-1  *
!************************************

            if( maxi_obj .eq. 1)  then 
             h=0 
             h= maxval(obj,mask=obj.ne.0) 
             numero_gran = numero_granule(h)         
             comptgrantemp=comptgrantemp + 1
             numgrantemp(comptgrantemp)=numero_gran
  
              do nunu=1,comptgran(kk)
               if(nunu .gt. aire_max-1)  goto 1114
                posx=XX(kk,nunu)   
                posy=YY(kk,nunu)
          
              if (posx .lt. 1) goto 1114
              if (posx .gt. nx) goto 1114             
              if (posy .lt. 1) goto 1114           
              if (posy .gt. ny) goto 1114            
        
              temporaire3(posx,posy)=numero_gran  
           enddo
1114          continue 

             goto 123
           endif
 
 
!************************************
!         GESTION des jonctions     *
!************************************

            if( maxi_obj .gt.1) then 
! on arrete les granules qui se melangent
! on recupere les numeros des granules a arreter
      
             do n=f,g                    
              soma=0
 
             soma=sum(obj0,mask=obj0.eq.n) 
              
               masque2=0
              
               if (soma .gt. 0) then            
                where(obj0.eq.n)
                 masque2=1
                endwhere
              
              obj2=obj*masque2  
              numero_a_arreter=maxval(obj2 ,mask=obj2.ne.0) 

! recuperer les CGX et CGY dans l'image a  t-1 
           cgx1= XGRANmoins(numero_a_arreter)/ real(comptgran2(numero_a_arreter))       
           cgy1= YGRANmoins(numero_a_arreter)/ real(comptgran2(numero_a_arreter))       
 
          xtraj0(numero_granule(numero_a_arreter),2)= cgx1 
          ytraj0(numero_granule(numero_a_arreter),2)= cgy1   
          duree0(numero_granule(numero_a_arreter),2)=ip-1                
         endif
        enddo

!  c'est donc un nouveau granule a t. 

             do nunu=1,comptgran(kk)
               if(nunu .gt. aire_max-1) goto 1112
 
              posx=XX(kk,nunu)   
              posy=YY(kk,nunu)
              
              if (posx .lt. 1)   goto 1112 
              if (posx .gt. nx)  goto 1112             
              if (posy .lt. 1)   goto 1112           
              if (posy .gt. ny)  goto 1112                    
   
              temporaire(posx,posy)=1       
             enddo                              
1112         continue

          endif
 
!***********************************************************
!                fin   GESTION des jonctions               *
!***********************************************************
!                 FIN de granule seul                      *
!***********************************************************

123 enddo   !fin de la boucle sur les kk
!$OMP END DO
!========================================================


$#ifdef _OPENMP
$        print*, 'DEALLOCATE IN OPENMP'
$         deallocate(obj_a_tplus1,obj_a_t,obj_a_tmoins1)
$         deallocate(masque,masque2)
$         deallocate(obj,obj1)
$         deallocate(obj2)
$         deallocate(obj0)
$         deallocate(obj3)
$#endif
!$OMP END PARALLEL   

  ! Temps CPU de restitution final
  call system_clock(count=t_2, count_rate=ir)
  temps=real(t_2 - t_1,kind=8)/real(ir,kind=8)

  ! Temps CPU de calcul final
  call cpu_time(t_cpu_1)
  t_cpu = t_cpu_1 - t_cpu_0

print*, "temps boucle I granule elepased", temps
print*, "temps boucle I granule cpu ", t_cpu

 ! Temps CPU de calcul initial.
  call cpu_time(t_cpu_0)
  ! Temps CPU de restitution initial.
  call system_clock(count=t_1, count_rate=ir)
          if (sum(temporaire) .gt. 0) then

          call label(real(temporaire),nx,ny,ngmax0,temporaire)

          maxigran= maxval(temporaire)

          if (sum(temporaire).eq.0) then
            minigran=   minval(temporaire)
           else 
            minigran=   minval(temporaire ,mask=temporaire .ne.0) 
          endif

! on repere les coordonnees des granules dans temporaire
! ------------------------------------------------------
            comptgran3(:)=0 
            XGRAN=0
            YGRAN=0

            do yl=1,ny         
             do xl=1,nx      
              if(temporaire(xl,yl).gt.0) then           
               gran3=temporaire(xl,yl)       
               XGRAN(gran3)= xl + XGRAN(gran3)
               YGRAN(gran3)= yl + YGRAN(gran3)

                comptgran3(gran3)= comptgran3(gran3) + 1

             if ( comptgran3(gran3) .gt. aire_max-1) goto 1811
              endif
1811         continue 
             end do
            end do

           comptgrantemp2 = comptgrantemp  
      
 
       print*,'minigran',minigran,'  maxigran=', maxigran

           do nouv=minigran,maxigran
             comptgrantemp2 = comptgrantemp2 +1
             numgrantemp(comptgrantemp2)=nouv
            cgx= XGRAN(nouv)/ real(comptgran3(nouv))       
            cgy= YGRAN(nouv)/ real(comptgran3(nouv))      

             nouvv=nouv+maximum
             maximum1=maximum

            xtraj0(nouvv,1)= cgx        
            ytraj0(nouvv,1)= cgy       
            duree0(nouvv,1)=ip      

           enddo
          
          comptgrantemp = comptgrantemp2

 endif
! on rajoute le nouveaux granules temporaire a ceux qui continuent
 
           where(temporaire .gt. 0)   
            temporaire(:,:)=temporaire(:,:) + maximum                         
           endwhere 
        
        temporaire = temporaire3 + temporaire
    
         maximum= maxval(temporaire)

        
 print*,'=================================='
 print*,' maximum=',maximum
 print*,'=================================='


!=============================================================
! GESTION DES SEPARATIONS
         
!=============================================================
! on repere les coordonnees des granules a t fichier  
! temporaire
            comptgrant(:)=0   
            minum=minval(temporaire,mask= temporaire .gt. 0)
            maxnum= maximum

print*,'minum=',minum,'  maxnum=',maxnum

            XGRAN(:)=0
            YGRAN(:)=0

            numbermax=0                  

              temporaire2=0

              where(temporaire .gt. 0)   
               temporaire2=1                         
              endwhere 
                  
            call label(real(temporaire2),nx,ny,ngmax,temporaire2)
            numbermax= maxval(temporaire2)

           do yl=1,ny         
             do xl=1,nx      
              if(temporaire2(xl,yl).gt.0) then           
               gran2t=temporaire2(xl,yl) 
               numero_granule(gran2t)= temporaire(xl,yl)             
              
               XGRAN(gran2t)= xl+ XGRAN(gran2t)
               YGRAN(gran2t)= yl+ YGRAN(gran2t)
                comptgrant(gran2t)= comptgrant(gran2t) +1

              if ( comptgrant(gran2t) .gt. aire_max-1) goto 1019
               XXtemp(gran2t,comptgrant(gran2t))=xl 
               YYtemp(gran2t,comptgrant(gran2t))=yl
              endif
1019          continue
             end do
           end do


             temporaire2=0

 ! Temps CPU de restitution final
  call system_clock(count=t_2, count_rate=ir)
  temps=real(t_2 - t_1,kind=8)/real(ir,kind=8)

  ! Temps CPU de calcul final
  call cpu_time(t_cpu_1)
  t_cpu = t_cpu_1 - t_cpu_0

print*, "temps intermediaire  granule elepased", temps
print*, "temps intermediaire granule cpu ", t_cpu

 ! Temps CPU de calcul initial.
  call cpu_time(t_cpu_0)
  ! Temps CPU de restitution initial.
  call system_clock(count=t_1, count_rate=ir)
!!!$OMP PARALLEL DEFAULT(FIRSTPRIVATE) SHARED(comptgrantemp,ip,temporaire,nx,ny,XXtemp,YYtemp,XGRANtemp,YGRANtemp,XGRANmoins,YGRANmoins,comptgrant,comptgran,comptgran2,comptgranfin,xtraj0,ytraj0,duree0,ngmax0,image_tplus1,image_t,image_tmoins1,maximum)


!$OMP PARALLEL DEFAULT(FIRSTPRIVATE) SHARED(comptgrantemp,ip,temporaire,nx,ny,XXtemp,YYtemp,XGRANmoins,YGRANmoins,comptgrant,comptgran,comptgran2,comptgranfin,xtraj0,ytraj0,duree0,ngmax0,image_tplus1,image_t,image_tmoins1,maximum)


#ifdef _OPENMP
!!$ 
         allocate(obj_a_tplus1(fen2,fen2)) ; obj_a_tplus1=0
         allocate(obj_a_t(fen2,fen2))      ; obj_a_t=0
         allocate(obj_a_tmoins1(fen2,fen2)) ; obj_a_tmoins1=0
         allocate(masque(fen2,fen2)) ; masque=0
         allocate(masque2(fen2,fen2)) ; masque2=0
         allocate(obj(fen2,fen2),obj1(fen2,fen2)) ; obj=0 ; obj1=0
         allocate(obj2(fen2,fen2)) ; obj2=0 
         allocate(obj0(fen2,fen2)) ; obj0=0 
         allocate(obj3(fen2,fen2)) ; obj3=0 
!$OMP BARRIER
#endif
!$OMP DO SCHEDULE(RUNTIME)


           do kks=1, numbermax                  

!  1)on repere le granule dans la tranche t ici temporaire
            cgx= XGRAN(kks)/ real(comptgrant(kks))       ! 
            cgy= YGRAN(kks)/ real(comptgrant(kks))       !

! on prend comme espace de localisation de chaque granule une boite de fen x fen pixels:
 
            xmin=cgx-fen       !-5 pixels  
            xmax=cgx+fen       !5
            ymin=cgy-fen       !-5  
            ymax=cgy+fen       !5
        
            if(xmin .lt. 1) goto 1239         
            if(xmax .gt. nx) goto 1239
            if( ymin .lt. 1) goto 1239
            if( ymax .gt. ny) goto 1239
 
         
!   on selection dans les images a t, t+1  l'espace ou est 
!localise le granule kks
  
            obj_a_tplus1=0 ; obj_a_t =0 

            obj_a_tplus1=image_tplus1(xmin:xmax,ymin:ymax)    
            obj_a_t=temporaire(xmin:xmax,ymin:ymax)            !    

!           on prend les dimensions du fichier objet
             xn=0  ; yn=0
             xn=size(obj_a_t,1); yn=size(obj_a_t,2) 
!
           masque=0
            where(obj_a_t .eq. numero_granule(kks))    
             masque=1.                
            endwhere 
! 
            obj=0 
            obj=obj_a_tplus1*masque    
 
             soma=  sum(obj,mask=obj .gt.0) 

             if( soma .eq.0) then       

!  c'est la fin du granule kks
           
          xtraj0(numero_granule(kks),2)= cgx    !    
          ytraj0(numero_granule(kks),2)= cgy    !   
          duree0(numero_granule(kks),2)=ip      !   

          do nunu=1,comptgrant(kks) 
            if(nunu .gt. aire_max-1) goto 1116
 
           posx=XXtemp(kks,nunu)   
           posy=YYtemp(kks,nunu)

           if (posx .lt. 1) goto 1116
           if (posx .gt. nx) goto 1116             
           if (posy .lt. 1) goto 1116           
           if (posy .gt. ny) goto 1116            
             
           temporaire(posx,posy)=0

          enddo 

                           
         goto 1239
       endif

1116       continue
!***********************************************************
!GESTION s'il y a plus de 2 structures a t+1               *
!***********************************************************
!
        maxi_obj=0

    if( soma .gt. 0) then                                                    
         f=minval(obj,mask=obj .ne.0) 
         g=maxval(obj,mask=obj .ne.0)  
         if (f.eq.g) then
           maxi_obj=1.
         else
           maxi_obj=g
         endif
      endif

! s'il y en plus de 2 morceaux
! c'est la fin du granule numkks

  if( maxi_obj .gt. 1) then
               
           xtraj0(numero_granule(kks),2)= cgx       !       
           ytraj0(numero_granule(kks),2)= cgy       !       
           duree0(numero_granule(kks),2)=ip         !     

          do nunu=1,comptgrant(kks)  
          if(nunu .gt. aire_max-1) goto 1117
 
            posx=XXtemp(kks,nunu)   
            posy=YYtemp(kks,nunu)

            if (posx .lt. 1) goto 1117
            if (posx .gt. nx) goto 1117             
            if (posy .lt. 1) goto 1117           
            if (posy .gt. ny) goto 1117             
           
           temporaire(posx,posy)=0      
          end do      
       
1117       continue 
end if   
!
!endif

1239      continue              
        
end do !fin de kks  (granules)
!$OMP END DO
!$OMP END PARALLEL

! 
!***********************************************************
!              fin    GESTION des separations              *
!***********************************************************



!========================================================
 ! Temps CPU de restitution final
  call system_clock(count=t_2, count_rate=ir)
  temps=real(t_2 - t_1,kind=8)/real(ir,kind=8)

  ! Temps CPU de calcul final
  call cpu_time(t_cpu_1)
  t_cpu = t_cpu_1 - t_cpu_0

print*, "temps boucle II granule elepased", temps
print*, "temps boucle II granule cpu ", t_cpu
!on arrete les granules pour la derniere image

       npp=np-1

       if(ip .eq. npp) then       ! avant derniere image
        comptgranfin(:)=0
       
            temporaire2=0

              where(temporaire .gt. 0)   
               temporaire2=1                         
              endwhere 
                  
            call label(real(temporaire2),nx,ny,ngmax,temporaire2)
            numbermax= maxval(temporaire2)

! Centre de gravite
           do yl=1,ny         
             do xl=1,nx      
              if(temporaire2(xl,yl).gt.0) then           
               gran=temporaire2(xl,yl) 
               numero_granule(gran)= temporaire(xl,yl)             
              
                comptgrant(gran)= comptgrant(gran) +1
                XGRANfin(gran)= xl+ XGRANfin(gran)
                YGRANfin(gran)= yl+ YGRANfin(gran)
                comptgranfin(gran)= comptgranfin(gran) +1
              if ( comptgranfin(gran) .gt. aire_max-1) goto 1049
              endif
1049          continue
             end do
           end do

  
        do i=1,numbermax
          xtraj0(numero_granule(i),2)= real(XGRANfin(i)/ comptgranfin(i))       
          ytraj0(numero_granule(i),2)= real(YGRANfin(i)/ comptgranfin(i)) 
          duree0(numero_granule(i),2)=ip      ! fin en temps 
        enddo  

        goto 2000
       endif

1111     continue                                 !suivant:

         maxim=maxval(temporaire)

         image_tmoins1=temporaire       
         image_t=image_tplus1

!     remise a zero
         numero_granule(:)=0

         image_tplus1(:,:)=0 
         temporaire(:,:)=0 
         temporaire2(:,:)=0
         temporaire3(:,:)=0

         XXtemp(:,:)=0
         YYtemp(:,:)=0
         comptgrantemp=0
         comptgran3(:)=0     
         comptgran2(:)=0 
         XGRAN(:)=0 
         YGRAN(:)=0 
         XGRANmoins(:)=0 
         YGRANmoins(:)=0 
         ipp=0
        call cpu_time(t2)
        
        print*,'duree de calcul=',t2-t1


!
2000    enddo !  ********** Fin de la boucle sur les images  *
      
! Output of the trajectories and velocity field

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
         ic=1
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 

         write(suff,"(i3)") ic
         fichier=trim(adjustl(postprocessingpath)) &
          //'/traject'//trim(adjustl(suff))//'_'// &
                 trim(strgx)//trim(strgy)
         open(unit=3,file=fichier)

         write(6,100) ic,maximum

100        format('Step number ',i3,'  Number of granule detected',f7.1)
           write(3,*) ic, maximum  

         ii=0; x=0.; y=0.; vx=0.; vy=0.; dv=0.
         lifetime=0d0

         print*, '          maximum=',maximum

         do i=1,maximum ! loop on the all the granules  
           
           if ( duree0(i,2) .ne. 0) then

!    Granules with a lifetime less than t_thresh are not used
         lifetime=(duree0(i,2)-duree0(i,1))*timestep    
       
           if ( lifetime < t_thres) goto 300
           velo_scale=hscale/lifetime ! km/s
    
            vvx=0 ; vvy=0

            vvx=(xtraj0(i,2)-xtraj0(i,1))*velo_scale
            vvy=(ytraj0(i,2)-ytraj0(i,1))*velo_scale
! on retire les vitesses > v_thres definie dans les donnees
            if ( abs(vvx) > v_thres) goto 300
            if ( abs(vvy) > v_thres) goto 300           

           ii=ii+1
           vx(ii)=(xtraj0(i,2)-xtraj0(i,1))*velo_scale
           vy(ii)=(ytraj0(i,2)-ytraj0(i,1))*velo_scale
           x(ii)=(xtraj0(i,2)+xtraj0(i,1))/2.
           y(ii)=(ytraj0(i,2)+ytraj0(i,1))/2.
           dv(ii)=delta_pix

           write(3,10) ii,x(ii),y(ii),duree0(i,1),duree0(i,2),lifetime,vx(ii),vy(ii)

           endif
300      enddo ! i and ii
 
          close(3)

10         format(i9,2x,2(1x,0pf8.2),2(1x,0pf8.2),2x,i9,1x,2(1x,0pf7.3))
         
          
          print*,'Nombre de points de mesure a interpoler',ii


 ! Temps CPU de calcul initial.
          call cpu_time(t_cpu_0)
  ! Temps CPU de restitution initial.
          call system_clock(count=t_1, count_rate=ir)

          call interpol2d_routine(vx,vy,dv,x,y,ii,ic)
        
 !========================================================
 ! Temps CPU de restitution final
  call system_clock(count=t_2, count_rate=ir)
  temps=real(t_2 - t_1,kind=8)/real(ir,kind=8)

  ! Temps CPU de calcul final
  call cpu_time(t_cpu_1)
  t_cpu = t_cpu_1 - t_cpu_0

  print*, "temps interlope  elepased", temps
  print*, "temps interlope cpu ", t_cpu  


end program cst
