LCOV - code coverage report
Current view: top level - dynamics/fv - diag_module.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 82 240 34.2 %
Date: 2025-03-14 01:21:06 Functions: 1 3 33.3 %

          Line data    Source code
       1             : module diag_module
       2             : 
       3             : ! diagnostic calcs
       4             : !
       5             : ! REVISION HISTORY:
       6             : !   05.09.10  Rasch   Creation of compute_vdot_gradp
       7             : !   05.10.18  Sawyer  Revisions for 2D decomp, placed in module
       8             : !   07.01.29  Chen    Removed pft2d calculation for OMGA (is in cd_core)
       9             : 
      10             : use shr_kind_mod,   only: r8 => shr_kind_r8
      11             : use spmd_utils,     only: masterproc
      12             : use pmgrid,         only: plon, plev, plevp
      13             : use cam_logfile,    only: iulog
      14             : use cam_history,    only: addfld, outfld, add_default, horiz_only
      15             : use cam_abortutils, only: endrun
      16             : 
      17             : implicit none
      18             : private
      19             : save
      20             : 
      21             : public :: &
      22             :    fv_diag_init,       &
      23             :    fv_diag_am_calc,    &
      24             :    compute_vdot_gradp
      25             : 
      26             : real(r8) :: rplon
      27             : real(r8) :: iref_p(plevp)              ! interface reference pressure for vertical interpolation
      28             : integer  :: ip_b                       ! level index where hybrid levels become purely pressure
      29             : integer  :: zm_limit
      30             : 
      31             : !========================================================================================
      32             : CONTAINS
      33             : !========================================================================================
      34             : 
      35           0 : subroutine fv_diag_init()
      36             : 
      37             :    use hycoef,       only : hyai, hybi, ps0
      38             : 
      39             :    ! local variables
      40             :    integer :: k
      41             :    logical :: history_waccm
      42             :    !---------------------------------------------------------------------------
      43             : 
      44           0 :    rplon    = 1._r8/plon
      45           0 :    zm_limit = plon/3
      46             : 
      47             :    !-------------------------------------------------------------
      48             :    ! Calculate reference pressure
      49             :    !-------------------------------------------------------------
      50           0 :    do k = 1, plevp
      51           0 :       iref_p(k) = (hyai(k) + hybi(k)) * ps0
      52             :    end do
      53           0 :    if( masterproc ) then
      54           0 :       write(iulog,*) 'fv_diag_inti: iref_p'
      55           0 :       write(iulog,'(1p5g15.7)') iref_p(:)
      56             :    end if
      57             : 
      58             :    !-------------------------------------------------------------
      59             :    ! Find level where hybrid levels become purely pressure 
      60             :    !-------------------------------------------------------------
      61           0 :    ip_b = -1
      62           0 :    do k = 1,plev
      63           0 :       if( hybi(k) == 0._r8 ) ip_b = k
      64             :    end do
      65             : 
      66             :    ! Fields for diagnosing angular momentum conservation.  They are supplemental
      67             :    ! to the fields computed by do_circulation_diags
      68             :    
      69           0 :    call addfld ('dUzm' ,(/ 'ilev' /),'A','M/S','Zonal-Mean U dyn increm - defined on ilev', gridname='fv_centers_zonal' )
      70           0 :    call addfld ('dVzm' ,(/ 'ilev' /),'A','M/S','Zonal-Mean V dyn increm - defined on ilev', gridname='fv_centers_zonal' )
      71           0 :    call addfld ('dUazm',(/ 'ilev' /),'A','M/S','Zonal-Mean U adv increm - defined on ilev', gridname='fv_centers_zonal' )
      72           0 :    call addfld ('dVazm',(/ 'ilev' /),'A','M/S','Zonal-Mean V adv increm - defined on ilev', gridname='fv_centers_zonal' )
      73           0 :    call addfld ('dUfzm',(/ 'ilev' /),'A','M/S','Zonal-Mean U fixer incr - defined on ilev', gridname='fv_centers_zonal' )
      74           0 :    call addfld ('dU',   (/ 'lev' /), 'A','K',  'U dyn increm', gridname='fv_centers' )
      75           0 :    call addfld ('dV',   (/ 'lev' /), 'A','K',  'V dyn increm', gridname='fv_centers' )
      76           0 :    call addfld ('dUa',  (/ 'lev' /), 'A','K',  'U adv increm', gridname='fv_centers' )
      77           0 :    call addfld ('dVa',  (/ 'lev' /), 'A','K',  'V adv increm', gridname='fv_centers' )
      78           0 :    call addfld ('dUf',  (/ 'lev' /), 'A','K',  'U fixer incr', gridname='fv_centers' )
      79             :     
      80           0 :    call add_default ('dUzm'  ,1, ' ')
      81           0 :    call add_default ('dVzm'  ,1, ' ')
      82           0 :    call add_default ('dUazm' ,1, ' ')
      83           0 :    call add_default ('dVazm' ,1, ' ')
      84           0 :    call add_default ('dUfzm' ,1, ' ')
      85           0 :    call add_default ('dU' ,   1, ' ')
      86           0 :    call add_default ('dV' ,   1, ' ')
      87           0 :    call add_default ('dUa',   1, ' ')
      88           0 :    call add_default ('dVa',   1, ' ')
      89           0 :    call add_default ('dUf',   1, ' ')
      90             : 
      91           0 : end subroutine fv_diag_init
      92             : 
      93             : !========================================================================================
      94             : 
      95           0 : subroutine fv_diag_am_calc(grid, ps, pe, du3, dv3, dua3, dva3, duf3)
      96             : 
      97             :    ! Compute fields for diagnosing angular momentum conservation.  They are supplemental
      98             :    ! to the fields computed by do_circulation_diags
      99             : 
     100             :     use dynamics_vars, only          : T_FVDYCORE_GRID
     101             :     use interpolate_data, only       : vertinterp
     102             : #ifdef SPMD
     103             :     use mpishorthand,       only     : mpilog, mpiint
     104             :     use parutilitiesmodule, only     : pargatherint
     105             : #endif
     106             : 
     107             : !-------------------------------------------------------------
     108             : !       ... dummy arguments
     109             : !-------------------------------------------------------------
     110             :     type(T_FVDYCORE_GRID), intent(in) :: grid                        ! FV Dynamics grid
     111             :     real(r8), intent(in)  :: ps(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy)         ! surface pressure (pa)
     112             :     real(r8), intent(in)  :: pe(grid%ifirstxy:grid%ilastxy,plevp,grid%jfirstxy:grid%jlastxy)   ! interface pressure (pa)
     113             :     real(r8), intent(in)  :: du3 (grid%ifirstxy:grid%ilastxy,plev,grid%jfirstxy:grid%jlastxy)  ! U increment, total (m/s/timestep)
     114             :     real(r8), intent(in)  :: dv3 (grid%ifirstxy:grid%ilastxy,plev,grid%jfirstxy:grid%jlastxy)  ! V increment, total (m/s/timestep)
     115             :     real(r8), intent(in)  :: dua3(grid%ifirstxy:grid%ilastxy,plev,grid%jfirstxy:grid%jlastxy)  ! U increment, advec (m/s/timestep)
     116             :     real(r8), intent(in)  :: dva3(grid%ifirstxy:grid%ilastxy,plev,grid%jfirstxy:grid%jlastxy)  ! V increment, advec (m/s/timestep)
     117             :     real(r8), intent(in)  :: duf3(grid%ifirstxy:grid%ilastxy,plev,grid%jfirstxy:grid%jlastxy)  ! U increment, fixer (m/s/timestep)
     118             : 
     119             : !-------------------------------------------------------------
     120             : !       ... local variables
     121             : !-------------------------------------------------------------
     122             :     
     123             :     real(r8) :: pinterp
     124           0 :     real(r8) :: pm(grid%ifirstxy:grid%ilastxy,plev,grid%jfirstxy:grid%jlastxy)         ! mid-point pressure
     125             :     real(r8) :: psurf
     126             : 
     127           0 :     real(r8) :: dui (grid%ifirstxy:grid%ilastxy,plevp)       ! interp. zonal mean U increment, total FV 
     128           0 :     real(r8) :: dvi (grid%ifirstxy:grid%ilastxy,plevp)       ! interp. zonal mean V increment, total FV 
     129           0 :     real(r8) :: duai(grid%ifirstxy:grid%ilastxy,plevp)       ! interp. zonal mean U increment, advection
     130           0 :     real(r8) :: dvai(grid%ifirstxy:grid%ilastxy,plevp)       ! interp. zonal mean V increment, advection
     131           0 :     real(r8) :: dufi(grid%ifirstxy:grid%ilastxy,plevp)       ! interp. zonal mean U increment, fixer    
     132             :     
     133             :     real(r8) :: dum (plevp)                                  ! zonal mean U increment, total FV 
     134             :     real(r8) :: dvm (plevp)                                  ! zonal mean V increment, total FV 
     135             :     real(r8) :: duam(plevp)                                  ! zonal mean U increment, advection
     136             :     real(r8) :: dvam(plevp)                                  ! zonal mean V increment, advection
     137             :     real(r8) :: dufm(plevp)                                  ! zonal mean U increment, fixer    
     138             : 
     139             :     real(r8) :: rdiv(plevp)
     140             :     
     141           0 :     integer  :: ip_gm1g(plon,grid%jfirstxy:grid%jlastxy)     ! contains level index-1 where blocked points begin
     142             :     integer  :: zm_cnt(plevp)                                ! counter
     143             :     integer  :: i,j,k
     144             :     integer  :: nlons
     145             : 
     146           0 :     logical  :: has_zm(plevp,grid%jfirstxy:grid%jlastxy)                   ! .true. the (z,y) point is a valid zonal mean 
     147           0 :     integer  :: ip_gm1(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy) ! contains level index-1 where blocked points begin
     148             : 
     149           0 :     real(r8) :: du2d (plevp,grid%jfirstxy:grid%jlastxy)              ! zonally averaged U dycore increment
     150           0 :     real(r8) :: dv2d (plevp,grid%jfirstxy:grid%jlastxy)              ! zonally averaged V dycore increment
     151           0 :     real(r8) :: dua2d(plevp,grid%jfirstxy:grid%jlastxy)              ! zonally averaged U advect increment
     152           0 :     real(r8) :: dva2d(plevp,grid%jfirstxy:grid%jlastxy)              ! zonally averaged V advect increment
     153           0 :     real(r8) :: duf2d(plevp,grid%jfirstxy:grid%jlastxy)              ! zonally averaged U fixer  increment
     154             : 
     155             :     real(r8) :: tmp2(grid%ifirstxy:grid%ilastxy)  
     156           0 :     real(r8) :: tmp3(grid%ifirstxy:grid%ilastxy,plevp)  
     157           0 :     real(r8) :: tmph(grid%ifirstxy:grid%ilastxy,plev)  
     158             : 
     159             :     integer :: beglat, endlat                          ! begin,end latitude indicies
     160             :     integer :: beglon, endlon                          ! begin,end longitude indicies
     161             : 
     162           0 :     beglon = grid%ifirstxy
     163           0 :     endlon = grid%ilastxy
     164           0 :     beglat = grid%jfirstxy
     165           0 :     endlat = grid%jlastxy
     166             : 
     167             : !omp parallel do private (i,j,k,psurf)
     168             : lat_loop1 : &
     169           0 :     do j = beglat, endlat
     170           0 :        do k = 1, plev
     171           0 :           do i = beglon, endlon
     172           0 :              pm(i,k,j) = 0.5_r8 * ( pe(i,k,j) + pe(i,k+1,j) )
     173             :           end do
     174             :        end do
     175             : !-------------------------------------------------------------
     176             : ! Keep track of where the bottom is in each column 
     177             : ! (i.e., largest index for which P(k) <= PS)
     178             : !-------------------------------------------------------------
     179           0 :        ip_gm1(:,j) = plevp 
     180           0 :        do i = beglon, endlon
     181           0 :           psurf = ps(i,j)
     182           0 :           do k = ip_b+1, plevp
     183           0 :              if( iref_p(k) <= psurf ) then
     184           0 :                 ip_gm1(i,j) = k
     185             :              end if
     186             :           end do
     187             :        end do
     188             :     end do lat_loop1
     189             : 
     190           0 :     nlons = endlon - beglon + 1
     191             : 
     192             : #ifdef SPMD    
     193           0 :     if( grid%twod_decomp == 1 ) then
     194           0 :        if (grid%iam .lt. grid%npes_xy) then
     195           0 :           call pargatherint( grid%commxy_x, 0, ip_gm1, grid%strip2dx, ip_gm1g )
     196             :        endif
     197             :     else
     198           0 :        ip_gm1g(:,:) = ip_gm1(:,:)
     199             :     end if
     200             : #else
     201             :     ip_gm1g(:,:) = ip_gm1(:,:)
     202             : #endif
     203             : #ifdef SPMD    
     204           0 :     if( grid%myidxy_x == 0 ) then
     205             : #endif
     206             : lat_loop2 : &
     207           0 :        do j = beglat, endlat
     208           0 :           zm_cnt(:ip_b) = plon
     209           0 :           do k = ip_b+1, plevp
     210           0 :              zm_cnt(k) = count( ip_gm1g(:,j) >= k )
     211             :           end do
     212           0 :           has_zm(:ip_b,j) = .true.
     213           0 :           do k = ip_b+1, plevp
     214           0 :              has_zm(k,j) = zm_cnt(k) >= zm_limit
     215             :           end do
     216             :        end do lat_loop2
     217             : #ifdef SPMD    
     218             :     end if
     219           0 :     if( grid%twod_decomp == 1 ) then
     220           0 :        call mpibcast( has_zm, plevp*(endlat-beglat+1), mpilog, 0, grid%commxy_x )
     221           0 :        call mpibcast( ip_gm1g, plon*(endlat-beglat+1), mpiint, 0, grid%commxy_x )
     222             :     end if
     223             : #endif
     224             : 
     225             : lat_loop3 : &
     226           0 :     do j = beglat, endlat
     227             : !-------------------------------------------------------------
     228             : ! Vertical interpolation
     229             : !-------------------------------------------------------------
     230           0 :        do k = 1, plevp
     231           0 :           pinterp = iref_p(k)
     232             : !-------------------------------------------------------------
     233             : !      Zonal & meridional velocity increments
     234             : !-------------------------------------------------------------
     235           0 :           call vertinterp( nlons, nlons, plev, pm(beglon,1,j), pinterp, &
     236           0 :                            du3(beglon,1,j) , dui (beglon,k) )
     237           0 :           call vertinterp( nlons, nlons, plev, pm(beglon,1,j), pinterp, &
     238           0 :                            dv3(beglon,1,j) , dvi (beglon,k) )
     239           0 :           call vertinterp( nlons, nlons, plev, pm(beglon,1,j), pinterp, &
     240           0 :                            dua3(beglon,1,j), duai(beglon,k) )
     241           0 :           call vertinterp( nlons, nlons, plev, pm(beglon,1,j), pinterp, &
     242           0 :                            dva3(beglon,1,j), dvai(beglon,k) )
     243           0 :           call vertinterp( nlons, nlons, plev, pm(beglon,1,j), pinterp, &
     244           0 :                            duf3(beglon,1,j), dufi(beglon,k) )
     245             :        end do
     246             : 
     247             : !-------------------------------------------------------------
     248             : ! Calculate zonal averages
     249             : !-------------------------------------------------------------
     250           0 :        do k = ip_b+1, plevp
     251           0 :           where( ip_gm1(beglon:endlon,j) < k )
     252           0 :              dui (beglon:endlon,k)= 0._r8
     253             :              dvi (beglon:endlon,k)= 0._r8
     254             :              duai(beglon:endlon,k)= 0._r8
     255             :              dvai(beglon:endlon,k)= 0._r8
     256             :              dufi(beglon:endlon,k)= 0._r8
     257             :           endwhere
     258             :        end do
     259             : 
     260           0 :        call par_xsum(grid, dui,  plevp, dum)
     261           0 :        call par_xsum(grid, dvi,  plevp, dvm)
     262           0 :        call par_xsum(grid, duai, plevp, duam)
     263           0 :        call par_xsum(grid, dvai, plevp, dvam)
     264           0 :        call par_xsum(grid, dufi, plevp, dufm)
     265             : 
     266           0 :        do k = 1, ip_b
     267           0 :           du2d(k,j) = dum(k) * rplon
     268           0 :           dv2d(k,j) = dvm(k) * rplon
     269           0 :           dua2d(k,j)= duam(k)* rplon
     270           0 :           dva2d(k,j)= dvam(k)* rplon
     271           0 :           duf2d(k,j)= dufm(k)* rplon
     272             :        end do
     273             : 
     274           0 :        do k = ip_b+1, plevp
     275           0 :           if( has_zm(k,j) ) then
     276           0 :              rdiv(k)   = 1._r8/count( ip_gm1g(:,j) >= k )
     277           0 :              du2d(k,j) = dum(k) * rdiv(k)
     278           0 :              dv2d(k,j) = dvm(k) * rdiv(k)
     279           0 :              dua2d(k,j)= duam(k)* rdiv(k)
     280           0 :              dva2d(k,j)= dvam(k)* rdiv(k)
     281           0 :              duf2d(k,j)= dufm(k)* rdiv(k)
     282             :           else
     283           0 :              du2d(k,j) = 0._r8
     284           0 :              dv2d(k,j) = 0._r8
     285           0 :              dua2d(k,j)= 0._r8
     286           0 :              dva2d(k,j)= 0._r8
     287           0 :              duf2d(k,j)= 0._r8
     288             :           end if
     289             :        end do
     290             : 
     291             :     end do lat_loop3
     292             : 
     293             : !-------------------------------------------------------------
     294             : ! Do the output
     295             : !-------------------------------------------------------------
     296           0 :     latloop: do j = beglat,endlat
     297             : 
     298             : !-------------------------------------------------------------
     299             : ! zonal-mean output
     300             : !-------------------------------------------------------------
     301             : 
     302           0 :        do k = 1,plevp
     303           0 :           tmp3(grid%ifirstxy,k) = du2d(k,j)
     304             :        enddo
     305           0 :        call outfld( 'dUzm', tmp3(grid%ifirstxy,:), 1, j )
     306             : 
     307           0 :        do k = 1,plevp
     308           0 :           tmp3(grid%ifirstxy,k) = dv2d(k,j)
     309             :        enddo
     310           0 :        call outfld( 'dVzm', tmp3(grid%ifirstxy,:), 1, j )
     311             : 
     312           0 :        do k = 1,plevp
     313           0 :           tmp3(grid%ifirstxy,k) = dua2d(k,j)
     314             :        enddo
     315           0 :        call outfld( 'dUazm', tmp3(grid%ifirstxy,:), 1, j )
     316             : 
     317           0 :        do k = 1,plevp
     318           0 :           tmp3(grid%ifirstxy,k) = dva2d(k,j)
     319             :        enddo
     320           0 :        call outfld( 'dVazm', tmp3(grid%ifirstxy,:), 1, j )
     321             : 
     322           0 :        do k = 1,plevp
     323           0 :           tmp3(grid%ifirstxy,k) = duf2d(k,j)
     324             :        enddo
     325           0 :        call outfld( 'dUfzm', tmp3(grid%ifirstxy,:), 1, j )
     326             : 
     327             : !-------------------------------------------------------------
     328             : ! 3D output
     329             : !-------------------------------------------------------------
     330             : 
     331           0 :        do k = 1,plev
     332           0 :           do i = beglon,endlon
     333           0 :              tmph(i,k) = du3(i,k,j)
     334             :           enddo
     335             :        enddo
     336           0 :        call outfld( 'dU', tmph, nlons, j )
     337             : 
     338           0 :        do k = 1,plev
     339           0 :           do i = beglon,endlon
     340           0 :              tmph(i,k) = dv3(i,k,j)
     341             :           enddo
     342             :        enddo
     343           0 :        call outfld( 'dV', tmph, nlons, j )
     344             : 
     345           0 :        do k = 1,plev
     346           0 :           do i = beglon,endlon
     347           0 :              tmph(i,k) = dua3(i,k,j)
     348             :           enddo
     349             :        enddo
     350           0 :        call outfld( 'dUa', tmph, nlons, j )
     351             : 
     352           0 :        do k = 1,plev
     353           0 :           do i = beglon,endlon
     354           0 :              tmph(i,k) = dva3(i,k,j)
     355             :           enddo
     356             :        enddo
     357           0 :        call outfld( 'dVa', tmph, nlons, j )
     358             : 
     359           0 :        do k = 1,plev
     360           0 :           do i = beglon,endlon
     361           0 :              tmph(i,k) = duf3(i,k,j)
     362             :           enddo
     363             :        enddo
     364           0 :        call outfld( 'dUf', tmph, nlons, j )
     365             : 
     366             :     enddo latloop
     367             : 
     368           0 : end subroutine fv_diag_am_calc
     369             : 
     370             : !========================================================================================
     371             : 
     372       16128 :   subroutine compute_vdot_gradp(grid, dt, frac, cx, cy, pexy, omgaxy )
     373             : 
     374             :   use shr_kind_mod, only :  r8 => shr_kind_r8
     375             :   use dynamics_vars, only : T_FVDYCORE_GRID
     376             : #if defined( SPMD )
     377             :   use mod_comm, only: mp_send3d, mp_recv3d, &
     378             :                       mp_sendirr, mp_recvirr
     379             : #endif
     380             : 
     381             :   implicit none
     382             : 
     383             : ! !INPUT PARAMETERS:
     384             :   type (T_FVDYCORE_GRID), intent(in) :: grid
     385             :   real(r8), intent(in):: dt
     386             :   real(r8), intent(in):: frac
     387             : 
     388             :   real(r8), intent(in):: cx(grid%im,grid%jfirst:grid%jlast,grid%kfirst:grid%klast)
     389             :   real(r8), intent(in):: cy(grid%im,grid%jfirst:grid%jlast+1,grid%kfirst:grid%klast)
     390             :   real(r8), target, intent(in)::   &
     391             :     pexy(grid%ifirstxy:grid%ilastxy,grid%km+1,grid%jfirstxy:grid%jlastxy) ! P (pascal) at layer edges
     392             :   real(r8), target, intent(inout):: &
     393             :     omgaxy(grid%ifirstxy:grid%ilastxy,grid%km,grid%jfirstxy:grid%jlastxy) ! vert. press. velocity (pa/sec)
     394             : 
     395             : ! Local 
     396             :   integer :: im       ! dimension in east-west
     397             :   integer :: jm       ! dimension in North-South
     398             :   integer :: km       ! number of Lagrangian layers
     399             :   integer :: jfirst   ! starting latitude index for MPI
     400             :   integer :: jlast    ! ending latitude index for MPI
     401             :   integer :: kfirst   ! starting level index for MPI
     402             :   integer :: klast    ! ending level index for MPI
     403             :   integer :: js2g0    ! j==1 not included
     404             :   integer :: jn2g0    ! j==jm not included
     405             : 
     406       32256 :   real(r8) :: pm(grid%im, grid%jfirst-1:grid%jlast+1)
     407       32256 :   real(r8) :: grad(grid%im, grid%jfirst:grid%jlast+1)
     408             :   real(r8) :: fac, sum1
     409             : 
     410       16128 :   real(r8), pointer :: pe(:,:,:)      ! YZ version of edge pressures
     411       16128 :   real(r8), pointer :: omga(:,:,:)    ! YZ version of vert. vel.
     412             : 
     413             :   real(r8), parameter :: half =  0.5_r8
     414             :   real(r8), parameter :: zero =  0.0_r8
     415             : 
     416             :   integer  :: i,j,k
     417             : 
     418             : #if defined( SPMD )
     419             :   integer  :: iam, dest, src, npr_y, npes_yz
     420       32256 :   real(r8) :: penorth(grid%im, grid%kfirst:grid%klast+1)
     421       32256 :   real(r8) :: pesouth(grid%im, grid%kfirst:grid%klast+1)
     422             : #endif
     423             : 
     424       16128 :   im     = grid%im
     425       16128 :   jm     = grid%jm
     426       16128 :   km     = grid%km
     427       16128 :   jfirst = grid%jfirst
     428       16128 :   jlast  = grid%jlast
     429       16128 :   kfirst = grid%kfirst
     430       16128 :   klast  = grid%klast
     431       16128 :   js2g0  = grid%js2g0
     432       16128 :   jn2g0  = grid%jn2g0
     433             : 
     434       16128 :   fac = half / (dt * frac)
     435             : 
     436             : #if defined( SPMD )
     437       16128 :   if ( grid%twod_decomp == 1 ) then
     438       80640 :     allocate(pe(im,kfirst:klast+1,jfirst:jlast))
     439       80640 :     allocate(omga(im,kfirst:klast,jfirst:jlast))
     440             :     call mp_sendirr( grid%commxy, grid%ikj_xy_to_yz%SendDesc,                  &
     441             :                      grid%ikj_xy_to_yz%RecvDesc, omgaxy, omga,                 &
     442       16128 :                      modc=grid%modc_dynrun )
     443             :     call mp_recvirr( grid%commxy, grid%ikj_xy_to_yz%SendDesc,                  &
     444             :                      grid%ikj_xy_to_yz%RecvDesc, omgaxy, omga,                 &
     445       16128 :                      modc=grid%modc_dynrun )
     446             :     call mp_sendirr( grid%commxy, grid%pexy_to_pe%SendDesc,                    &
     447             :                      grid%pexy_to_pe%RecvDesc, pexy, pe,                       &
     448       16128 :                      modc=grid%modc_dynrun )
     449             :     call mp_recvirr( grid%commxy, grid%pexy_to_pe%SendDesc,                    &
     450             :                      grid%pexy_to_pe%RecvDesc, pexy, pe,                       &
     451       16128 :                      modc=grid%modc_dynrun )
     452             :   else
     453           0 :     pe => pexy
     454           0 :     omga => omgaxy
     455             :   endif
     456       16128 :   iam   = grid%iam
     457       16128 :   npes_yz   = grid%npes_yz
     458       16128 :  if (iam .lt. npes_yz) then
     459       16128 :   npr_y = grid%npr_y
     460       16128 :   dest  = iam+1
     461       16128 :   src   = iam-1
     462       16128 :   if ( mod(iam+1,npr_y) == 0 ) dest = -1
     463       16128 :   if ( mod(iam,npr_y) == 0 ) src = -1
     464             : 
     465             : !
     466             : ! Have to give more thought to the source and destination for 2D
     467             : !
     468             :   call mp_send3d(grid%commyz, dest, src, im, km+1, jm,       &
     469             :                  1, im, kfirst, klast+1, jfirst, jlast,     &
     470       16128 :                  1, im, kfirst, klast+1, jlast, jlast, pe)
     471             :   call mp_recv3d(grid%commyz, src, im, km+1, jm,              &
     472             :                  1, im, kfirst, klast+1, jfirst-1, jfirst-1, &
     473       16128 :                  1, im, kfirst, klast+1, jfirst-1, jfirst-1, pesouth)
     474             :   call mp_send3d(grid%commyz, src, dest, im, km+1, jm,       &
     475             :                  1, im, kfirst, klast+1, jfirst, jlast,     &
     476       16128 :                  1, im, kfirst, klast+1, jfirst, jfirst, pe)
     477             :   call mp_recv3d(grid%commyz, dest, im, km+1, jm,            &
     478             :                  1, im, kfirst, klast+1, jlast+1, jlast+1,  &
     479       16128 :                  1, im, kfirst, klast+1, jlast+1, jlast+1, penorth)
     480             :  end if  !  (iam .lt. npes_yz)
     481             : #else
     482             :   pe => pexy
     483             :   omga => omgaxy
     484             : #endif
     485             : 
     486             : !$omp parallel do private(i,j,k,pm,grad, sum1)
     487       59136 :   do k=kfirst,klast
     488             : 
     489             : ! Compute layer mean p
     490      172032 :      do j=jfirst,jlast
     491    37330944 :         do i=1,im
     492    37287936 :            pm(i,j) = half * ( pe(i,k,j) + pe(i,k+1,j) )
     493             :         enddo
     494             :      enddo
     495             : 
     496             : #if defined( SPMD )
     497       43008 :      if ( jfirst/=1 ) then
     498    12235104 :         do i=1,im
     499    12235104 :            pm(i,jfirst-1) = half * ( pesouth(i,k) + pesouth(i,k+1))
     500             :         enddo
     501             :      endif
     502             : 
     503       43008 :      if ( jlast/=jm ) then
     504    12235104 :         do i=1,im
     505    12235104 :            pm(i,jlast+1) = half * ( penorth(i,k) + penorth(i,k+1))
     506             :         enddo
     507             :      endif
     508             : #endif
     509             : 
     510      170688 :      do j=js2g0,jn2g0
     511      127680 :            i=1
     512      127680 :            grad(i,j) = fac * cx(i,j,k) * (pm(i,j)-pm(im,j)) 
     513    36814848 :         do i=2,im
     514    36771840 :            grad(i,j) = fac * cx(i,j,k) * (pm(i,j)-pm(i-1,j)) 
     515             :         enddo
     516             :      enddo
     517             : 
     518      170688 :      do j=js2g0,jn2g0
     519    36771840 :         do i=1,im-1
     520    36771840 :            omga(i,k,j) = omga(i,k,j) + grad(i,j) + grad(i+1,j)
     521             :         enddo
     522      127680 :            i=im
     523      170688 :            omga(i,k,j) = omga(i,k,j) + grad(i,j) + grad(1,j)
     524             :      enddo
     525             : 
     526      213696 :      do j=js2g0,min(jm,jlast+1)
     527    49371840 :         do i=1,im
     528    49328832 :            grad(i,j) = fac * cy(i,j,k) * (pm(i,j)-pm(i,j-1)) 
     529             :         enddo
     530             :      enddo
     531             : 
     532      170688 :      do j=js2g0,jn2g0
     533    36942528 :         do i=1,im
     534    36899520 :            omga(i,k,j) = omga(i,k,j) + grad(i,j) + grad(i,j+1)
     535             :         enddo
     536             :      enddo
     537             : 
     538             : ! Note: Since V*grad(P) at poles are harder to compute accurately we use the average of sourding points
     539             : !       to be used as input to physics.
     540             : 
     541       43008 :      if ( jfirst==1 ) then
     542         672 :         sum1 = zero
     543      194208 :         do i=1,im
     544      194208 :            sum1 = sum1 + omga(i,k,2)
     545             :         enddo
     546         672 :         sum1 = sum1 / real(im,r8)
     547      194208 :         do i=1,im
     548      194208 :            omga(i,k,1) = sum1
     549             :         enddo
     550             :      endif
     551             : 
     552       59136 :      if ( jlast==jm ) then
     553         672 :         sum1 = zero
     554      194208 :         do i=1,im
     555      194208 :            sum1 = sum1 + omga(i,k,jm-1)
     556             :         enddo
     557         672 :         sum1 = sum1 / real(im,r8)
     558      194208 :         do i=1,im
     559      194208 :            omga(i,k,jm) = sum1
     560             :         enddo
     561             :      endif
     562             :   enddo
     563             : 
     564             : #if defined( SPMD)
     565       16128 :   if ( grid%twod_decomp == 1 ) then
     566             : !
     567             : ! Transpose back to XY  (if 1D, the changes to omgaxy were made in place)
     568             : !
     569             :     call mp_sendirr( grid%commxy, grid%ikj_yz_to_xy%SendDesc,                  &
     570             :                      grid%ikj_yz_to_xy%RecvDesc, omga, omgaxy,                 &
     571       16128 :                      modc=grid%modc_dynrun )
     572             :     call mp_recvirr( grid%commxy, grid%ikj_yz_to_xy%SendDesc,                  &
     573             :                      grid%ikj_yz_to_xy%RecvDesc, omga, omgaxy,                 &
     574       16128 :                      modc=grid%modc_dynrun )
     575       16128 :     deallocate( pe )
     576       16128 :     deallocate( omga )
     577             :   endif
     578             : #endif
     579             : 
     580       16128 :   end subroutine compute_vdot_gradp
     581             : 
     582             : end module diag_module

Generated by: LCOV version 1.14