LCOV - code coverage report
Current view: top level - dynamics/fv - ctem.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 13 235 5.5 %
Date: 2025-03-14 01:21:06 Functions: 2 3 66.7 %

          Line data    Source code
       1             : !-----------------------------------------------------------------------------
       2             : ! circulation diagnostics -- terms of the Transformed Eulerian Mean (TEM) equation
       3             : !-----------------------------------------------------------------------------
       4             : module ctem
       5             : 
       6             :   use shr_kind_mod, only: r8 => shr_kind_r8
       7             :   use spmd_utils,   only: masterproc
       8             :   use pmgrid,       only: plon, plev, plevp
       9             :   use cam_logfile,  only: iulog
      10             :   use cam_history,  only: addfld, outfld, add_default, horiz_only
      11             :   use cam_abortutils, only: endrun
      12             : 
      13             :   implicit none
      14             :   private
      15             :   
      16             :   public :: ctem_readnl
      17             :   public :: ctem_init
      18             :   public :: ctem_diags
      19             :   public :: do_circulation_diags
      20             : 
      21             :   real(r8) :: rplon
      22             :   real(r8) :: iref_p(plevp)              ! interface reference pressure for vertical interpolation
      23             :   integer  :: ip_b                       ! level index where hybrid levels become purely pressure
      24             :   integer  :: zm_limit
      25             : 
      26             :   logical :: do_circulation_diags = .false.
      27             : 
      28             : contains
      29             : 
      30             : !================================================================================
      31             : 
      32           0 :   subroutine ctem_diags( u3, v3, omga, pt, h2o, ps, pe, grid)
      33             : 
      34             :     use physconst, only              : zvir, cappa
      35             :     use dynamics_vars, only          : T_FVDYCORE_GRID
      36             :     use hycoef, only                 : ps0
      37             :     use interpolate_data, only       : vertinterp
      38             : #ifdef SPMD
      39             :     use mpishorthand,       only     : mpilog, mpiint
      40             :     use parutilitiesmodule, only     : pargatherint
      41             : #endif
      42             : 
      43             : !-------------------------------------------------------------
      44             : !       ... dummy arguments
      45             : !-------------------------------------------------------------
      46             :     type(T_FVDYCORE_GRID), intent(in) :: grid                        ! FV Dynamics grid
      47             : 
      48             :     real(r8), intent(in)  :: ps(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy)         ! surface pressure (pa)
      49             :     real(r8), intent(in)  :: u3(grid%ifirstxy:grid%ilastxy,plev,grid%jfirstxy:grid%jlastxy)    ! zonal velocity (m/s)
      50             :     real(r8), intent(in)  :: v3(grid%ifirstxy:grid%ilastxy,plev,grid%jfirstxy:grid%jlastxy)    ! meridional velocity (m/s)
      51             :     real(r8), intent(in)  :: omga(grid%ifirstxy:grid%ilastxy,plev,grid%jfirstxy:grid%jlastxy)  ! pressure velocity
      52             :     real(r8), intent(in)  :: pe(grid%ifirstxy:grid%ilastxy,plevp,grid%jfirstxy:grid%jlastxy)   ! interface pressure (pa)
      53             :     real(r8), intent(in)  :: pt(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy,plev)    ! virtual temperature
      54             :     real(r8), intent(in)  :: h2o(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy,plev)   ! water constituent (kg/kg)
      55             : 
      56             : !-------------------------------------------------------------
      57             : !       ... local variables
      58             : !-------------------------------------------------------------
      59             :     real(r8), parameter :: hscale = 7000._r8          ! pressure scale height
      60             :     real(r8), parameter :: navp   = 1.e35_r8
      61             :     
      62             :     real(r8) :: pinterp
      63           0 :     real(r8) :: w(grid%ifirstxy:grid%ilastxy,plev,grid%jfirstxy:grid%jlastxy)          ! vertical velocity
      64           0 :     real(r8) :: th(grid%ifirstxy:grid%ilastxy,plev,grid%jfirstxy:grid%jlastxy)         ! pot. temperature
      65             : 
      66           0 :     real(r8) :: pm(grid%ifirstxy:grid%ilastxy,plev,grid%jfirstxy:grid%jlastxy)         ! mid-point pressure
      67             : 
      68             :     real(r8) :: pexf     ! Exner function
      69             :     real(r8) :: psurf
      70             : 
      71           0 :     real(r8) :: ui(grid%ifirstxy:grid%ilastxy,plevp)         ! interpolated zonal velocity
      72           0 :     real(r8) :: vi(grid%ifirstxy:grid%ilastxy,plevp)         ! interpolated meridional velocity
      73           0 :     real(r8) :: wi(grid%ifirstxy:grid%ilastxy,plevp)         ! interpolated vertical velocity
      74           0 :     real(r8) :: thi(grid%ifirstxy:grid%ilastxy,plevp)        ! interpolated pot. temperature
      75             :     
      76             :     real(r8) :: um(plevp)                                    ! zonal mean zonal velocity
      77             :     real(r8) :: vm(plevp)                                    ! zonal mean meridional velocity
      78             :     real(r8) :: wm(plevp)                                    ! zonal mean vertical velocity
      79             :     real(r8) :: thm(plevp)                                   ! zonal mean pot. temperature
      80             : 
      81           0 :     real(r8) :: ud(grid%ifirstxy:grid%ilastxy,plevp)         ! zonal deviation of zonal velocity
      82           0 :     real(r8) :: vd(grid%ifirstxy:grid%ilastxy,plevp)         ! zonal deviation of meridional velocity
      83           0 :     real(r8) :: wd(grid%ifirstxy:grid%ilastxy,plevp)         ! zonal deviation of vertical velocity
      84           0 :     real(r8) :: thd(grid%ifirstxy:grid%ilastxy,plevp)        ! zonal deviation of pot. temperature
      85             : 
      86           0 :     real(r8) :: vthp(grid%ifirstxy:grid%ilastxy,plevp)       ! zonal deviation of zonal velocity
      87           0 :     real(r8) :: wthp(grid%ifirstxy:grid%ilastxy,plevp)       ! zonal deviation of meridional velocity
      88           0 :     real(r8) :: uvp(grid%ifirstxy:grid%ilastxy,plevp)        ! zonal deviation of vertical velocity
      89           0 :     real(r8) :: uwp(grid%ifirstxy:grid%ilastxy,plevp)        ! zonal deviation of pot. temperature
      90             : 
      91             :     real(r8) :: rdiv(plevp)
      92             :     
      93           0 :     integer  :: ip_gm1g(plon,grid%jfirstxy:grid%jlastxy)     ! contains level index-1 where blocked points begin
      94             :     integer  :: zm_cnt(plevp)                                ! counter
      95             :     integer  :: i,j,k
      96             :     integer  :: nlons
      97             : 
      98           0 :     logical  :: has_zm(plevp,grid%jfirstxy:grid%jlastxy)                   ! .true. the (z,y) point is a valid zonal mean 
      99           0 :     integer  :: ip_gm1(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy) ! contains level index-1 where blocked points begin
     100             : 
     101           0 :     real(r8) :: vth(plevp,grid%jfirstxy:grid%jlastxy)                ! VTH flux
     102           0 :     real(r8) :: uv(plevp,grid%jfirstxy:grid%jlastxy)                 ! UV flux
     103           0 :     real(r8) :: wth(plevp,grid%jfirstxy:grid%jlastxy)                ! WTH flux
     104           0 :     real(r8) :: uw(plevp,grid%jfirstxy:grid%jlastxy)                 ! UW flux
     105           0 :     real(r8) :: u2d(plevp,grid%jfirstxy:grid%jlastxy)                ! zonally averaged U
     106           0 :     real(r8) :: v2d(plevp,grid%jfirstxy:grid%jlastxy)                ! zonally averaged V
     107           0 :     real(r8) :: th2d(plevp,grid%jfirstxy:grid%jlastxy)               ! zonally averaged TH
     108           0 :     real(r8) :: w2d(plevp,grid%jfirstxy:grid%jlastxy)                ! zonally averaged W
     109           0 :     real(r8) :: thig(grid%ifirstxy:grid%ilastxy,plevp,grid%jfirstxy:grid%jlastxy) ! interpolated pot. temperature
     110             : 
     111           0 :     real(r8) :: tmp2(grid%ifirstxy:grid%ilastxy)  
     112           0 :     real(r8) :: tmp3(grid%ifirstxy:grid%ilastxy,plevp)  
     113             : 
     114             :     integer :: beglat, endlat                          ! begin,end latitude indicies
     115             :     integer :: beglon, endlon                          ! begin,end longitude indicies
     116             : 
     117           0 :     beglon = grid%ifirstxy
     118           0 :     endlon = grid%ilastxy
     119           0 :     beglat = grid%jfirstxy
     120           0 :     endlat = grid%jlastxy
     121             : 
     122             : !omp parallel do private (i,j,k,pexf,psurf)
     123             : lat_loop1 : &
     124           0 :     do j = beglat, endlat
     125           0 :        do k = 1, plev
     126           0 :           do i = beglon, endlon
     127             : !-------------------------------------------------------------
     128             : ! Calculate pressure and Exner function
     129             : !-------------------------------------------------------------
     130           0 :              pm(i,k,j) = 0.5_r8 * ( pe(i,k,j) + pe(i,k+1,j) )
     131           0 :              pexf      = (ps0 / pm(i,k,j))**cappa
     132             : !-------------------------------------------------------------
     133             : ! Convert virtual temperature to temperature and calculate potential temperature
     134             : !-------------------------------------------------------------
     135           0 :              th(i,k,j) = pt(i,j,k) / (1._r8 + zvir*h2o(i,j,k)) 
     136           0 :              th(i,k,j) = th(i,k,j) * pexf
     137             : !-------------------------------------------------------------
     138             : ! Calculate vertical velocity
     139             : !-------------------------------------------------------------
     140           0 :              w(i,k,j)  = - hscale * omga(i,k,j) / pm(i,k,j)
     141             :           end do
     142             :        end do
     143             : !-------------------------------------------------------------
     144             : ! Keep track of where the bottom is in each column 
     145             : ! (i.e., largest index for which P(k) <= PS)
     146             : !-------------------------------------------------------------
     147           0 :        ip_gm1(:,j) = plevp
     148           0 :        do i = beglon, endlon
     149           0 :           psurf = ps(i,j)
     150           0 :           do k = ip_b+1, plevp
     151           0 :              if( iref_p(k) <= psurf ) then
     152           0 :                 ip_gm1(i,j) = k
     153             :              end if
     154             :           end do
     155             :        end do
     156             :     end do lat_loop1
     157             : 
     158           0 :     nlons = endlon - beglon + 1
     159             : 
     160             : #ifdef SPMD    
     161           0 :     if( grid%twod_decomp == 1 ) then
     162           0 :        if (grid%iam .lt. grid%npes_xy) then
     163           0 :           call pargatherint( grid%commxy_x, 0, ip_gm1, grid%strip2dx, ip_gm1g )
     164             :        endif
     165             :     else
     166           0 :        ip_gm1g(:,:) = ip_gm1(:,:)
     167             :     end if
     168             : #else
     169             :     ip_gm1g(:,:) = ip_gm1(:,:)
     170             : #endif
     171             : #ifdef CTEM_DIAGS
     172             :     write(iulog,*) '===================================================='
     173             :     do j = beglat,endlat
     174             :        write(iulog,'(''iam,myidxy_x,myidxy_y,j = '',4i4)') grid%iam,grid%myidxy_x,grid%myidxy_y,j
     175             :        write(iulog,'(20i3)') ip_gm1(:,j)
     176             :     end do
     177             :     if( grid%myidxy_x == 0 ) then
     178             :        do j = beglat,endlat
     179             :           write(iulog,*) '===================================================='
     180             :           write(iulog,'(''iam,myidxy_x,myidxy_y,j = '',4i4)') grid%iam,grid%myidxy_x,grid%myidxy_y,j
     181             :           write(iulog,'(20i3)') ip_gm1g(:,j)
     182             :        end do
     183             :        write(iulog,*) '===================================================='
     184             : #else
     185             : #ifdef SPMD    
     186           0 :     if( grid%myidxy_x == 0 ) then
     187             : #endif
     188             : #endif
     189             : lat_loop2 : &
     190           0 :        do j = beglat, endlat
     191           0 :           zm_cnt(:ip_b) = plon
     192           0 :           do k = ip_b+1, plevp
     193           0 :              zm_cnt(k) = count( ip_gm1g(:,j) >= k )
     194             :           end do
     195           0 :           has_zm(:ip_b,j) = .true.
     196           0 :           do k = ip_b+1, plevp
     197           0 :              has_zm(k,j) = zm_cnt(k) >= zm_limit
     198             :           end do
     199             :        end do lat_loop2
     200             : #ifdef SPMD    
     201             :     end if
     202           0 :     if( grid%twod_decomp == 1 ) then
     203           0 :        call mpibcast( has_zm, plevp*(endlat-beglat+1), mpilog, 0, grid%commxy_x )
     204           0 :        call mpibcast( ip_gm1g, plon*(endlat-beglat+1), mpiint, 0, grid%commxy_x )
     205             :     end if
     206             : #endif
     207             : 
     208             : #ifdef CTEM_DIAGS
     209             :     if( grid%myidxy_y == 12 ) then
     210             :        write(iulog,*) '^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^'
     211             :        write(iulog,'(''iam,myidxy_x,myidxy_y,j = '',4i4)') grid%iam,grid%myidxy_x,grid%myidxy_y,beglat
     212             :        write(iulog,*) 'has_zm'
     213             :        write(iulog,'(20l2)') has_zm(:,beglat)
     214             :        write(iulog,*) 'ip_gm1g'
     215             :        write(iulog,'(20i4)') ip_gm1g(:,beglat)
     216             :        write(iulog,*) '^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^'
     217             :     end if
     218             : #endif
     219             : 
     220             : lat_loop3 : &
     221           0 :     do j = beglat, endlat
     222             : !-------------------------------------------------------------
     223             : ! Vertical interpolation
     224             : !-------------------------------------------------------------
     225           0 :        do k = 1, plevp
     226           0 :           pinterp = iref_p(k)
     227             : !-------------------------------------------------------------
     228             : !      Zonal velocity
     229             : !-------------------------------------------------------------
     230           0 :           call vertinterp( nlons, nlons, plev, pm(beglon,1,j), pinterp, &
     231           0 :                            u3(beglon,1,j), ui(beglon,k) )
     232             : !-------------------------------------------------------------
     233             : !      Meridional velocity
     234             : !-------------------------------------------------------------
     235           0 :           call vertinterp( nlons, nlons, plev, pm(beglon,1,j), pinterp, &
     236           0 :                            v3(beglon,1,j), vi(beglon,k) )
     237             : !-------------------------------------------------------------
     238             : !      Vertical velocity
     239             : !-------------------------------------------------------------
     240           0 :           call vertinterp( nlons, nlons, plev, pm(beglon,1,j), pinterp, &
     241           0 :                            w(beglon,1,j), wi(beglon,k) )
     242             : !-------------------------------------------------------------
     243             : !      Pot. Temperature
     244             : !-------------------------------------------------------------
     245           0 :           call vertinterp( nlons, nlons, plev, pm(beglon,1,j), pinterp, &
     246           0 :                            th(beglon,1,j), thi(beglon,k) )
     247             :        end do
     248             : #ifdef CTEM_DIAGS
     249             :        if( j == endlat ) then
     250             :        write(iulog,*) '^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^'
     251             :        write(iulog,'(''iam,myidxy_x,myidxy_y,j = '',4i4)') grid%iam,grid%myidxy_x,grid%myidxy_y,j
     252             :        write(iulog,*) 'iref_p'
     253             :        write(iulog,'(5g15.7)') iref_p(:)
     254             :        write(iulog,'(''pm(endlon,:,'',i2,'')'')') j
     255             :        write(iulog,'(5g15.7)') pm(endlon,:,j)
     256             :        write(iulog,'(''u3(endlon,:,'',i2,'')'')') j
     257             :        write(iulog,'(5g15.7)') u3(endlon,:,j)
     258             :        write(iulog,*) 'ui(endlon,:)'
     259             :        write(iulog,'(5g15.7)') ui(endlon,:)
     260             :        write(iulog,*) '^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^'
     261             :        end if
     262             : #endif
     263             : 
     264             : !-------------------------------------------------------------
     265             : ! Calculate zonal averages
     266             : !-------------------------------------------------------------
     267           0 :        do k = ip_b+1, plevp
     268           0 :           if( has_zm(k,j) ) then
     269           0 :              where( ip_gm1(beglon:endlon,j) < k )
     270             :                 ui(beglon:endlon,k)  = 0._r8
     271             :                 vi(beglon:endlon,k)  = 0._r8
     272             :                 wi(beglon:endlon,k)  = 0._r8
     273             :                 thi(beglon:endlon,k) = 0._r8
     274             :              endwhere
     275             :           end if
     276             :        end do
     277             : 
     278           0 :        call par_xsum( grid, ui, plevp, um )
     279           0 :        call par_xsum( grid, vi, plevp, vm )
     280           0 :        call par_xsum( grid, wi, plevp, wm )
     281           0 :        call par_xsum( grid, thi, plevp, thm )
     282             : #ifdef CTEM_DIAGS
     283             :        if( j == endlat .and. grid%myidxy_y == 12 ) then
     284             :           write(iulog,*) '$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$'
     285             :           write(iulog,'(''iam,myidxy_x,myidxy_y,j = '',4i4)') grid%iam,grid%myidxy_x,grid%myidxy_y,j
     286             :           write(iulog,*) 'um after par_xsum'
     287             :           write(iulog,'(5g15.7)') um(:)
     288             :           write(iulog,*) '$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$'
     289             :        end if
     290             : #endif
     291           0 :        do k = 1, ip_b
     292           0 :           um(k)     = um(k) * rplon
     293           0 :           vm(k)     = vm(k) * rplon
     294           0 :           wm(k)     = wm(k) * rplon
     295           0 :           thm(k)    = thm(k) * rplon
     296           0 :           u2d(k,j)  = um(k)
     297           0 :           v2d(k,j)  = vm(k)
     298           0 :           th2d(k,j) = thm(k)
     299           0 :           w2d(k,j)  = wm(k)
     300             :        end do
     301           0 :        do k = ip_b+1, plevp
     302           0 :           if( has_zm(k,j) ) then
     303           0 :              rdiv(k)   = 1._r8/count( ip_gm1g(:,j) >= k )
     304           0 :              um(k)     = um(k) * rdiv(k)
     305           0 :              vm(k)     = vm(k) * rdiv(k)
     306           0 :              wm(k)     = wm(k) * rdiv(k)
     307           0 :              thm(k)    = thm(k) * rdiv(k)
     308           0 :              u2d(k,j)  = um(k)
     309           0 :              v2d(k,j)  = vm(k)
     310           0 :              th2d(k,j) = thm(k)
     311           0 :              w2d(k,j)  = wm(k)
     312             :           else
     313           0 :              u2d(k,j)  = navp
     314           0 :              v2d(k,j)  = navp
     315           0 :              th2d(k,j) = navp
     316           0 :              w2d(k,j)  = navp
     317             :           end if
     318             :        end do
     319             : 
     320             : !-------------------------------------------------------------
     321             : ! Calculate zonal deviations
     322             : !-------------------------------------------------------------
     323           0 :        do k = 1, ip_b
     324           0 :           ud(beglon:endlon,k)  = ui(beglon:endlon,k)  - um(k)
     325           0 :           vd(beglon:endlon,k)  = vi(beglon:endlon,k)  - vm(k)
     326           0 :           wd(beglon:endlon,k)  = wi(beglon:endlon,k)  - wm(k)
     327           0 :           thd(beglon:endlon,k) = thi(beglon:endlon,k) - thm(k)
     328             :        end do
     329             : 
     330           0 :        do k = ip_b+1, plevp
     331           0 :           if( has_zm(k,j) ) then
     332           0 :              where( ip_gm1g(beglon:endlon,j) >= k )
     333             :                 ud(beglon:endlon,k)  = ui(beglon:endlon,k) - um(k)
     334             :                 vd(beglon:endlon,k)  = vi(beglon:endlon,k) - vm(k)
     335             :                 wd(beglon:endlon,k)  = wi(beglon:endlon,k) - wm(k)
     336             :                 thd(beglon:endlon,k) = thi(beglon:endlon,k) - thm(k)
     337             :              elsewhere
     338             :                 ud(beglon:endlon,k)  = 0._r8
     339             :                 vd(beglon:endlon,k)  = 0._r8
     340             :                 wd(beglon:endlon,k)  = 0._r8
     341             :                 thd(beglon:endlon,k) = 0._r8
     342             :              endwhere
     343             :           end if
     344             :        end do
     345             : 
     346             : !-------------------------------------------------------------
     347             : ! Calculate fluxes
     348             : !-------------------------------------------------------------
     349           0 :        do k = 1, ip_b
     350           0 :           vthp(:,k) = vd(:,k) * thd(:,k)
     351           0 :           wthp(:,k) = wd(:,k) * thd(:,k)
     352           0 :           uwp(:,k)  = wd(:,k) * ud(:,k)
     353           0 :           uvp(:,k)  = vd(:,k) * ud(:,k)
     354             :        end do
     355             : 
     356           0 :        do k = ip_b+1, plevp
     357           0 :           if( has_zm(k,j) ) then
     358           0 :              vthp(:,k) = vd(:,k) * thd(:,k)
     359           0 :              wthp(:,k) = wd(:,k) * thd(:,k)
     360           0 :              uwp(:,k)  = wd(:,k) * ud(:,k)
     361           0 :              uvp(:,k)  = vd(:,k) * ud(:,k)
     362             :           else
     363           0 :              vthp(:,k) = 0._r8
     364           0 :              wthp(:,k) = 0._r8
     365           0 :              uwp(:,k)  = 0._r8
     366           0 :              uvp(:,k)  = 0._r8
     367             :           end if
     368             :        end do
     369             : 
     370             : #ifdef CTEM_DIAGS
     371             :        if( j == endlat .and. grid%myidxy_y == 12 ) then
     372             :           write(iulog,*) '#################################################'
     373             :           write(iulog,*) 'DIAGNOSTICS before par_xsum'
     374             :           write(iulog,'(''iam,myidxy_x,myidxy_y,j = '',4i4)') grid%iam,grid%myidxy_x,grid%myidxy_y,j
     375             :           write(iulog,*) 'has_zm'
     376             :           write(iulog,*) has_zm(:,j)
     377             :           write(iulog,*) 'rdiv'
     378             :           write(iulog,'(5g15.7)') rdiv(:)
     379             :           write(iulog,*) 'wm'
     380             :           write(iulog,'(5g15.7)') wm(:)
     381             :           write(iulog,*) 'um'
     382             :           write(iulog,'(5g15.7)') um(:)
     383             :           write(iulog,*) 'uw'
     384             :           write(iulog,'(5g15.7)') uw(:)
     385             :           write(iulog,*) '#################################################'
     386             :        end if
     387             : #endif
     388           0 :        call par_xsum( grid, vthp, plevp, vth(1,j) )
     389           0 :        call par_xsum( grid, wthp, plevp, wth(1,j) )
     390           0 :        call par_xsum( grid, uvp, plevp, uv(1,j) )
     391           0 :        call par_xsum( grid, uwp, plevp, uw(1,j) )
     392             : #ifdef CTEM_DIAGS
     393             :        if( j == endlat .and. grid%myidxy_y == 12 ) then
     394             :           write(iulog,*) '#################################################'
     395             :           write(iulog,'(''iam,myidxy_x,myidxy_y,j = '',4i4)') grid%iam,grid%myidxy_x,grid%myidxy_y,j
     396             :           write(iulog,*) 'uw after par_xsum'
     397             :           write(iulog,'(5g15.7)') uw(:,j)
     398             :           write(iulog,*) '#################################################'
     399             :        end if
     400             : #endif
     401           0 :        do k = 1, ip_b
     402           0 :           vth(k,j) = vth(k,j) * rplon
     403           0 :           wth(k,j) = wth(k,j) * rplon
     404           0 :           uw(k,j)  = uw(k,j) * rplon
     405           0 :           uv(k,j)  = uv(k,j) * rplon
     406             :        end do
     407           0 :        do k = ip_b+1, plevp
     408           0 :           if( has_zm(k,j) ) then
     409           0 :              vth(k,j) = vth(k,j) * rdiv(k)
     410           0 :              wth(k,j) = wth(k,j) * rdiv(k)
     411           0 :              uw(k,j)  = uw(k,j) * rdiv(k)
     412           0 :              uv(k,j)  = uv(k,j) * rdiv(k)
     413             :           else
     414           0 :              vth(k,j) = navp
     415           0 :              wth(k,j) = navp
     416           0 :              uw(k,j)  = navp
     417           0 :              uv(k,j)  = navp
     418             :           end if
     419             :        end do
     420             : 
     421           0 :        thig(:,:,j) = thi(:,:)
     422             :     end do lat_loop3
     423             : 
     424             : !-------------------------------------------------------------
     425             : ! Do the output
     426             : !-------------------------------------------------------------
     427           0 :     latloop: do j = beglat,endlat
     428             : 
     429             : !-------------------------------------------------------------
     430             : ! zonal-mean output
     431             : !-------------------------------------------------------------
     432           0 :        do k = 1,plevp
     433           0 :           tmp3(grid%ifirstxy,k) = vth(k,j)
     434             :        enddo
     435           0 :        call outfld( 'VTHzm', tmp3(grid%ifirstxy,:), 1, j )
     436             : 
     437           0 :        do k = 1,plevp
     438           0 :           tmp3(grid%ifirstxy,k) = wth(k,j)
     439             :        enddo
     440           0 :        call outfld( 'WTHzm', tmp3(grid%ifirstxy,:), 1, j )
     441             : 
     442           0 :        do k = 1,plevp
     443           0 :           tmp3(grid%ifirstxy,k) = uv(k,j)
     444             :        enddo
     445           0 :        call outfld( 'UVzm', tmp3(grid%ifirstxy,:), 1, j )
     446             :  
     447           0 :        do k = 1,plevp
     448           0 :           tmp3(grid%ifirstxy,k) = uw(k,j)
     449             :        enddo
     450           0 :        call outfld( 'UWzm', tmp3(grid%ifirstxy,:), 1, j )
     451           0 :        do k = 1,plevp
     452           0 :           tmp3(grid%ifirstxy,k) = u2d(k,j)
     453             :        enddo
     454           0 :        call outfld( 'Uzm', tmp3(grid%ifirstxy,:), 1, j )
     455           0 :        do k = 1,plevp
     456           0 :           tmp3(grid%ifirstxy,k) = v2d(k,j)
     457             :        enddo
     458           0 :        call outfld( 'Vzm', tmp3(grid%ifirstxy,:), 1, j )
     459           0 :        do k = 1,plevp
     460           0 :           tmp3(grid%ifirstxy,k) = w2d(k,j)
     461             :        enddo
     462           0 :        call outfld( 'Wzm', tmp3(grid%ifirstxy,:), 1, j )
     463           0 :        do k = 1,plevp
     464           0 :           tmp3(grid%ifirstxy,k) = th2d(k,j)
     465             :        enddo
     466           0 :        call outfld( 'THzm', tmp3(grid%ifirstxy,:), 1, j )
     467             : 
     468             : !-------------------------------------------------------------
     469             : ! 3D output
     470             : !-------------------------------------------------------------
     471           0 :        do k = 1,plevp
     472           0 :           do i = beglon,endlon
     473           0 :              tmp3(i,k) = thig(i,k,j)
     474             :           enddo
     475             :        enddo
     476           0 :        call outfld( 'TH', tmp3, nlons, j )
     477             : 
     478             : !-------------------------------------------------------------
     479             : ! horizontal output
     480             : !-------------------------------------------------------------
     481           0 :        tmp2(beglon:endlon) = ip_gm1(beglon:endlon,j)
     482           0 :        call outfld( 'MSKtem', tmp2, nlons, j  )
     483             : 
     484             :     enddo latloop
     485             : 
     486           0 :   end subroutine ctem_diags
     487             : 
     488             : !=================================================================================
     489             : 
     490        1536 :   subroutine ctem_init()
     491             : 
     492             :   use hycoef,       only : hyai, hybi, ps0
     493             :   use phys_control, only : phys_getopts
     494             : 
     495             : !-------------------------------------------------------------
     496             : !       ... local variables
     497             : !-------------------------------------------------------------
     498             :     integer :: k
     499             :     logical :: history_waccm
     500             : 
     501        1536 :     if (.not.do_circulation_diags) return
     502             : 
     503           0 :     rplon    = 1._r8/plon
     504           0 :     zm_limit = plon/3
     505             : 
     506             : !-------------------------------------------------------------
     507             : ! Calculate reference pressure
     508             : !-------------------------------------------------------------
     509           0 :     do k = 1, plevp
     510           0 :        iref_p(k) = (hyai(k) + hybi(k)) * ps0
     511             :     end do
     512           0 :     if( masterproc ) then
     513           0 :        write(iulog,*) 'ctem_inti: iref_p'
     514           0 :        write(iulog,'(1p5g15.7)') iref_p(:)
     515             :     end if
     516             : 
     517             : !-------------------------------------------------------------
     518             : ! Find level where hybrid levels become purely pressure 
     519             : !-------------------------------------------------------------
     520           0 :     ip_b = -1
     521           0 :     do k = 1,plev
     522           0 :        if( hybi(k) == 0._r8 ) ip_b = k
     523             :     end do
     524             : 
     525           0 :     call phys_getopts( history_waccm_out = history_waccm )
     526             : 
     527             : !-------------------------------------------------------------
     528             : ! Initialize output buffer
     529             : !-------------------------------------------------------------
     530           0 :     call addfld ('VTHzm',(/ 'ilev' /),'A','MK/S','Meridional Heat Flux: 3D zon. mean', gridname='fv_centers_zonal' )
     531           0 :     call addfld ('WTHzm',(/ 'ilev' /),'A','MK/S','Vertical Heat Flux: 3D zon. mean', gridname='fv_centers_zonal' )
     532           0 :     call addfld ('UVzm', (/ 'ilev' /),'A','M2/S2','Meridional Flux of Zonal Momentum: 3D zon. mean', gridname='fv_centers_zonal' )
     533           0 :     call addfld ('UWzm', (/ 'ilev' /),'A','M2/S2','Vertical Flux of Zonal Momentum: 3D zon. mean', gridname='fv_centers_zonal' )
     534             : 
     535           0 :     call addfld ('Uzm',  (/ 'ilev' /),'A','M/S','Zonal-Mean zonal wind - defined on ilev', gridname='fv_centers_zonal' )
     536           0 :     call addfld ('Vzm',  (/ 'ilev' /),'A','M/S','Zonal-Mean meridional wind - defined on ilev', gridname='fv_centers_zonal' )
     537           0 :     call addfld ('Wzm',  (/ 'ilev' /),'A','M/S','Zonal-Mean vertical wind - defined on ilev', gridname='fv_centers_zonal' )
     538           0 :     call addfld ('THzm', (/ 'ilev' /),'A',  'K','Zonal-Mean potential temp - defined on ilev', gridname='fv_centers_zonal' )
     539             : 
     540           0 :     call addfld ('TH',   (/ 'ilev' /),'A','K',  'Potential Temperature', gridname='fv_centers' )
     541           0 :     call addfld ('MSKtem',horiz_only, 'A','1',  'TEM mask', gridname='fv_centers' )
     542             :     
     543             : !-------------------------------------------------------------
     544             : ! primary tapes: 3D fields
     545             : !-------------------------------------------------------------
     546           0 :     call add_default ('VTHzm', 1, ' ')
     547           0 :     call add_default ('WTHzm', 1, ' ')
     548           0 :     call add_default ('UVzm' , 1, ' ')
     549           0 :     call add_default ('UWzm' , 1, ' ')
     550           0 :     call add_default ('TH' , 1, ' ')
     551           0 :     call add_default ('MSKtem',1, ' ')
     552             : 
     553           0 :     if (history_waccm) then
     554           0 :        call add_default ('MSKtem',7, ' ')
     555           0 :        call add_default ('VTHzm', 7, ' ')
     556           0 :        call add_default ('UVzm', 7, ' ')
     557           0 :        call add_default ('UWzm', 7, ' ')
     558           0 :        call add_default ('Uzm', 7, ' ')
     559           0 :        call add_default ('Vzm', 7, ' ')
     560           0 :        call add_default ('Wzm', 7, ' ')
     561           0 :        call add_default ('THzm', 7, ' ')
     562             :     end if
     563             : 
     564           0 :     if (masterproc) then
     565           0 :        write(iulog,*) 'ctem_inti: do_circulation_diags = ',do_circulation_diags
     566             :     endif
     567             : 
     568             :   end subroutine ctem_init
     569             : 
     570             : !================================================================================
     571             : 
     572        1536 : subroutine ctem_readnl(nlfile)
     573             : 
     574             :    use namelist_utils,     only: find_group_name
     575             :    use units,              only: getunit, freeunit
     576             :    use spmd_utils,         only: mpicom, mstrid=>masterprocid, mpi_logical
     577             : 
     578             :    character(len=*), intent(in) :: nlfile  ! filepath for file containing namelist input
     579             :    
     580             :    ! Local variables
     581             :    integer :: unitn, ierr
     582             :    character(len=*), parameter :: subname = 'ctem_readnl'
     583             : 
     584             :    namelist /circ_diag_nl/ do_circulation_diags
     585             :    !-----------------------------------------------------------------------------
     586             :     
     587        1536 :    if (masterproc) then
     588           2 :       unitn = getunit()
     589           2 :       open( unitn, file=trim(nlfile), status='old' )
     590           2 :       call find_group_name(unitn, 'circ_diag_nl', status=ierr)
     591           2 :       if (ierr == 0) then
     592           0 :          read(unitn, circ_diag_nl, iostat=ierr)
     593           0 :          if (ierr /= 0) then
     594           0 :             call endrun(subname // ':: ERROR reading namelist')
     595             :          end if
     596             :       end if
     597           2 :       close(unitn)
     598           2 :       call freeunit(unitn)
     599             :    end if
     600             : 
     601        1536 :    call mpi_bcast(do_circulation_diags, 1, mpi_logical, mstrid, mpicom, ierr)
     602        1536 :    if (ierr /= 0) call endrun(subname//": FATAL: mpi_bcast: do_circulation_diags")
     603             : 
     604        1536 : end subroutine ctem_readnl
     605             : 
     606             : end module ctem

Generated by: LCOV version 1.14