New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
Changeset 8882 for branches/2017/dev_CNRS_2017/NEMOGCM/NEMO/OPA_SRC/DIA/diacfl.F90 – NEMO

Ignore:
Timestamp:
2017-12-01T18:44:09+01:00 (6 years ago)
Author:
flavoni
Message:

dev_CNRS_2017 branch: merged dev_r7881_ENHANCE09_RK3 with trunk r8864

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2017/dev_CNRS_2017/NEMOGCM/NEMO/OPA_SRC/DIA/diacfl.F90

    r8329 r8882  
    11MODULE diacfl 
    2    !!============================================================================== 
     2   !!====================================================================== 
    33   !!                       ***  MODULE  diacfl  *** 
    44   !! Output CFL diagnostics to ascii file 
    5    !!============================================================================== 
    6    !! History :  1.0  !  2010-03  (E. Blockley)  Original code 
    7    !!                 !  2014-06  (T Graham) Removed CPP key & Updated to vn3.6 
    8    !!  
     5   !!====================================================================== 
     6   !! History :  3.4  !  2010-03  (E. Blockley)  Original code 
     7   !!            3.6  !  2014-06  (T. Graham) Removed CPP key & Updated to vn3.6 
     8   !!            4.0  !  2017-09  (G. Madec)  style + comments 
    99   !!---------------------------------------------------------------------- 
    1010   !!   dia_cfl        : Compute and output Courant numbers at each timestep 
     
    1212   USE oce             ! ocean dynamics and active tracers 
    1313   USE dom_oce         ! ocean space and time domain 
     14   USE domvvl          !  
     15   ! 
    1416   USE lib_mpp         ! distribued memory computing 
    1517   USE lbclnk          ! ocean lateral boundary condition (or mpp link) 
    1618   USE in_out_manager  ! I/O manager 
    17    USE domvvl      
    1819   USE timing          ! Performance output 
    1920 
     
    2122   PRIVATE 
    2223 
    23    REAL(wp) :: cu_max, cv_max, cw_max                      ! Run max U Courant number  
    24    INTEGER, DIMENSION(3) :: cu_loc, cv_loc, cw_loc         ! Run max locations 
    25    REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:,:) :: zcu_cfl           ! Courant number arrays 
    26    REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:,:) :: zcv_cfl           ! Courant number arrays 
    27    REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:,:) :: zcw_cfl           ! Courant number arrays 
     24   CHARACTER(LEN=50) :: clname="cfl_diagnostics.ascii"    ! ascii filename 
     25   INTEGER           :: numcfl                            ! outfile unit 
     26   ! 
     27   INTEGER, DIMENSION(3) ::   nCu_loc, nCv_loc, nCw_loc   ! U, V, and W run max locations in the global domain 
     28   REAL(wp)              ::   rCu_max, rCv_max, rCw_max   ! associated run max Courant number  
    2829 
    29    INTEGER  :: numcfl                                       ! outfile unit 
    30    CHARACTER(LEN=50) :: clname="cfl_diagnostics.ascii"      ! ascii filename 
     30!!gm CAUTION: need to declare these arrays here, otherwise the calculation fails in multi-proc ! 
     31!!gm          I don't understand why. 
     32   REAL(wp), ALLOCATABLE, DIMENSION(:,:,:) ::   zCu_cfl, zCv_cfl, zCw_cfl         ! workspace 
     33!!gm end 
    3134 
    3235   PUBLIC   dia_cfl       ! routine called by step.F90 
     
    4043   !! Software governed by the CeCILL licence (modipsl/doc/NEMO_CeCILL.txt) 
    4144   !!---------------------------------------------------------------------- 
    42  
    43  
    4445CONTAINS 
    45  
    4646 
    4747   SUBROUTINE dia_cfl ( kt ) 
     
    5252      !!               and output to ascii file 'cfl_diagnostics.ascii' 
    5353      !!---------------------------------------------------------------------- 
     54      INTEGER, INTENT(in) ::   kt   ! ocean time-step index 
     55      ! 
     56      INTEGER :: ji, jj, jk   ! dummy loop indices 
     57      REAL(wp)::   z2dt, zCu_max, zCv_max, zCw_max       ! local scalars 
     58      INTEGER , DIMENSION(3)           ::   iloc_u , iloc_v , iloc_w , iloc   ! workspace 
     59!!gm this does not work      REAL(wp), DIMENSION(jpi,jpj,jpk) ::   zCu_cfl, zCv_cfl, zCw_cfl         ! workspace 
     60      !!---------------------------------------------------------------------- 
     61      ! 
     62      IF( nn_timing == 1 )   CALL timing_start('dia_cfl') 
     63      ! 
     64      !                       ! setup timestep multiplier to account for initial Eulerian timestep 
     65      IF( neuler == 0 .AND. kt == nit000 ) THEN   ;    z2dt = rdt 
     66      ELSE                                        ;    z2dt = rdt * 2._wp 
     67      ENDIF 
     68      ! 
     69      !                 
     70      DO jk = 1, jpk       ! calculate Courant numbers 
     71         DO jj = 1, jpj 
     72            DO ji = 1, fs_jpim1   ! vector opt. 
     73               zCu_cfl(ji,jj,jk) = ABS( un(ji,jj,jk) ) * z2dt / e1u  (ji,jj)      ! for i-direction 
     74               zCv_cfl(ji,jj,jk) = ABS( vn(ji,jj,jk) ) * z2dt / e2v  (ji,jj)      ! for j-direction 
     75               zCw_cfl(ji,jj,jk) = ABS( wn(ji,jj,jk) ) * z2dt / e3w_n(ji,jj,jk)   ! for k-direction 
     76            END DO 
     77         END DO          
     78      END DO 
     79      ! 
     80      !                    ! calculate maximum values and locations 
     81      IF( lk_mpp ) THEN 
     82         CALL mpp_maxloc( zCu_cfl, umask, zCu_max, iloc_u(1), iloc_u(2), iloc_u(3) ) 
     83         CALL mpp_maxloc( zCv_cfl, vmask, zCv_max, iloc_v(1), iloc_v(2), iloc_v(3) ) 
     84         CALL mpp_maxloc( zCw_cfl, wmask, zCw_max, iloc_w(1), iloc_w(2), iloc_w(3) ) 
     85      ELSE 
     86         iloc = MAXLOC( ABS( zcu_cfl(:,:,:) ) ) 
     87         iloc_u(1) = iloc(1) + nimpp - 1 
     88         iloc_u(2) = iloc(2) + njmpp - 1 
     89         iloc_u(3) = iloc(3) 
     90         zCu_max = zCu_cfl(iloc(1),iloc(2),iloc(3)) 
     91         ! 
     92         iloc = MAXLOC( ABS( zcv_cfl(:,:,:) ) ) 
     93         iloc_v(1) = iloc(1) + nimpp - 1 
     94         iloc_v(2) = iloc(2) + njmpp - 1 
     95         iloc_v(3) = iloc(3) 
     96         zCv_max = zCv_cfl(iloc(1),iloc(2),iloc(3)) 
     97         ! 
     98         iloc = MAXLOC( ABS( zcw_cfl(:,:,:) ) ) 
     99         iloc_w(1) = iloc(1) + nimpp - 1 
     100         iloc_w(2) = iloc(2) + njmpp - 1 
     101         iloc_w(3) = iloc(3) 
     102         zCw_max = zCw_cfl(iloc(1),iloc(2),iloc(3)) 
     103      ENDIF 
     104      ! 
     105      !                    ! write out to file 
     106      IF( lwp ) THEN 
     107         WRITE(numcfl,FMT='(2x,i4,5x,a6,5x,f6.4,1x,i4,1x,i4,1x,i4)') kt, 'Max Cu', zCu_max, iloc_u(1), iloc_u(2), iloc_u(3) 
     108         WRITE(numcfl,FMT='(11x,     a6,5x,f6.4,1x,i4,1x,i4,1x,i4)')     'Max Cv', zCv_max, iloc_v(1), iloc_v(2), iloc_v(3) 
     109         WRITE(numcfl,FMT='(11x,     a6,5x,f6.4,1x,i4,1x,i4,1x,i4)')     'Max Cw', zCw_max, iloc_w(1), iloc_w(2), iloc_w(3) 
     110      ENDIF 
     111      ! 
     112      !                    ! update maximum Courant numbers from whole run if applicable 
     113      IF( zCu_max > rCu_max ) THEN   ;   rCu_max = zCu_max   ;   nCu_loc(:) = iloc_u(:)   ;   ENDIF 
     114      IF( zCv_max > rCv_max ) THEN   ;   rCv_max = zCv_max   ;   nCv_loc(:) = iloc_v(:)   ;   ENDIF 
     115      IF( zCw_max > rCw_max ) THEN   ;   rCw_max = zCw_max   ;   nCw_loc(:) = iloc_w(:)   ;   ENDIF 
    54116 
    55       INTEGER, INTENT(in) ::  kt                            ! ocean time-step index 
     117      !                    ! at end of run output max Cu and Cv and close ascii file 
     118      IF( kt == nitend .AND. lwp ) THEN 
     119         ! to ascii file 
     120         WRITE(numcfl,*) '******************************************' 
     121         WRITE(numcfl,FMT='(3x,a12,7x,f6.4,1x,i4,1x,i4,1x,i4)') 'Run Max Cu', rCu_max, nCu_loc(1), nCu_loc(2), nCu_loc(3) 
     122         WRITE(numcfl,FMT='(3x,a8,11x,f15.1)') ' => dt/C', z2dt/rCu_max 
     123         WRITE(numcfl,*) '******************************************' 
     124         WRITE(numcfl,FMT='(3x,a12,7x,f6.4,1x,i4,1x,i4,1x,i4)') 'Run Max Cv', rCv_max, nCv_loc(1), nCv_loc(2), nCv_loc(3) 
     125         WRITE(numcfl,FMT='(3x,a8,11x,f15.1)') ' => dt/C', z2dt/rCv_max 
     126         WRITE(numcfl,*) '******************************************' 
     127         WRITE(numcfl,FMT='(3x,a12,7x,f6.4,1x,i4,1x,i4,1x,i4)') 'Run Max Cw', rCw_max, nCw_loc(1), nCw_loc(2), nCw_loc(3) 
     128         WRITE(numcfl,FMT='(3x,a8,11x,f15.1)') ' => dt/C', z2dt/rCw_max 
     129         CLOSE( numcfl )  
     130         ! 
     131         ! to ocean output 
     132         WRITE(numout,*) 
     133         WRITE(numout,*) 'dia_cfl : Maximum Courant number information for the run ' 
     134         WRITE(numout,*) '~~~~~~~' 
     135         WRITE(numout,*) '   Max Cu = ', rCu_max, ' at (i,j,k) = (',nCu_loc(1),nCu_loc(2),nCu_loc(3),') => dt/C = ', z2dt/rCu_max 
     136         WRITE(numout,*) '   Max Cv = ', rCv_max, ' at (i,j,k) = (',nCv_loc(1),nCv_loc(2),nCv_loc(3),') => dt/C = ', z2dt/rCv_max 
     137         WRITE(numout,*) '   Max Cw = ', rCw_max, ' at (i,j,k) = (',nCw_loc(1),nCw_loc(2),nCw_loc(3),') => dt/C = ', z2dt/rCw_max 
     138      ENDIF 
     139      ! 
     140      IF( nn_timing == 1 )   CALL timing_stop('dia_cfl') 
     141      ! 
     142   END SUBROUTINE dia_cfl 
    56143 
    57       REAL(wp) :: zcu_max, zcv_max, zcw_max                 ! max Courant numbers per timestep 
    58       INTEGER, DIMENSION(3) :: zcu_loc, zcv_loc, zcw_loc    ! max Courant number locations 
    59  
    60       REAL(wp) :: dt                                        ! temporary scalars 
    61       INTEGER, DIMENSION(3) :: zlocu, zlocv, zlocw          ! temporary arrays  
    62       INTEGER  :: ji, jj, jk                                ! dummy loop indices 
    63  
    64        
    65       IF( nn_diacfl == 1) THEN 
    66          IF( nn_timing == 1 )   CALL timing_start('dia_cfl') 
    67          ! setup timestep multiplier to account for initial Eulerian timestep 
    68          IF( neuler == 0 .AND. kt == nit000 ) THEN   ;    dt = rdt 
    69          ELSE                                        ;    dt = rdt * 2.0 
    70          ENDIF 
    71  
    72              ! calculate Courant numbers 
    73          DO jk = 1, jpk 
    74             DO jj = 1, jpj 
    75                DO ji = 1, fs_jpim1   ! vector opt. 
    76  
    77                   ! Courant number for x-direction (zonal current) 
    78                   zcu_cfl(ji,jj,jk) = ABS(un(ji,jj,jk))*dt/e1u(ji,jj) 
    79  
    80                   ! Courant number for y-direction (meridional current) 
    81                   zcv_cfl(ji,jj,jk) = ABS(vn(ji,jj,jk))*dt/e2v(ji,jj) 
    82  
    83                   ! Courant number for z-direction (vertical current) 
    84                   zcw_cfl(ji,jj,jk) = ABS(wn(ji,jj,jk))*dt/e3w_n(ji,jj,jk) 
    85                END DO 
    86             END DO          
    87          END DO 
    88  
    89          ! calculate maximum values and locations 
    90          IF( lk_mpp ) THEN 
    91             CALL mpp_maxloc(zcu_cfl,umask,zcu_max, zcu_loc(1), zcu_loc(2), zcu_loc(3)) 
    92             CALL mpp_maxloc(zcv_cfl,vmask,zcv_max, zcv_loc(1), zcv_loc(2), zcv_loc(3)) 
    93             CALL mpp_maxloc(zcw_cfl,tmask,zcw_max, zcw_loc(1), zcw_loc(2), zcw_loc(3)) 
    94          ELSE 
    95             zlocu = MAXLOC( ABS( zcu_cfl(:,:,:) ) ) 
    96             zcu_loc(1) = zlocu(1) + nimpp - 1 
    97             zcu_loc(2) = zlocu(2) + njmpp - 1 
    98             zcu_loc(3) = zlocu(3) 
    99             zcu_max = zcu_cfl(zcu_loc(1),zcu_loc(2),zcu_loc(3)) 
    100  
    101             zlocv = MAXLOC( ABS( zcv_cfl(:,:,:) ) ) 
    102             zcv_loc(1) = zlocv(1) + nimpp - 1 
    103             zcv_loc(2) = zlocv(2) + njmpp - 1 
    104             zcv_loc(3) = zlocv(3) 
    105             zcv_max = zcv_cfl(zcv_loc(1),zcv_loc(2),zcv_loc(3)) 
    106  
    107             zlocw = MAXLOC( ABS( zcw_cfl(:,:,:) ) ) 
    108             zcw_loc(1) = zlocw(1) + nimpp - 1 
    109             zcw_loc(2) = zlocw(2) + njmpp - 1 
    110             zcw_loc(3) = zlocw(3) 
    111             zcw_max = zcw_cfl(zcw_loc(1),zcw_loc(2),zcw_loc(3)) 
    112          ENDIF 
    113        
    114          ! write out to file 
    115          IF( lwp ) THEN 
    116             WRITE(numcfl,FMT='(2x,i4,5x,a6,5x,f6.4,1x,i4,1x,i4,1x,i4)') kt, 'Max Cu', zcu_max, zcu_loc(1), zcu_loc(2), zcu_loc(3) 
    117             WRITE(numcfl,FMT='(11x,a6,5x,f6.4,1x,i4,1x,i4,1x,i4)') 'Max Cv', zcv_max, zcv_loc(1), zcv_loc(2), zcv_loc(3) 
    118             WRITE(numcfl,FMT='(11x,a6,5x,f6.4,1x,i4,1x,i4,1x,i4)') 'Max Cw', zcw_max, zcw_loc(1), zcw_loc(2), zcw_loc(3) 
    119          ENDIF 
    120  
    121          ! update maximum Courant numbers from whole run if applicable 
    122          IF( zcu_max > cu_max ) THEN 
    123             cu_max = zcu_max 
    124             cu_loc = zcu_loc 
    125          ENDIF 
    126          IF( zcv_max > cv_max ) THEN 
    127             cv_max = zcv_max 
    128             cv_loc = zcv_loc 
    129          ENDIF 
    130          IF( zcw_max > cw_max ) THEN 
    131             cw_max = zcw_max 
    132             cw_loc = zcw_loc 
    133          ENDIF 
    134  
    135          ! at end of run output max Cu and Cv and close ascii file 
    136          IF( kt == nitend .AND. lwp ) THEN 
    137             ! to ascii file 
    138             WRITE(numcfl,*) '******************************************' 
    139             WRITE(numcfl,FMT='(3x,a12,7x,f6.4,1x,i4,1x,i4,1x,i4)') 'Run Max Cu', cu_max, cu_loc(1), cu_loc(2), cu_loc(3) 
    140             WRITE(numcfl,FMT='(3x,a8,11x,f7.1)') ' => dt/C', dt*(1.0/cu_max) 
    141             WRITE(numcfl,*) '******************************************' 
    142             WRITE(numcfl,FMT='(3x,a12,7x,f6.4,1x,i4,1x,i4,1x,i4)') 'Run Max Cv', cv_max, cv_loc(1), cv_loc(2), cv_loc(3) 
    143             WRITE(numcfl,FMT='(3x,a8,11x,f7.1)') ' => dt/C', dt*(1.0/cv_max) 
    144             WRITE(numcfl,*) '******************************************' 
    145             WRITE(numcfl,FMT='(3x,a12,7x,f6.4,1x,i4,1x,i4,1x,i4)') 'Run Max Cw', cw_max, cw_loc(1), cw_loc(2), cw_loc(3) 
    146             WRITE(numcfl,FMT='(3x,a8,11x,f7.1)') ' => dt/C', dt*(1.0/cw_max) 
    147             CLOSE( numcfl )  
    148  
    149             ! to ocean output 
    150             WRITE(numout,*) 
    151             WRITE(numout,*) 'dia_cfl     : Maximum Courant number information for the run:' 
    152             WRITE(numout,*) '~~~~~~~~~~~~' 
    153             WRITE(numout,FMT='(12x,a12,7x,f6.4,5x,a16,i4,1x,i4,1x,i4,a1)') 'Run Max Cu', cu_max, 'at (i, j, k) =   & 
    154                           &   (', cu_loc(1), cu_loc(2), cu_loc(3), ')' 
    155             WRITE(numout,FMT='(12x,a8,11x,f7.1)') ' => dt/C', dt*(1.0/cu_max) 
    156             WRITE(numout,FMT='(12x,a12,7x,f6.4,5x,a16,i4,1x,i4,1x,i4,a1)') 'Run Max Cv', cv_max, 'at (i, j, k) =   & 
    157                           &   (', cv_loc(1), cv_loc(2), cv_loc(3), ')' 
    158             WRITE(numout,FMT='(12x,a8,11x,f7.1)') ' => dt/C', dt*(1.0/cv_max) 
    159             WRITE(numout,FMT='(12x,a12,7x,f6.4,5x,a16,i4,1x,i4,1x,i4,a1)') 'Run Max Cw', cw_max, 'at (i, j, k) =   & 
    160                           &   (', cw_loc(1), cw_loc(2), cw_loc(3), ')' 
    161             WRITE(numout,FMT='(12x,a8,11x,f7.1)') ' => dt/C', dt*(1.0/cw_max) 
    162  
    163          ENDIF 
    164  
    165          IF( nn_timing == 1 )   CALL timing_stop('dia_cfl') 
    166       ENDIF 
    167  
    168    END SUBROUTINE dia_cfl 
    169144 
    170145   SUBROUTINE dia_cfl_init 
     
    174149      !! ** Purpose :   create output file, initialise arrays 
    175150      !!---------------------------------------------------------------------- 
    176  
    177  
    178       IF( nn_diacfl == 1 ) THEN 
    179          IF( nn_timing == 1 )   CALL timing_start('dia_cfl_init') 
    180  
    181          cu_max=0.0 
    182          cv_max=0.0 
    183          cw_max=0.0 
    184  
    185          ALLOCATE( zcu_cfl(jpi, jpj, jpk), zcv_cfl(jpi, jpj, jpk), zcw_cfl(jpi, jpj, jpk) ) 
    186  
    187          zcu_cfl(:,:,:)=0.0 
    188          zcv_cfl(:,:,:)=0.0 
    189          zcw_cfl(:,:,:)=0.0 
    190  
    191          IF( lwp ) THEN 
    192             WRITE(numout,*) 
    193             WRITE(numout,*) 'dia_cfl     : Outputting CFL diagnostics to '//TRIM(clname) 
    194             WRITE(numout,*) '~~~~~~~~~~~~' 
    195             WRITE(numout,*) 
    196  
    197             ! create output ascii file 
    198             CALL ctl_opn( numcfl, clname, 'UNKNOWN', 'FORMATTED', 'SEQUENTIAL', 1, numout, lwp, 1 ) 
    199             WRITE(numcfl,*) 'Timestep  Direction  Max C     i    j    k' 
    200             WRITE(numcfl,*) '******************************************' 
    201          ENDIF 
    202  
    203          IF( nn_timing == 1 )   CALL timing_stop('dia_cfl_init') 
    204  
     151      ! 
     152      IF(lwp) THEN 
     153         WRITE(numout,*) 
     154         WRITE(numout,*) 'dia_cfl : Outputting CFL diagnostics to ',TRIM(clname), ' file' 
     155         WRITE(numout,*) '~~~~~~~' 
     156         WRITE(numout,*) 
     157         ! 
     158         ! create output ascii file 
     159         CALL ctl_opn( numcfl, clname, 'UNKNOWN', 'FORMATTED', 'SEQUENTIAL', 1, numout, lwp, 1 ) 
     160         WRITE(numcfl,*) 'Timestep  Direction  Max C     i    j    k' 
     161         WRITE(numcfl,*) '******************************************' 
    205162      ENDIF 
    206  
     163      ! 
     164      rCu_max = 0._wp 
     165      rCv_max = 0._wp 
     166      rCw_max = 0._wp 
     167      ! 
     168!!gm required to work 
     169      ALLOCATE ( zCu_cfl(jpi,jpj,jpk), zCv_cfl(jpi,jpj,jpk), zCw_cfl(jpi,jpj,jpk) ) 
     170!!gm end 
     171      !       
    207172   END SUBROUTINE dia_cfl_init 
    208173 
     174   !!====================================================================== 
    209175END MODULE diacfl 
Note: See TracChangeset for help on using the changeset viewer.