*IF DEF,C97_1A,OR,DEF,RECON,OR,DEF,MAKEBC                                  UIE3F404.58     
C ******************************COPYRIGHT******************************    GTS2F400.10405  
C (c) CROWN COPYRIGHT 1995, METEOROLOGICAL OFFICE, All Rights Reserved.    GTS2F400.10406  
C                                                                          GTS2F400.10407  
C Use, duplication or disclosure of this code is subject to the            GTS2F400.10408  
C restrictions as set forth in the contract.                               GTS2F400.10409  
C                                                                          GTS2F400.10410  
C                Meteorological Office                                     GTS2F400.10411  
C                London Road                                               GTS2F400.10412  
C                BRACKNELL                                                 GTS2F400.10413  
C                Berkshire UK                                              GTS2F400.10414  
C                RG12 2SZ                                                  GTS2F400.10415  
C                                                                          GTS2F400.10416  
C If no contract has been raised with this copy of the code, the use,      GTS2F400.10417  
C duplication or disclosure of it is strictly prohibited.  Permission      GTS2F400.10418  
C to do so must first be obtained in writing from the Head of Numerical    GTS2F400.10419  
C Modelling at the above address.                                          GTS2F400.10420  
C ******************************COPYRIGHT******************************    GTS2F400.10421  
C                                                                          GTS2F400.10422  

      SUBROUTINE TIMER(SUB,I)                                               924,33TIMER1A.3      
CFPP$ NOCONCUR R                                                           TIMER1A.4      
!   ..................................................................     GIE1F304.2      
!   SUBROUTINE TIMER                                                       GIE1F304.3      
!   ----------------                                                       GIE1F304.4      
!   A PROGRAM TO RECORD THE FLOW THROUGH AND TIME SPENT IN EACH            GIE1F304.5      
!   SUBROUTINE OF A MULTI SUBROUTINED PROGRAM.                             GIE1F304.6      
!   CALLS TO TIMER MUST BE MADE BEFORE THE FIRST EXECUTABLE STATEMENT      GIE1F304.7      
!   OF EACH SUBROUTINE AND BEFORE EACH RETURN POINT.                       GIE1F304.8      
!                                                                          GIE1F304.9      
!   PARAMETERS:                                                            GIE1F304.10     
!   SUB - 8 BYTE CHARACTER STRING CONTAINING NAME OF CALLING               GIE1F304.11     
!         PROGRAM WHICH HAS BEEN LEFT ADJUSTED                             GIE1F304.12     
!                                                                          GIE1F304.13     
!   I  -  I=1 - FIRST CALL FROM MAIN (OR THE HIGHEST LEVEL PROGRAM)        GIE1F304.14     
!         I=2 - LAST CALL FROM MAIN ( OR THE HIGHEST LEVEL PROGRAM)        GIE1F304.15     
!         I=3 - FIRST CALL FROM LOWER SUBROUTINE                           GIE1F304.16     
!         I=4 CALL BEFORE RETURN STATEMENTS IN LOWER SUBROUTINE            GIE1F304.17     
!                                                                          GIE1F304.18     
!   ---NOTE :THE CRAY FACILITY PERFTRACE IS MORE APPROPRIATE FOR SINGLE    GIE1F304.19     
!   TASKED TIMING DIAGNOSTICS, BUT A BREAKDOWN OF ELAPSE TIME BY           GIE1F304.20     
!   SUBROUTINE OF MULTITASKED JOBS IS UNAVAILABLE WITHOUT THIS HOMEMADE    GIE1F304.21     
!   TIMER ROUTINE                                                          GIE1F304.22     
!                                                                          GIE1F304.23     
!   REVISED TO CONFORM WITH UM SOFTWARE STANDARDS, THIS VERSION RUNS       GIE1F304.24     
!   ON BOTH THE CRAY & HP WORKSTATIONS. IF THERE ARE > 200 DIFFERENT       GIE1F304.25     
!   SUBROUTINE CALLS TO TIMER, FINAL TABLE REPLACED BY WARNING MESSAGE.    GIE1F304.26     
!   ..................................................................     GIE1F304.27     
!   ---AUTHOR OF THIS REVISION IAN EDMOND                                  GIE1F304.28     
!   ---DATE 12/04/94                                                       GIE1F304.29     
!                                                                          GIE1F304.30     
!    Model            Modification history from model version 3.0:         GIE1F304.31     
!   version  Date                                                          GIE1F304.32     
CLL   4.1       12/03/96  Changes to avoid clashes with TIMER2A            GPB1F401.2      
CLL                       P.Burton                                         GPB1F401.3      
!LL   4.5       17/04/98  Modified to cope with action (I) > 100           GPB8F405.20     
!LL                       intended for MPP timer.       P.Burton           GPB8F405.21     
!  4.5  12/06/98  Use CLOCK(...,0,2) for CPUtime on Fujitsu.               GRB1F405.8      
!                                        RBarnes@ecmwf.int                 GRB1F405.9      
!                                                                          GIE1F304.33     
!   Programming standard :                                                 GIE1F304.34     
!                                                                          GIE1F304.35     
!   Logical components covered : D66                                       GIE1F304.36     
!                                                                          GIE1F304.37     
!   Project task :                                                         GIE1F304.38     
!                                                                          GIE1F304.39     
!   External documentation:                                                GIE1F304.40     
!                                                                          GIE1F304.41     
!  ---------------------------------------------------------------------   GIE1F304.42     
!                                                                          GIE1F304.43     
                                                                           TIMER1A.54     
       IMPLICIT NONE                                                       GIE1F304.44     
                                                                           TIMER1A.63     
       INTEGER KLIMIT                                                      GIE1F304.45     
       PARAMETER(KLIMIT=200)                                               GIE1F304.46     
       CHARACTER*8 SUB,SUBNAME(KLIMIT),RETURNAM(KLIMIT),SWORK              GIE1F304.47     
       INTEGER NENTER(KLIMIT),I,L,J,K,NSUBS,ISTOP,NCALLS,IWORK             GIE1F304.48     
       INTEGER ICALL                                                       PXTIMER1.4      
       REAL ELAPSE(KLIMIT),TOTE,ELPEND,ELPSTART,CPUSTART,TOT,AT,CPUEND     GIE1F304.49     
       REAL TOTELAP,AVELAP,PCENT,RWORK,TOTLAP,SPEEDUP,P,TIME(KLIMIT)       GIE1F304.50     
       REAL UWORK                                                          GIE1F304.51     
       SAVE SUBNAME,RETURNAM,NENTER,ELAPSE,TIME                            GIE1F304.52     
       SAVE K,J,NSUBS,ELPSTART,ISTOP,CPUSTART                              GIE1F304.53     
                                                                           GIE1F304.54     
       REAL SECOND                                                         GIE1F304.55     
*IF DEF,SGI                                                                PXTIMEFN.26     
      REAL (KIND=8) TIMEF                                                  PXTIMEFN.27     
*ENDIF                                                                     PXTIMEFN.28     
!      -----------------------------------------------------------------   GIE1F304.56     
       IF (I .GT. 100) THEN                                                PXTIMER1.5      
         ICALL=I-100                                                       PXTIMER1.6      
       ELSE                                                                PXTIMER1.7      
         ICALL=I                                                           PXTIMER1.8      
       ENDIF                                                               PXTIMER1.9      
       IF (ICALL.EQ.1) THEN                                                PXTIMER1.10     
                                                                           GIE1F304.58     
!      First call to timer from the main program                           GIE1F304.59     
!      Set up initial values of variables                                  GIE1F304.60     
                                                                           GIE1F304.61     
         K         = 1                                                     GIE1F304.62     
         J         = 0                                                     GIE1F304.63     
         ISTOP     = 0                                                     GIE1F304.64     
         NSUBS     = 1                                                     GIE1F304.65     
         SUBNAME(1)= SUB                                                   GIE1F304.66     
                                                                           GIE1F304.67     
         DO L=1,KLIMIT                                                     GIE1F304.68     
           ELAPSE(L) = 0.0                                                 GIE1F304.69     
           TIME(L) = 0.0                                                   GIE1F304.70     
           NENTER(L) = 0                                                   GIE1F304.71     
                                                                           TIMER1A.68     
         ENDDO                                                             GIE1F304.72     
                                                                           GIE1F304.73     
      NENTER(1)=1                                                          TIMER1A.69     
*IF -DEF,SGI                                                               PXTIMEFN.29     
      CALL TIMEF(ELPSTART)                                                 TIMER1A.70     
*ELSE                                                                      PXTIMEFN.30     
      ELPSTART=TIMEF()                                                     PXTIMEFN.31     
*ENDIF                                                                     PXTIMEFN.32     
*IF -DEF,FUJITSU                                                           GRB1F405.10     
         CPUSTART=SECOND(CPUSTART)                                         GIE1F304.74     
*ELSE                                                                      GRB1F405.11     
      CALL CLOCK(CPUSTART,0,2)                                             GRB1F405.12     
*ENDIF                                                                     GRB1F405.13     
                                                                           TIMER1A.73     
!      -----------------------------------------------------------------   GIE1F304.75     
       ELSEIF ((ICALL.EQ.2).AND.(ISTOP.EQ.0)) THEN                         PXTIMER1.11     
                                                                           TIMER1A.79     
!      Last call to timer from main program                                GIE1F304.77     
!      Print out table of results                                          GIE1F304.78     
                                                                           GIE1F304.79     
*IF -DEF,FUJITSU                                                           GRB1F405.14     
!        Stop timer                                                        GIE1F304.80     
*ELSE                                                                      GRB1F405.15     
      CALL CLOCK(CPUEND,0,2)                                               GRB1F405.16     
*ENDIF                                                                     GRB1F405.17     
      CPUEND=SECOND()                                                      TIMER1A.81     
*IF -DEF,SGI                                                               PXTIMEFN.33     
      CALL TIMEF(ELPEND)                                                   TIMER1A.82     
*ELSE                                                                      PXTIMEFN.34     
      ELPEND=TIMEF()                                                       PXTIMEFN.35     
*ENDIF                                                                     PXTIMEFN.36     
         ELAPSE(1)=ELAPSE(1)+(ELPEND-ELPSTART)*1.E-3                       GIE1F304.81     
         TIME(1)=TIME(1)+CPUEND-CPUSTART                                   GIE1F304.82     
                                                                           GIE1F304.83     
!        Calculate total time in program                                   GIE1F304.84     
         TOTE=0.0                                                          GIE1F304.85     
         TOT=0.0                                                           GIE1F304.86     
         DO K=1,NSUBS                                                      GIE1F304.87     
                                                                           GIE1F304.88     
           TOTE=TOTE+ELAPSE(K)                                             GIE1F304.89     
           TOT=TOT+TIME(K)                                                 GIE1F304.90     
                                                                           GIE1F304.91     
         ENDDO                                                             GIE1F304.92     
                                                                           GIE1F304.93     
!        Sort subroutines into time order                                  GIE1F304.94     
                                                                           GIE1F304.95     
         DO K=1,(NSUBS-1)                                                  GIE1F304.96     
                                                                           GIE1F304.97     
           DO J=(K+1),NSUBS                                                GIE1F304.98     
                                                                           GIE1F304.99     
             IF (TIME(J).GT.TIME(K)) THEN                                  GIE1F304.100    
                                                                           GIE1F304.101    
!              Swap the values:                                            GIE1F304.102    
               RWORK=TIME(K)                                               GIE1F304.103    
               TIME(K)=TIME(J)                                             GIE1F304.104    
               TIME(J)=RWORK                                               GIE1F304.105    
               UWORK=ELAPSE(K)                                             GIE1F304.106    
               ELAPSE(K)=ELAPSE(J)                                         GIE1F304.107    
               ELAPSE(J)=UWORK                                             GIE1F304.108    
               IWORK=NENTER(K)                                             GIE1F304.109    
               NENTER(K)=NENTER(J)                                         GIE1F304.110    
               NENTER(J)=IWORK                                             GIE1F304.111    
               SWORK=SUBNAME(K)                                            GIE1F304.112    
               SUBNAME(K)=SUBNAME(J)                                       GIE1F304.113    
               SUBNAME(J)=SWORK                                            GIE1F304.114    
                                                                           GIE1F304.115    
             ENDIF                                                         GIE1F304.116    
                                                                           GIE1F304.117    
           ENDDO                                                           GIE1F304.118    
                                                                           GIE1F304.119    
         ENDDO                                                             GIE1F304.120    
                                                                           GIE1F304.121    
                                                                           GIE1F304.122    
!        Output timing information                                         GIE1F304.123    
                                                                           GIE1F304.124    
                                                                           GIE1F304.125    
      WRITE(*,'(''1'',//,20X,'' FLOW TRACE SUMMARY'',/)')                  GIE1F304.126    
      WRITE(*,'(4X,''ROUTINE'',6X,''CPU'',6X,''%'',3X,                     GIE1F304.127    
     &  ''CALLS'',2X,''AVERAGE'',4X,''ELAPSE'',4X,''%''                    GIE1F304.128    
     &  ,6X,''AVERAGE'',1X,''CPU'')')                                      GIE1F304.129    
      WRITE(*,'(17X,''TIME'',4X,''CPU'',9X,''CPUTIME'',4X,                 GIE1F304.130    
     &  ''TIME'',3X,''ELAPSE'',4X,''ELAPSE'',2X,''SPEEDUP'')')             GIE1F304.131    
                                                                           GIE1F304.132    
         DO K=1,NSUBS                                                      GIE1F304.133    
                                                                           GIE1F304.134    
           SWORK=SUBNAME(K)                                                PXTIMER1.1      
           TOTLAP=TIME(K)                                                  GIE1F304.136    
           TOTELAP=ELAPSE(K)                                               GIE1F304.137    
           NCALLS=NENTER(K)                                                GIE1F304.138    
           AVELAP=TOTELAP/NCALLS                                           GIE1F304.139    
           P=100.0*TOTLAP/TOT                                              GIE1F304.140    
           PCENT=100.0*TOTELAP/TOTE                                        GIE1F304.141    
           AT=TIME(K)/NENTER(K)                                            GIE1F304.142    
           IF (AVELAP.EQ.0.0) THEN                                         GIE1F304.143    
             SPEEDUP=0.0                                                   GIE1F304.144    
           ELSE                                                            GIE1F304.145    
             SPEEDUP=AT/AVELAP                                             GIE1F304.146    
           ENDIF                                                           GIE1F304.147    
           WRITE(*,'(/,T1,I3,T5,A8,T13,F10.4,T25,F5.2,T30,                 GIE1F304.148    
     &       I5,T35,F10.4,T45,F10.4,T57,F5.2,T62,F10.4,T74,F5.2)')         GIE1F304.149    
     &       K,SWORK,TOTLAP,P,NENTER(K),AT,TOTELAP,PCENT,AVELAP,           PXTIMER1.2      
     &       SPEEDUP                                                       PXTIMER1.3      
                                                                           GIE1F304.151    
         ENDDO                                                             GIE1F304.152    
                                                                           GIE1F304.153    
         SPEEDUP=TOT/TOTE                                                  GIE1F304.154    
         WRITE(*,'(/,T3,''**TOTAL'',T12,F11.4,T44,F11.4,                   GIE1F304.155    
     &     T74,F5.2)')TOT,TOTE,SPEEDUP                                     GIE1F304.156    
                                                                           GIE1F304.157    
!      -----------------------------------------------------------------   GIE1F304.158    
       ELSEIF ((ICALL.EQ.3).AND.(ISTOP.EQ.0)) THEN                         PXTIMER1.12     
                                                                           GIE1F304.160    
!      First call in subroutine                                            GIE1F304.161    
                                                                           GIE1F304.162    
!        Switch off timer                                                  GIE1F304.163    
*IF -DEF,FUJITSU                                                           GRB1F405.18     
         CPUEND=SECOND()                                                   GIE1F304.164    
*ELSE                                                                      GRB1F405.19     
         CALL CLOCK(CPUEND,0,2)                                            GRB1F405.20     
*ENDIF                                                                     GRB1F405.21     
*IF -DEF,SGI                                                               PXTIMEFN.37     
         CALL TIMEF(ELPEND)                                                GIE1F304.165    
*ELSE                                                                      PXTIMEFN.38     
         ELPEND=TIMEF()                                                    PXTIMEFN.39     
*ENDIF                                                                     PXTIMEFN.40     
      ELAPSE(K)=ELAPSE(K)+(ELPEND-ELPSTART)*1.E-3                          TIMER1A.84     
         TIME(K)=TIME(K)+CPUEND-CPUSTART                                   GIE1F304.166    
                                                                           TIMER1A.85     
!        Save name of calling subroutine                                   GIE1F304.167    
      J=J+1                                                                TIMER1A.87     
      RETURNAM(J)=SUBNAME(K)                                               TIMER1A.88     
                                                                           TIMER1A.89     
!        Check subroutine name                                             GIE1F304.168    
         DO K=1,NSUBS                                                      GIE1F304.169    
                                                                           GIE1F304.170    
           IF (SUBNAME(K).EQ.SUB) GOTO 10                                  GIE1F304.171    
                                                                           GIE1F304.172    
         ENDDO                                                             GIE1F304.173    
                                                                           GIE1F304.174    
!        New subroutine entered                                            GIE1F304.175    
      NSUBS=NSUBS+1                                                        TIMER1A.95     
         IF (NSUBS .LE. KLIMIT) THEN                                       GIE1F304.176    
                                                                           GIE1F304.177    
      SUBNAME(NSUBS)=SUB                                                   TIMER1A.96     
      K=NSUBS                                                              TIMER1A.97     
                                                                           TIMER1A.99     
         ELSE                                                              GIE1F304.178    
                                                                           GIE1F304.179    
           WRITE(*,'(''WARNING: More than''I4                              GIE1F304.180    
     &       '' different subroutine calls to TIMER'')')KLIMIT             GIE1F304.181    
           ISTOP=1                                                         GIE1F304.182    
           GOTO 9999                                                       GIE1F304.183    
                                                                           GIE1F304.184    
         ENDIF                                                             GIE1F304.185    
                                                                           GIE1F304.186    
 10      CONTINUE                                                          GIE1F304.187    
                                                                           GIE1F304.188    
!        Start timer for subroutine                                        GIE1F304.189    
      NENTER(K)=NENTER(K)+1                                                TIMER1A.101    
*IF -DEF,SGI                                                               PXTIMEFN.41     
      CALL TIMEF(ELPSTART)                                                 TIMER1A.102    
*ELSE                                                                      PXTIMEFN.42     
      ELPSTART=TIMEF()                                                     PXTIMEFN.43     
*ENDIF                                                                     PXTIMEFN.44     
*IF -DEF,FUJITSU                                                           GRB1F405.22     
      CPUSTART=SECOND()                                                    TIMER1A.103    
*ELSE                                                                      GRB1F405.23     
      CALL CLOCK(CPUSTART,0,2)                                             GRB1F405.24     
*ENDIF                                                                     GRB1F405.25     
!      -----------------------------------------------------------------   GIE1F304.190    
       ELSEIF ((ICALL.EQ.4).AND.(ISTOP.EQ.0)) THEN                         PXTIMER1.13     
                                                                           TIMER1A.105    
!      Return from subroutine                                              GIE1F304.192    
                                                                           TIMER1A.111    
!        Stop timer                                                        GIE1F304.193    
*IF -DEF,FUJITSU                                                           GRB1F405.26     
      CPUEND=SECOND()                                                      TIMER1A.113    
*ELSE                                                                      GRB1F405.27     
      CALL CLOCK(CPUEND,0,2)                                               GRB1F405.28     
*ENDIF                                                                     GRB1F405.29     
*IF -DEF,SGI                                                               PXTIMEFN.45     
      CALL TIMEF(ELPEND)                                                   TIMER1A.114    
*ELSE                                                                      PXTIMEFN.46     
      ELPEND=TIMEF()                                                       PXTIMEFN.47     
*ENDIF                                                                     PXTIMEFN.48     
      ELAPSE(K)=ELAPSE(K)+(ELPEND-ELPSTART)*1.E-3                          TIMER1A.115    
      TIME(K)=TIME(K)+CPUEND-CPUSTART                                      TIMER1A.116    
                                                                           TIMER1A.117    
!        Find name of calling program                                      GIE1F304.194    
         DO K=1,NSUBS                                                      GIE1F304.195    
                                                                           GIE1F304.196    
           IF (SUBNAME(K).EQ.RETURNAM(J)) GOTO 11                          GIE1F304.197    
                                                                           GIE1F304.198    
         ENDDO                                                             GIE1F304.199    
                                                                           GIE1F304.200    
         WRITE(*,'(3X,''Calling prog:-'',1X,A8,1X,''not found              GIE1F304.201    
     &     ,now in'',1X,A8/3X,''TIMER being DISABLED for the rest          GIE1F304.202    
     &     of this run'')')RETURNAM(J),SUBNAME(J+1)                        GIE1F304.203    
      ISTOP=1                                                              TIMER1A.125    
         GOTO 9999                                                         GIE1F304.204    
 11      CONTINUE                                                          GIE1F304.205    
                                                                           TIMER1A.128    
!        Start timer for calling program                                   GIE1F304.206    
*IF -DEF,SGI                                                               PXTIMEFN.49     
      CALL TIMEF(ELPSTART)                                                 TIMER1A.130    
*ELSE                                                                      PXTIMEFN.50     
      ELPSTART=TIMEF()                                                     PXTIMEFN.51     
*ENDIF                                                                     PXTIMEFN.52     
*IF -DEF,FUJITSU                                                           GRB1F405.30     
      CPUSTART=SECOND()                                                    TIMER1A.131    
*ELSE                                                                      GRB1F405.31     
      CALL CLOCK(CPUSTART,0,2)                                             GRB1F405.32     
*ENDIF                                                                     GRB1F405.33     
      J=J-1                                                                TIMER1A.132    
                                                                           TIMER1A.134    
!      -----------------------------------------------------------------   GIE1F304.207    
       ELSEIF ((ICALL.LT.1).OR.(ICALL.GT.6)) THEN                          PXTIMER1.14     
                                                                           GPB1F401.5      
!      If ICALL<1 or ICALL>6 then there is an error.                       PXTIMER1.15     
!      If 4<ICALL<=6 then this call                                        PXTIMER1.16     
!      to TIMER is ignored. These values of I are recognised by the        GPB1F401.7      
!      TIMER3A version.                                                    GPB1F401.8      
                                                                           TIMER1A.147    
         WRITE(*,'(3X,                                                     GIE1F304.210    
     &     ''Illegal call to TIMER by subroutine'',1X,A8)')SUB             GIE1F304.211    
                                                                           TIMER1A.150    
       ENDIF                                                               GIE1F304.212    
                                                                           TIMER1A.159    
 9999    CONTINUE                                                          GIE1F304.213    
                                                                           TIMER1A.165    
       RETURN                                                              GIE1F304.214    
       END                                                                 GIE1F304.215    
                                                                           TIMER1A.178    
                                                                           GIE1F304.216    
*ENDIF                                                                     TIMER1A.186