LCOV - code coverage report
Current view: top level - dynamics/fv - p_d_adjust.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 94 134 70.1 %
Date: 2025-03-14 01:30:37 Functions: 1 1 100.0 %

          Line data    Source code
       1             : !-----------------------------------------------------------------------
       2             : !BOP
       3             : ! !IROUTINE: p_d_adjust --- complete full physics update
       4             : !
       5             : ! !INTERFACE: 
       6       14592 :   subroutine p_d_adjust(grid, tracer, pelnxy, pkxy, pkzxy, zvir, &
       7       14592 :                         cap3v, delpxy, ptxy, pexy, psxy, ptop)
       8             : 
       9             : ! !USES:
      10             :     use shr_kind_mod, only: r8 => shr_kind_r8
      11             :     use dynamics_vars, only : T_FVDYCORE_GRID
      12             : #if defined( SPMD )
      13             :     use parutilitiesmodule, only: parcollective, sumop
      14             : #endif
      15             :     use shr_reprosum_mod, only : shr_reprosum_calc, shr_reprosum_tolExceeded, &
      16             :                               shr_reprosum_reldiffmax, &
      17             :                               shr_reprosum_recompute
      18             :     use cam_logfile,   only : iulog
      19             :     use perf_mod
      20             : 
      21             : !-----------------------------------------------------------------------
      22             :     implicit none
      23             : 
      24             : ! !INPUT PARAMETERS:
      25             :     type (T_FVDYCORE_GRID), intent(in) :: grid
      26             :     real(r8), intent(in) :: zvir
      27             :     real(r8), intent(in) :: ptop
      28             :     real(r8), intent(in) :: cap3v( grid%ifirstxy:grid%ilastxy,                      &
      29             :                                    grid%jfirstxy:grid%jlastxy, grid%km) ! cappa
      30             : 
      31             : ! !INPUT/OUTPUT PARAMETERS:
      32             :     real(r8), intent(inout) :: tracer(grid%ifirstxy:grid%ilastxy,                     &
      33             :                                       grid%jfirstxy:grid%jlastxy,grid%km,grid%ntotq) ! constituents
      34             :     real(r8), intent(inout) :: delpxy(grid%ifirstxy:grid%ilastxy,                     &
      35             :                                       grid%jfirstxy:grid%jlastxy,grid%km) ! pressure difference
      36             :     real(r8), intent(inout) :: ptxy (grid%ifirstxy:grid%ilastxy,                      &
      37             :                                      grid%jfirstxy:grid%jlastxy, grid%km) ! Virtual pot temp
      38             :     real(r8), intent(inout) :: pexy(grid%ifirstxy:grid%ilastxy,                       &
      39             :                                     grid%km+1,grid%jfirstxy:grid%jlastxy)
      40             : 
      41             : ! !OUTPUT PARAMETERS
      42             :     real(r8), intent(out) :: psxy(grid%ifirstxy:grid%ilastxy, grid%jfirstxy:grid%jlastxy)  ! surf. press
      43             :     real(r8), intent(out) :: pelnxy(grid%ifirstxy:grid%ilastxy,grid%km+1,grid%jfirstxy:grid%jlastxy) ! interface pres
      44             :     real(r8), intent(out) :: pkzxy(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy, grid%km)    ! Layer-mean value of PK
      45             :     real(r8), intent(out) :: pkxy(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy, grid%km+1)  ! PE**cappa
      46             : 
      47             : ! !DESCRIPTION:
      48             : !
      49             : !   Complete adjustment of quantities after physics update
      50             : !
      51             : ! !REVISION HISTORY:
      52             : !   00.06.01   Grant?     Creation
      53             : !   01.06.08   AAM        Created from p_d_coupling
      54             : !   02.04.24   WS         New mod_comm interface
      55             : !   02.05.01   WS         Fix of S.-J. and Phil to peln, pk update
      56             : !   03.03.31   BAB        dry mass adjustment moved to dme_adjust, just finish up here
      57             : !   05.07.06   WS         Use grid argument to get all grid-related data
      58             : !   05.09.23   WS         Transitioned to XY variables only
      59             : !   06.07.01   WS         Transitioned tracers q3 to T_TRACERS
      60             : !   08.06.25   PW         Added call to fixed point reproducible sum
      61             : !
      62             : !EOP
      63             : !-----------------------------------------------------------------------
      64             : !BOC
      65             : ! !LOCAL VARIABLES:
      66             :     real(r8), parameter ::  D0_0                    =  0.0_r8
      67             :     real(r8), parameter ::  D1_0                    =  1.0_r8
      68             : 
      69       29184 :     real(r8) :: pole(grid%ifirstxy:grid%ilastxy,grid%km,grid%ntotq+2)
      70             :                                                !  Array containing local pole values
      71       29184 :     real(r8) :: pole_sum(grid%km,grid%ntotq+2) !  Array containing average of all pole values
      72       29184 :     real(r8) :: rel_diff(2,grid%km,grid%ntotq+2)
      73             : 
      74             :     real(r8) :: &
      75       29184 :         cap3vi(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy,grid%km+1)
      76             :     real(r8) :: &
      77       29184 :         pkln(grid%ifirstxy:grid%ilastxy,grid%km+1,grid%jfirstxy:grid%jlastxy)
      78             : 
      79       14592 :     real(r8),allocatable :: pole_tmp(:)
      80             : 
      81             :     integer :: i, k, m, j ! indices
      82             :     integer :: im, jm, km, ntotq, lim
      83             :     integer :: ifirstxy, ilastxy, jfirstxy, jlastxy
      84             : 
      85             :     logical  :: write_warning
      86             :     logical  :: high_alt
      87             : 
      88             : !---------------------------End Local workspace-------------------------
      89             : 
      90             : !
      91             : ! ----------------------------------------------------
      92             : ! Complete update of dynamics variables
      93             : ! ----------------------------------------------------
      94             : !
      95       14592 :     high_alt = grid%high_alt
      96       14592 :     im       = grid%im
      97       14592 :     jm       = grid%jm
      98       14592 :     km       = grid%km
      99       14592 :     ntotq    = grid%ntotq
     100             : 
     101       14592 :     ifirstxy = grid%ifirstxy
     102       14592 :     ilastxy  = grid%ilastxy
     103       14592 :     jfirstxy = grid%jfirstxy
     104       14592 :     jlastxy  = grid%jlastxy
     105             : 
     106       14592 :     lim      = (ilastxy-ifirstxy) + 1
     107             : 
     108             :     ! Average the pole values (WS 2006/02/16, bug fix)
     109             : 
     110       14592 :     if (jfirstxy==1) then
     111             : 
     112             :        !$omp parallel do private(i,k,m)
     113        7524 :        do k = 1, km
     114      182400 :           do i = ifirstxy, ilastxy
     115      175104 :              pole(i,k,1) = delpxy(i,1,k)
     116      182400 :              pole(i,k,2) =   ptxy(i,1,k)
     117             :           enddo
     118     2867556 :           do m = 1, ntotq
     119    71508096 :              do i = ifirstxy, ilastxy
     120    71500800 :                 pole(i,k,m+2) = tracer(i,1,k,m)
     121             :              enddo
     122             :           enddo
     123             :        enddo
     124             : 
     125         228 :        call t_startf("pdadj_reprosum")
     126             :        call shr_reprosum_calc(pole, pole_sum, lim, lim, km*(ntotq+2), gbl_count=im, &
     127         228 :                       commid=grid%commxy_x, rel_diff=rel_diff) ! South pole
     128         228 :        call t_stopf("pdadj_reprosum")
     129             : 
     130             :        ! check that "fast" reproducible sum is accurate enough. If not, calculate
     131             :        ! using old method
     132         228 :        write_warning = .false.
     133         228 :        if (grid%myidxy_x == 0) write_warning = .true.
     134         228 :        if ( shr_reprosum_tolExceeded('p_d_adjust/South Pole', km*(ntotq+2), &
     135             :                                    write_warning, iulog, rel_diff) ) then
     136           0 :           if ( shr_reprosum_recompute ) then
     137           0 :              call t_startf("pdadj_sumfix")
     138           0 :              allocate( pole_tmp(im) )
     139           0 :              do m = 1, ntotq+2
     140           0 :                 do k = 1, km
     141           0 :                    if (rel_diff(1,k,m) > shr_reprosum_reldiffmax) then
     142           0 :                       pole_tmp(:) = D0_0
     143           0 :                       do i = ifirstxy, ilastxy
     144           0 :                          pole_tmp(i) = pole(i,k,m)
     145             :                       enddo
     146             : #if defined(SPMD)
     147           0 :                       call parcollective(grid%commxy_x,sumop,im,pole_tmp)
     148             : #endif
     149           0 :                       pole_sum(k,m) = D0_0
     150           0 :                       do i = 1, im
     151           0 :                          pole_sum(k,m) = pole_sum(k,m) + pole_tmp(i)
     152             :                       enddo
     153             :                    endif
     154             :                 enddo
     155             :              enddo
     156           0 :              deallocate( pole_tmp )
     157           0 :              call t_stopf("pdadj_sumfix")
     158             :           endif
     159             :        endif
     160             : 
     161             :        ! save results
     162             :        !$omp parallel do private(i,k,m)
     163        7524 :        do k = 1, km
     164             :           ! normalize first
     165     2881920 :           do m = 1, ntotq+2
     166     2881920 :              pole_sum(k,m) = pole_sum(k,m)/im
     167             :           enddo
     168      182400 :           do i = ifirstxy,ilastxy
     169      175104 :              delpxy(i,1,k) = pole_sum(k,1)
     170      182400 :              ptxy(i,1,k)   = pole_sum(k,2)
     171             :           enddo
     172     2867556 :           do m = 1, ntotq
     173    71508096 :              do i = ifirstxy,ilastxy
     174    71500800 :                 tracer(i,1,k,m) = pole_sum(k,m+2)
     175             :              enddo
     176             :           enddo
     177             :        enddo
     178             : 
     179             :     endif ! jfirstxy==1
     180             : 
     181       14592 :     if (jlastxy==jm) then
     182             : 
     183             :        !$omp parallel do private(i,k,m)
     184        7524 :        do k = 1, km
     185      182400 :           do i = ifirstxy, ilastxy
     186      175104 :              pole(i,k,1) = delpxy(i,jm,k)
     187      182400 :              pole(i,k,2) =   ptxy(i,jm,k)
     188             :           enddo
     189     2867556 :           do m = 1, ntotq
     190    71508096 :              do i = ifirstxy, ilastxy
     191    71500800 :                 pole(i,k,m+2) = tracer(i,jm,k,m)
     192             :              enddo
     193             :           enddo
     194             :        enddo
     195             : 
     196         228 :        call t_startf("pdadj_reprosum")
     197             :        call shr_reprosum_calc(pole, pole_sum, lim, lim, km*(ntotq+2), gbl_count=im, &
     198         228 :                       commid=grid%commxy_x, rel_diff=rel_diff) ! North pole
     199         228 :        call t_stopf("pdadj_reprosum")
     200             : 
     201             :        ! check that "fast" reproducible sum is accurate enough. If not, calculate
     202             :        ! using old method
     203         228 :        write_warning = .false.
     204         228 :        if (grid%myidxy_x == 0) write_warning = .true.
     205         228 :        if ( shr_reprosum_tolExceeded('p_d_adjust/Nouth Pole', km*(ntotq+2), &
     206             :                                    write_warning, iulog, rel_diff) ) then
     207           0 :           if ( shr_reprosum_recompute ) then
     208           0 :              call t_startf("pdadj_sumfix")
     209           0 :              allocate( pole_tmp(im) )
     210           0 :              do m = 1, ntotq+2
     211           0 :                 do k = 1, km
     212           0 :                    if (rel_diff(1,k,m) > shr_reprosum_reldiffmax) then
     213           0 :                       pole_tmp(:) = D0_0
     214           0 :                       do i = ifirstxy, ilastxy
     215           0 :                          pole_tmp(i) = pole(i,k,m)
     216             :                       enddo
     217             : #if defined(SPMD)
     218           0 :                       call parcollective(grid%commxy_x,sumop,im,pole_tmp)
     219             : #endif
     220           0 :                       pole_sum(k,m) = D0_0
     221           0 :                       do i = 1, im
     222           0 :                          pole_sum(k,m) = pole_sum(k,m) + pole_tmp(i)
     223             :                       enddo
     224             :                    endif
     225             :                 enddo
     226             :              enddo
     227           0 :              deallocate( pole_tmp )
     228           0 :              call t_stopf("pdadj_sumfix")
     229             :           endif
     230             :        endif
     231             : 
     232             :        ! save results
     233             :        !$omp parallel do private(i,k,m)
     234        7524 :        do k = 1, km
     235             :           ! normalize first
     236     2881920 :           do m = 1, ntotq+2
     237     2881920 :              pole_sum(k,m) = pole_sum(k,m)/im
     238             :           enddo
     239      182400 :           do i = ifirstxy,ilastxy
     240      175104 :              delpxy(i,jm,k) = pole_sum(k,1)
     241      182400 :              ptxy(i,jm,k)   = pole_sum(k,2)
     242             :           enddo
     243     2867556 :           do m = 1, ntotq
     244    71508096 :              do i = ifirstxy,ilastxy
     245    71500800 :                 tracer(i,jm,k,m) = pole_sum(k,m+2)
     246             :              enddo
     247             :           enddo
     248             :        enddo
     249             : 
     250             :     endif ! jlastxy==jm
     251             : 
     252             :     !
     253             :     ! Fix pe,ps if nontrivial z decomposition
     254             :     ! Transpose pe - change to better method (16-byte?) later on
     255             :     !
     256             : 
     257             :     !
     258             :     ! Compute pexy
     259             :     !
     260             :     !$omp parallel do private(i, j)
     261       58368 :     do j = jfirstxy,jlastxy
     262     1108992 :        do i = ifirstxy, ilastxy
     263     1094400 :           pexy(i,1,j) = ptop
     264             :        enddo
     265             :     enddo
     266             : 
     267             :     !$omp parallel do private(i, j, k)
     268       58368 :     do j = jfirstxy,jlastxy
     269     1459200 :        do k = 1, km
     270    35064576 :           do i = ifirstxy, ilastxy
     271    35020800 :              pexy(i,k+1,j) = pexy(i,k,j) + delpxy(i,j,k)
     272             :           enddo
     273             :        enddo
     274             :     enddo
     275             : 
     276       58368 :     do j=jfirstxy,jlastxy
     277     1108992 :        do i=ifirstxy,ilastxy
     278     1094400 :           psxy(i,j) = pexy(i,km+1,j)
     279             :        enddo
     280             :     enddo
     281             : 
     282       14592 :     if (high_alt) then
     283             :        !$omp parallel do private(i,j,k)
     284           0 :        do k=2,km
     285           0 :           do j=jfirstxy,jlastxy
     286           0 :              do i=ifirstxy,ilastxy
     287           0 :                 cap3vi(i,j,k) = 0.5_r8*(cap3v(i,j,k-1)+cap3v(i,j,k))
     288             :              enddo
     289             :           enddo
     290             :        enddo
     291           0 :        cap3vi(:,:,1) = 1.5_r8 * cap3v(:,:,1) - 0.5_r8 * cap3v(:,:,2)
     292           0 :        cap3vi(:,:,km+1) = 1.5_r8 * cap3v(:,:,km) - 0.5_r8 * cap3v(:,:,km-1)
     293             :     else
     294    36611328 :        cap3vi(:,:,:) =  cap3v(grid%ifirstxy,grid%jfirstxy,1)
     295             :     endif
     296             : 
     297             :     !
     298             :     ! Update pelnxy and pkxy
     299             :     !
     300             :     !$omp parallel do private(i, j, k)
     301       58368 :     do j=jfirstxy,jlastxy
     302     1502976 :        do k = 1, km+1
     303    36158976 :           do i = ifirstxy, ilastxy
     304    34670592 :              pelnxy(i,k,j) = log( pexy(i,k,j) )
     305    34670592 :              pkxy  (i,j,k) = pexy(i,k,j) ** cap3vi(i,j,k)
     306    36115200 :              pkln(i,k,j) = log(pkxy(i,j,k))
     307             :           enddo
     308             :        enddo
     309             :     enddo     ! jfirstxy:jlastxy loop
     310             :     !
     311             :     ! Update pkzxy
     312             :     !
     313       14592 :     if (high_alt) then
     314             :        !$omp parallel do private(i, j, k)
     315           0 :        do j=jfirstxy,jlastxy
     316           0 :           do k = 1,km
     317           0 :              do i = ifirstxy,ilastxy
     318           0 :                 pkzxy(i,j,k) = (pkxy(i,j,k+1)-pkxy(i,j,k))/(pkln(i,k+1,j)-pkln(i,k,j))
     319             :              enddo
     320             :           enddo
     321             :        enddo
     322             :     else
     323             :        !$omp parallel do private(i, j, k)
     324       58368 :        do j=jfirstxy,jlastxy
     325     1459200 :           do k = 1,km
     326    35064576 :              do i = ifirstxy,ilastxy
     327    35020800 :                 pkzxy(i,j,k) = (pkxy(i,j,k+1)-pkxy(i,j,k))/(cap3v(i,j,k)*(pelnxy(i,k+1,j)-pelnxy(i,k,j)))
     328             :              enddo
     329             :           enddo
     330             :        enddo
     331             :     endif
     332             : 
     333             :     !
     334             :     ! Calculate virtual potential temperature
     335             :     !
     336             : 
     337             :     !$omp parallel do private(i, j, k)
     338       58368 :     do j=jfirstxy,jlastxy
     339     1459200 :        do k = 1,km
     340    35064576 :           do i = ifirstxy,ilastxy
     341   100859904 :              ptxy(i,j,k) = ptxy(i,j,k)*                  &
     342    33619968 :                 (D1_0+zvir*tracer(i,j,k,1)) &
     343   135880704 :                 /pkzxy(i,j,k)
     344             :           enddo
     345             :        enddo
     346             :     enddo     ! jfirstxy:jlastxy loop
     347             : 
     348             :     !EOC
     349       14592 :  end subroutine p_d_adjust
     350             : !-----------------------------------------------------------------------

Generated by: LCOV version 1.14