LCOV - code coverage report
Current view: top level - dynamics/fv - pfixer.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 154 201 76.6 %
Date: 2025-03-14 01:18:36 Functions: 3 3 100.0 %

          Line data    Source code
       1             : 
       2             : module pfixer
       3             : 
       4             : !----------------------------------------------------------------------- 
       5             : !
       6             : ! BOP
       7             : !
       8             : ! !MODULE: pfixer
       9             : !
      10             : ! !DESCRIPTION
      11             : ! Corrects (or fixes) mass fluxes and edge pressures to be consistent
      12             : ! with offline surface pressure at next model time step.
      13             : !
      14             : ! !USES
      15             :   use shr_kind_mod,      only: r8 => shr_kind_r8
      16             :   use cam_abortutils,    only: endrun
      17             :   use dynamics_vars,     only: T_FVDYCORE_GRID
      18             :   use cam_logfile,       only: iulog
      19             :   use metdata,           only: met_rlx
      20             : 
      21             : ! !PUBLIC MEMBER FUNCTIONS
      22             :   public :: adjust_press
      23             : 
      24             : ! !REVISION HISTORY:
      25             : !   04.01.30  Stacy Walters    Creation
      26             : !   04.02.15  F Vitt  Fixed bug in edge pressure corrections
      27             : !   04.08.27  F Vitt  Added ability to handle 2D decomposition
      28             : !   05.07.06  Sawyer  Simplified interfaces with grid
      29             : !
      30             : ! EOP
      31             : !----------------------------------------------------------------------- 
      32             : 
      33             :   private
      34             :   real(r8), parameter ::  D0_0                    =   0.0_r8
      35             :   real(r8), parameter ::  D0_5                    =   0.5_r8
      36             :   real(r8), parameter ::  D1_0                    =   1.0_r8
      37             :   real(r8), parameter ::  D100_0                  = 100.0_r8
      38             : contains
      39             : 
      40             : !-----------------------------------------------------------------------
      41             : !       ... adjust mass fluxes and pressures for lin-rood transport
      42             : !-----------------------------------------------------------------------
      43             : 
      44       64512 :   subroutine adjust_press( grid, ps_mod,  ps_obs, mfx, mfy, pexy )
      45             : 
      46             : #if defined( SPMD )
      47             :     use mod_comm, only : mp_send3d, mp_recv3d, &
      48             :                          mp_sendirr, mp_recvirr
      49             :     use parutilitiesmodule, only: parcollective, SUMOP
      50             : #endif
      51             :     use time_manager, only : get_nstep
      52             : !!$    use history,        only: outfld
      53             : 
      54             :     implicit none
      55             : 
      56             :     !-----------------------------------------------------------------------
      57             :     !       ... dummy arguments
      58             :     !-----------------------------------------------------------------------
      59             :     type (T_FVDYCORE_GRID), intent(in) :: grid
      60             :     real(r8), intent(in)    :: ps_obs(grid%im,grid%jfirst:grid%jlast)    ! surface pressure at t(n) (Pa)
      61             :     real(r8), intent(in)    :: ps_mod(grid%im,grid%jfirst:grid%jlast)    ! surface pressure at t(n) (Pa)
      62             :     real(r8), intent(inout) :: mfx(grid%im,grid%jfirst:grid%jlast,grid%kfirst:grid%klast)     ! zonal mass flux
      63             :     real(r8), intent(inout) :: mfy(grid%im,grid%jfirst:grid%jlast+1,grid%kfirst:grid%klast)   ! meridional mass flux
      64             :     real(r8), intent(inout) :: pexy(grid%ifirstxy:grid%ilastxy,grid%km+1,grid%jfirstxy:grid%jlastxy)
      65             : 
      66             :     !-----------------------------------------------------------------------
      67             :     !       ... local variables
      68             :     !-----------------------------------------------------------------------
      69             :     integer, parameter :: nstep0 = -1
      70             : 
      71             :     integer  :: i, j, k, km1
      72             :     integer  :: nstep
      73             : #if defined( SPMD )
      74             :     integer  :: dest, src
      75             : #endif
      76             :     integer  :: ndx(2)
      77       64512 :     real(r8) :: dpi(grid%im,grid%jfirst:grid%jlast,grid%kfirst:grid%klast)
      78       64512 :     real(r8) :: dpixy(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy,grid%km)
      79       64512 :     real(r8) :: dpi_in(grid%im,grid%jfirst:grid%jlast,grid%kfirst:grid%klast)
      80       64512 :     real(r8) :: dpi_inxy(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy,1:grid%km)
      81       64512 :     real(r8) :: dpi_c(grid%im,grid%jfirst:grid%jlast,grid%kfirst:grid%klast)
      82       64512 :     real(r8) :: dps   (grid%im,grid%jfirst:grid%jlast)
      83       64512 :     real(r8) :: dps_in(grid%im,grid%jfirst:grid%jlast)
      84       64512 :     real(r8) :: dps_inxy(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy)
      85       64512 :     real(r8) :: ps_diffxy(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy)
      86             : 
      87       64512 :     real(r8) :: dmfx(grid%im,grid%jfirst:grid%jlast,grid%kfirst:grid%klast)     ! original zonnal mass flux
      88       64512 :     real(r8) :: dmfy(grid%im,grid%jfirst:grid%jlast+1,grid%kfirst:grid%klast)   ! original meridional mass flux 
      89       64512 :     real(r8) :: emfx(grid%im,grid%jfirst:grid%jlast)     ! zonal mass flux error
      90       64512 :     real(r8) :: emfy(grid%im,grid%jfirst:grid%jlast+1)   ! meridional mass flux error
      91             :  
      92             :     real(r8) :: tmp2d(grid%im,grid%kfirst:grid%klast)
      93             :     logical :: debug = .false.
      94             :     logical :: method1 = .true.
      95             : 
      96             :     integer  :: im, jm, km, ifirstxy, ilastxy, jfirstxy, jlastxy
      97             :     integer  :: jfirst, jlast, kfirst, klast
      98             : 
      99       32256 :     im       = grid%im
     100       32256 :     jm       = grid%jm
     101       32256 :     km       = grid%km
     102             : 
     103       32256 :     ifirstxy = grid%ifirstxy
     104       32256 :     ilastxy  = grid%ilastxy
     105       32256 :     jfirstxy = grid%jfirstxy
     106       32256 :     jlastxy  = grid%jlastxy
     107             : 
     108       32256 :     jfirst   = grid%jfirst
     109       32256 :     jlast    = grid%jlast
     110       32256 :     kfirst   = grid%kfirst
     111       32256 :     klast    = grid%klast
     112             :     
     113             : #if defined( SPMD )
     114             :     ! Send one latitude of mfy to the south
     115       32256 :     if( mod(grid%iam,grid%npr_y) /= 0 ) then
     116       31752 :        dest = grid%iam-1
     117             :     else
     118         504 :        dest = -1
     119             :     end if
     120       32256 :     if( mod(grid%iam+1,grid%npr_y) /= 0 ) then
     121       31752 :        src  = grid%iam+1
     122             :     else
     123         504 :        src = -1
     124             :     end if
     125             :     call mp_send3d( grid%commxy, dest, src, im, jm, km,                  &
     126             :                     1, im, jfirst, jlast+1, kfirst, klast,              &
     127       32256 :                     1, im, jfirst, jfirst, kfirst, klast, mfy)
     128             : #endif
     129             : 
     130      129024 :     do j = jfirst,jlast
     131    27998208 :        dps(:,j) = ps_obs(:,j) - ps_mod(:,j)
     132             :     end do
     133             : 
     134             :     ! ghost mfy
     135             : #if defined( SPMD )
     136             :     call mp_recv3d( grid%commxy, src, im, jm, km,                &
     137             :                     1, im, jfirst, jlast+1, kfirst, klast,      &
     138       32256 :                     1, im, jlast+1, jlast+1, kfirst, klast, mfy)
     139             : #endif
     140             : 
     141       32256 :     nstep = get_nstep()
     142             : !-----------------------------------------------------------------------
     143             : !       ... store incoming mass fluxes
     144             : !-----------------------------------------------------------------------
     145       32256 :     if (debug) then
     146           0 :        do k = kfirst,klast
     147           0 :           do j = jfirst,jlast
     148           0 :              dmfx(:,j,k) = mfx(:,j,k)
     149           0 :              dmfy(:,j,k) = mfy(:,j,k)
     150             :           end do
     151           0 :           if( jlast /= jm ) then
     152           0 :              dmfy(:,jlast+1,k) = mfy(:,jlast+1,k)
     153             :           end if
     154             :        end do
     155             :     endif
     156             : 
     157             : !-----------------------------------------------------------------------
     158             : !       ... incoming mass flux divergence
     159             : !-----------------------------------------------------------------------
     160       32256 :     call calc_divergence( grid, mfx, mfy, dpi_in )
     161             : 
     162             : !-----------------------------------------------------------------------
     163             : !       ... surface pressure from mass flux divergence
     164             : !-----------------------------------------------------------------------
     165             : !  Two different methods to compute change in ps give differnt 
     166             : !  results if 2D decomp is used (round off error).  Method 1 gives
     167             : !  identical 1D vs 2D decomposition results.
     168             : !-----------------------------------------------------------------------
     169       32256 :     if (method1) then 
     170             : 
     171             :        ! xfer dpi_in to dpi_inxy
     172       32256 :        if (grid%twod_decomp .eq. 1) then
     173             : #if defined (SPMD)
     174             :           call mp_sendirr( grid%commxy, grid%ijk_yz_to_xy%SendDesc,                  &
     175             :                            grid%ijk_yz_to_xy%RecvDesc, dpi_in, dpi_inxy,             &
     176       32256 :                            modc=grid%modc_dynrun )
     177             :           call mp_recvirr( grid%commxy, grid%ijk_yz_to_xy%SendDesc,                  &
     178             :                            grid%ijk_yz_to_xy%RecvDesc, dpi_in, dpi_inxy,             &
     179       32256 :                            modc=grid%modc_dynrun )
     180             : #endif
     181             :        else            
     182           0 :           dpi_inxy(:,:,:) = dpi_in(:,:,:)
     183             :        endif
     184             : 
     185             :        ! vertical sum
     186      129024 :        do j = jfirstxy,jlastxy
     187     2451456 :           do i = ifirstxy,ilastxy
     188   132475392 :              dps_inxy(i,j) = sum( dpi_inxy(i,j,1:km) )
     189             :           end do
     190             :        end do
     191             : 
     192             :        ! xfer dps_inxy to dps_in
     193             :        ! Embed in 3D array since transpose machinery cannot handle 2D arrays
     194       32256 :        if (grid%twod_decomp .eq. 1) then
     195             : #if defined (SPMD)
     196     1838592 :           do k = 1,km
     197     7257600 :              do j = jfirstxy,jlastxy
     198   137281536 :                 do i = ifirstxy,ilastxy
     199   135475200 :                    dpixy(i,j,k) = dps_inxy(i,j)
     200             :                 enddo
     201             :              enddo
     202             :           enddo
     203             : 
     204             :           call mp_sendirr( grid%commxy, grid%ijk_xy_to_yz%SendDesc,                  &
     205             :                            grid%ijk_xy_to_yz%RecvDesc, dpixy, dpi,                   &
     206       32256 :                            modc=grid%modc_dynrun )
     207             :           call mp_recvirr( grid%commxy, grid%ijk_xy_to_yz%SendDesc,                  &
     208             :                            grid%ijk_xy_to_yz%RecvDesc, dpixy, dpi,                   &
     209       32256 :                            modc=grid%modc_dynrun )
     210             : 
     211      129024 :           do j = jfirst,jlast
     212    27998208 :              do i = 1,im
     213    27965952 :                 dps_in(i,j) = dpi(i,j,kfirst)
     214             :              enddo
     215             :           enddo
     216             : #endif
     217             :        else            
     218           0 :           dps_in(:,:) = dps_inxy(:,:)
     219             :        endif
     220             : 
     221             :     else ! method1
     222             : 
     223             :        ! this method does not give identical results as the above method
     224             :        ! when two dimensional decomposition is used
     225             : 
     226           0 :        do j = jfirst,jlast
     227           0 :           do i = 1,im
     228           0 :              dps_in(i,j) = sum( dpi_in(i,j,kfirst:klast) )
     229             :           end do
     230             :        end do
     231             : 
     232             : #if ( defined SPMD )
     233           0 :        if (grid%twod_decomp .eq. 1) then
     234           0 :           call parcollective( grid%comm_z, SUMOP, im, jlast-jfirst+1,  dps_in )
     235             :        endif
     236             : #endif
     237             : 
     238             :     endif ! method1
     239             : 
     240             : !-----------------------------------------------------------------------
     241             : !       ... modify (fix) mass fluxes
     242             : !-----------------------------------------------------------------------
     243       32256 :     call do_press_fix_llnl( grid, dps, dps_in, mfx, mfy )
     244             : 
     245             : !-----------------------------------------------------------------------
     246             : !       ... modified mass flux divergence
     247             : !-----------------------------------------------------------------------
     248       32256 :     call calc_divergence( grid, mfx, mfy, dpi_c )
     249             :       
     250             : !-----------------------------------------------------------------------
     251             : !       ... differential mass flux divergence
     252             : !-----------------------------------------------------------------------
     253      182784 :     do k = kfirst,klast
     254      634368 :        do j = jfirst,jlast
     255   130658304 :           dpi(:,j,k) = dpi_c(:,j,k) - dpi_in(:,j,k)
     256             :        end do
     257             :     end do
     258             : 
     259       32256 :     if (grid%twod_decomp .eq. 1) then
     260             : #if defined (SPMD)
     261             :        call mp_sendirr( grid%commxy, grid%ijk_yz_to_xy%SendDesc,                  &
     262             :                         grid%ijk_yz_to_xy%RecvDesc, dpi, dpixy,                   &
     263       32256 :                         modc=grid%modc_dynrun )
     264             :        call mp_recvirr( grid%commxy, grid%ijk_yz_to_xy%SendDesc,                  &
     265             :                         grid%ijk_yz_to_xy%RecvDesc, dpi, dpixy,                   &
     266       32256 :                         modc=grid%modc_dynrun )
     267             : #endif
     268             :     else            
     269           0 :        dpixy(:,:,:) = dpi(:,:,:)
     270             :     endif
     271             : 
     272             : 
     273             : !-----------------------------------------------------------------------
     274             : !       ... modify pe
     275             : !-----------------------------------------------------------------------
     276             : 
     277       32256 :     if (debug) then
     278           0 :        write(iulog,*) ' '
     279           0 :        write(iulog,*) 'adjust_press: max pe diff %  @ nstep,ifirstxy,ilastxy,jfirstxy,jlastxy = ',&
     280           0 :             nstep,ifirstxy,ilastxy,jfirstxy,jlastxy
     281             :     endif
     282             : 
     283     1838592 :     do k = 1+1,km+1
     284     1806336 :        km1 = k - 1
     285             : 
     286     1806336 :        if (debug) then
     287           0 :           do j = jfirstxy,jlastxy
     288           0 :              do i = ifirstxy,ilastxy
     289           0 :                 ps_diffxy(i,j) = sum( dpixy(i,j,1:km1) )/ pexy(i,k,j )
     290             :              end do
     291             :           end do
     292             :        endif
     293             : 
     294     1806336 :        if( nstep > nstep0 ) then
     295     7225344 :           do j = jfirstxy,jlastxy
     296   137281536 :              do i = ifirstxy,ilastxy
     297  3842076672 :                 pexy(i,k,j) = pexy(i,k,j) + sum( dpixy(i,j,1:km1) ) 
     298             :              end do
     299             :           end do
     300             :        end if
     301     1838592 :        if (debug) then
     302             : 
     303           0 :           ndx(:)       = maxloc( abs( ps_diffxy(:,:) ) )
     304             : 
     305           0 :           ndx(1)       = ndx(1) + ifirstxy - 1
     306           0 :           ndx(2)       = ndx(2) + jfirstxy - 1
     307             : 
     308             :           write(iulog,'("pfixer press change error (% error,press adjmnt,new pe)",1x,3i5,1p,3g15.7)') &
     309           0 :                k,ndx(:),D100_0*abs( ps_diffxy(ndx(1),ndx(2)) ), &
     310           0 :                dpixy(ndx(1),ndx(2),km1),pexy(ndx(1),k,ndx(2))
     311             : 
     312             :        endif
     313             :     end do
     314             : 
     315       32256 :     if (debug) then 
     316           0 :        write(iulog,*) ' '
     317           0 :        write(iulog,*) 'adjust_press: max  mass flux error  @ nstep,jfirst,jlast,kfirst,klast = ',&
     318           0 :             nstep,jfirst,jlast,kfirst,klast
     319             : 
     320           0 :        do k = kfirst,klast
     321             : 
     322           0 :           do j=jfirst,jlast
     323           0 :              do i=1,im
     324           0 :                 emfx(i,j) = ( mfx(i,j,k)-dmfx(i,j,k) ) 
     325             :              enddo
     326             :           enddo
     327             : 
     328           0 :           ndx(:)       = maxloc( abs( emfx(:,:) ) )
     329           0 :           ndx(2)       = ndx(2) + jfirst - 1
     330             : 
     331             :           write(iulog,'("pfixer max x flux error (diff,fixed,orig) ",1x,3i5,1p,3g15.7)') &
     332           0 :                k,ndx(:), emfx( ndx(1),ndx(2) ) , &
     333           0 :                mfx(ndx(1),ndx(2),k),  dmfx(ndx(1),ndx(2),k)
     334             : 
     335           0 :           do j=jfirst,jlast+1
     336           0 :              do i=1,im
     337           0 :                 emfy(i,j) = ( mfy(i,j,k)-dmfy(i,j,k) ) 
     338             :              enddo
     339             :           enddo
     340             : 
     341           0 :           ndx(:)       = maxloc( abs( emfy(:,:) ) )
     342           0 :           ndx(2)       = ndx(2) + jfirst - 1
     343             : 
     344             :           write(iulog,'("pfixer max y flux error (diff,fixed,orig) ",1x,3i5,1p,3g15.7)') &
     345           0 :                k,ndx(:), emfy( ndx(1),ndx(2) ) , &
     346           0 :                mfy(ndx(1),ndx(2),k),  dmfy(ndx(1),ndx(2),k)
     347             : 
     348             :        enddo
     349             :     endif
     350             : 
     351       32256 :   end subroutine adjust_press
     352             : 
     353             : !-----------------------------------------------------------------------
     354             : !       ... calculate horizontal mass flux divergence
     355             : !-----------------------------------------------------------------------
     356       64512 :   subroutine calc_divergence( grid, mfx, mfy, dpi )
     357             : 
     358             :     implicit none
     359             : 
     360             :     !-----------------------------------------------------------------------
     361             :     !       ... dummy arguments
     362             :     !-----------------------------------------------------------------------
     363             :     type (T_FVDYCORE_GRID), intent(in) :: grid
     364             :     real(r8), intent(in)    :: mfx(grid%im,grid%jfirst:grid%jlast,      &
     365             :                                    grid%kfirst:grid%klast)          ! zonal mass flux
     366             :     real(r8), intent(in)    :: mfy(grid%im,grid%jfirst:grid%jlast+1,    &
     367             :                                    grid%kfirst:grid%klast)        ! meridional mass flux
     368             :     real(r8), intent(inout) :: dpi(grid%im,grid%jfirst:grid%jlast,      &
     369             :                                    grid%kfirst:grid%klast)          ! horizontal mass flux divergence
     370             : 
     371             : !-----------------------------------------------------------------------
     372             : !       ... local variables
     373             : !-----------------------------------------------------------------------
     374             :     integer  :: i, j, k, js2g0, jn2g0
     375             :     real(r8) :: sum1
     376             :     integer  :: im, jm, km, jfirst, jlast, kfirst, klast
     377             : 
     378       64512 :     im    = grid%im
     379       64512 :     jm    = grid%jm
     380       64512 :     km    = grid%km
     381       64512 :     jfirst= grid%jfirst
     382       64512 :     jlast = grid%jlast
     383       64512 :     kfirst= grid%kfirst
     384       64512 :     klast = grid%klast
     385             : 
     386       64512 :     js2g0 = max( 2,jfirst )
     387       64512 :     jn2g0 = min( jm-1,jlast )
     388             : 
     389             : !$omp parallel do private( j, k, sum1 )
     390      365568 :     do k = kfirst,klast
     391             : !-----------------------------------------------------------------------
     392             : !       ... north-south component
     393             : !-----------------------------------------------------------------------
     394     1194816 :        do j = js2g0,jn2g0
     395   258597696 :           dpi(:,j,k) = (mfy(:,j,k) - mfy(:,j+1,k)) * grid%acosp(j)
     396             :        end do
     397             : !-----------------------------------------------------------------------
     398             : !       ... east-west component
     399             : !-----------------------------------------------------------------------
     400     1194816 :        do j = js2g0,jn2g0
     401   257402880 :           dpi(:im-1,j,k) = dpi(:im-1,j,k) + mfx(:im-1,j,k) - mfx(2:im,j,k)
     402     1194816 :           dpi(im,j,k)    = dpi(im,j,k) + mfx(im,j,k) - mfx(1,j,k)
     403             :        end do
     404             : !-----------------------------------------------------------------------
     405             : !       ... poles
     406             : !-----------------------------------------------------------------------
     407      301056 :        if( jfirst == 1 ) then
     408     1359456 :           sum1 = -sum( mfy(:,2,k) )*grid%rcap
     409     1359456 :           dpi(:,1,k) = sum1
     410             :        end if
     411      365568 :        if( jlast == jm ) then
     412     1359456 :           sum1 = sum( mfy(:,jm,k) ) * grid%rcap
     413     1359456 :           dpi(:,jm,k) = sum1
     414             :        end if
     415             :     end do
     416             : !$omp end parallel do
     417             : 
     418       32256 :   end subroutine calc_divergence
     419             : 
     420             : !-----------------------------------------------------------------------
     421             : !       ... fix the mass fluxes to match the met field pressure tendency
     422             : !     See: http://asd.llnl.gov/pfix/index.html
     423             : !-----------------------------------------------------------------------
     424       32256 :   subroutine do_press_fix_llnl( grid, dps, dps_ctm, mfx, mfy )
     425             : 
     426             :     use commap,        only : gw => w
     427             : #ifdef SPMD
     428             :     use mpishorthand,  only : mpicom, mpi_double_precision, mpi_success
     429             :     use spmd_dyn,      only : compute_gsfactors
     430             : #endif
     431             :     use spmd_utils,    only : npes
     432             :     use hycoef,        only : hybd
     433             :     implicit none
     434             : 
     435             : !-----------------------------------------------------------------------
     436             : !       ... dummy arguments
     437             : !-----------------------------------------------------------------------
     438             :     type (T_FVDYCORE_GRID), intent(in) :: grid
     439             : ! surface pressure change from met fields
     440             :     real(r8), intent(in)    :: dps(grid%im,grid%jfirst:grid%jlast)
     441             : ! vert. sum of dpi from original mass fluxes
     442             :     real(r8), intent(in)    :: dps_ctm(grid%im,grid%jfirst:grid%jlast)
     443             : ! zonal mass flux
     444             :     real(r8), intent(inout) :: mfx(grid%im,grid%jfirst:grid%jlast,grid%kfirst:grid%klast)
     445             : ! meridional mass flux
     446             :     real(r8), intent(inout) :: mfy(grid%im,grid%jfirst:grid%jlast+1,grid%kfirst:grid%klast)
     447             : 
     448             : !-----------------------------------------------------------------------
     449             : !       ... local variables
     450             : !-----------------------------------------------------------------------
     451             :     integer     :: i, j, jglob, k, astat, ierr
     452             :     integer     :: jn2g0, js2g0, jn2g1
     453             :     integer     :: cnt
     454             : #ifdef SPMD
     455       64512 :     integer     :: numrecv(0:npes-1)
     456       64512 :     integer     :: displs(0:npes-1)
     457             : #endif
     458             :     real(r8)    :: dpress_g                       ! global pressure error
     459             :     real(r8)    :: fxmean, factor
     460       64512 :     real(r8)    :: ddps(grid%im,grid%jfirst:grid%jlast)        ! surface pressure change error
     461       64512 :     real(r8)    :: dpresslat(grid%jm)
     462       64512 :     real(r8)    :: mmfd(grid%jm)
     463       64512 :     real(r8)    :: mmf(grid%jm+1)
     464       64512 :     real(r8)    :: fxintegral(grid%im+1)
     465       64512 :     real(r8)    :: xcolmass_fix(grid%im,grid%jfirst:grid%jlast)
     466       64512 :     real(r8)    :: temp(grid%jfirst:grid%jlast)
     467             : 
     468             :     integer     :: im, jm, km, jfirst, jlast, kfirst, klast
     469             : 
     470       32256 :     im    = grid%im
     471       32256 :     jm    = grid%jm
     472       32256 :     km    = grid%km
     473       32256 :     jfirst= grid%jfirst
     474       32256 :     jlast = grid%jlast
     475       32256 :     kfirst= grid%kfirst
     476       32256 :     klast = grid%klast
     477             : 
     478       32256 :     js2g0 = max( 2,jfirst )
     479       32256 :     jn2g0 = min( jm-1,jlast )
     480       32256 :     jn2g1 = min( jm-1,jlast+1 )
     481             : 
     482      129024 :     do j = jfirst,jlast
     483    27998208 :        ddps(:,j) = dps(:,j) - dps_ctm(:,j)
     484             :     end do
     485       32256 :     factor = D0_5/im
     486      129024 :     do j = jfirst,jlast
     487    27998208 :        dpresslat(j) = sum( ddps(:,j) ) * gw(j) * factor
     488             :     end do
     489             : 
     490             : #ifdef SPMD
     491       32256 :     call compute_gsfactors( 1, cnt, numrecv, displs )
     492      161280 :     temp(jfirst:jlast) = dpresslat(jfirst:jlast)
     493             :     call mpi_allgatherv( temp(jfirst:jlast), cnt, mpi_double_precision, &
     494       32256 :                          dpresslat, numrecv,   displs, mpi_double_precision, mpicom, ierr )
     495       32256 :     if( ierr /= mpi_success ) then
     496           0 :        write(iulog,*) 'do_press_fix_llnl: mpi_allgatherv failed; error code = ',ierr
     497           0 :        call endrun
     498             :     end if
     499             : #endif
     500             : 
     501     6225408 :     dpress_g = sum( dpresslat(:) )
     502       32256 :     if( grid%iam == 0 ) then
     503          42 :        write(iulog,*) 'do_press_fix_llnl: dpress_g = ',dpress_g
     504             :     end if
     505             : 
     506             : !-----------------------------------------------------------------------
     507             : !     calculate mean meridional flux divergence (df/dy).
     508             : !     note that mmfd is actually the zonal mean pressure change,
     509             : !     which is related to df/dy by geometrical factors.
     510             : !-----------------------------------------------------------------------
     511             : !-----------------------------------------------------------------------
     512             : !       ... handle non-pole regions.
     513             : !-----------------------------------------------------------------------
     514       32256 :     factor = D1_0/im
     515      129024 :     do j = jfirst,jlast
     516    27998208 :        mmfd(j) = dpress_g - sum( ddps(:,j) ) * factor
     517             :     end do
     518             : 
     519             : #ifdef SPMD
     520       32256 :     cnt = jlast - jfirst + 1
     521      129024 :     temp(jfirst:jlast) = mmfd(jfirst:jlast)
     522             :     call mpi_allgatherv( temp(jfirst:jlast), cnt, mpi_double_precision, &
     523       32256 :          mmfd, numrecv, displs, mpi_double_precision, mpicom, ierr )
     524       32256 :     if( ierr /= mpi_success ) then
     525           0 :        write(iulog,*) 'do_press_fix_llnl: mpi_allgatherv failed; error code = ',ierr
     526           0 :        call endrun
     527             :     end if
     528             : #endif
     529             : 
     530             : !-----------------------------------------------------------------------
     531             : !     calculate mean meridional fluxes (cosp*fy).
     532             : !     nb: this calculation is being done for global lats, i.e., (1,jm)
     533             : !-----------------------------------------------------------------------
     534       32256 :     mmf(2) = mmfd(1) / (grid%rcap*im)
     535     6160896 :     do j = 2,jm-1
     536     6160896 :        mmf(j+1) = mmf(j) + mmfd(j) * grid%cosp(j)
     537             :     end do
     538             : 
     539             : !-----------------------------------------------------------------------
     540             : !     fix latitude bands.
     541             : !     note that we do not need to worry about geometry here because
     542             : !     all boxes in a latitude band are identical.
     543             : !     note also that fxintegral(im+1) should equal fxintegral(1),
     544             : !     i.e., zero.
     545             : !-----------------------------------------------------------------------
     546             : !$omp parallel do private( i, j, k, fxmean, fxintegral )
     547      128016 :     do j = js2g0,jn2g0
     548       95760 :        fxintegral(1) = D0_0
     549    27674640 :        do i = 1,im
     550    27674640 :           fxintegral(i+1)  = fxintegral(i) - (ddps(i,j) - dpress_g) - mmfd(j)
     551             :        end do
     552       95760 :        fxintegral(1)       = fxintegral(im+1)
     553    27770400 :        fxmean              = sum( fxintegral(:im) ) * factor
     554    27706896 :        xcolmass_fix(:im,j) = fxintegral(:im) - fxmean
     555             :     end do
     556             : !$omp end parallel do
     557             : 
     558             : !-----------------------------------------------------------------------
     559             : !       ... distribute colmass_fix in vertical
     560             : !-----------------------------------------------------------------------
     561             : !$omp parallel do private( j, k )
     562      182784 :     do k = kfirst,klast
     563      597408 :        do j = js2g0,jn2g0
     564   129298848 :           mfx(:,j,k) = mfx(:,j,k) +  met_rlx(k) * xcolmass_fix(:,j) * hybd(k)
     565             :        end do
     566      745584 :        do j = js2g0,jn2g1
     567   172121712 :           mfy(:,j,k) = mfy(:,j,k) +  met_rlx(k) * mmf(j) * hybd(k)
     568             :        end do
     569      182784 :        if( jlast == jm ) then
     570      679728 :           mfy(:,jm,k) = mfy(:,jm,k) +  met_rlx(k) * mmf(jm) * hybd(k)
     571             :        end if
     572             :     end do
     573             : !$omp end parallel do
     574             : 
     575       32256 :   end subroutine do_press_fix_llnl
     576             : 
     577             : end module pfixer

Generated by: LCOV version 1.14