⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 highp2.f90

📁 CCSM Research Tools: Community Atmosphere Model (CAM)
💻 F90
字号:
#include <misc.h>!-----------------------------------------------------------------------!BOP! !ROUTINE: highp2 --- Compute finite-volume mean pressure forces!                     using more accurate contour decomposition!! !INTERFACE:      subroutine highp2(pk,   wz,    pzx,  pzy,        &                       pzz,  im,  jm,   km,            &                       jfirst,  jlast, kfirst, klast,  &                       klastp, nx )! !USES:      use precision      use pmgrid, only: npr_y, myid_z, npr_z, iam, strip3zatyj2,   &                        strip3zatypj1, strip3zatypj2#if defined (SPMD)      use spmd_dyn, only: comm_z      use parutilitiesmodule, only: pargatherreal, parscatterreal      use mod_comm, only: bufferpack3d, bufferunpack3d, buff_s, buff_r,   &                          mp_send, mp_recv, mp_barrier#endif      implicit none! !INPUT PARAMETERS:      integer im, jm, km, jfirst, jlast, kfirst, klast, klastp      integer nx                        ! # of pieces in longitude direction      real(r8) pk(im,jfirst-1:jlast+1,kfirst:klast+1)      real(r8) wz(im,jfirst-1:jlast+1,kfirst:klast+1) ! !OUTPUT PARAMETERS      real(r8) pzx(im,jfirst-1:jlast  ,kfirst:klast+1)        real(r8) pzy(im,jfirst  :jlast+1,kfirst:klast+1)       real(r8) pzz(im,jfirst-1:jlast+1,kfirst:klast)! ! !DESCRIPTION:! Note: this routine needs to be further optimized for speed.!! !REVISION HISTORY:!  AAM    01.06.27     Institute 2D decomposition!  WS     02.01.15     Transitioned to mod_comm!!EOP!---------------------------------------------------------------------!BOC! Local:      integer i, j, k      integer ixj, jp, it, i1, i2      real(r8) pka(km+1)      real(r8) pkb(km+1)      real(r8) wza(km+1)      real(r8) wzb(km+1)      real(r8) pf(km+1)      real(r8) pza(km)      real(r8) pzb(km)      real(r8) dka(km)      real(r8) dkb(km)      real(r8)    tmp      integer im1      integer js1g1      integer js2g0!     integer js2g1      integer jn2g0      integer jn1g1!! Additional variables for yz decomposition!      real (r8), allocatable:: pkz(:,:,:), wzz(:,:,:), pzxz(:,:,:),  &            pzyz(:,:,:), pzzz(:,:,:)      real (r8), allocatable:: pky(:,:,:), wzy(:,:,:), pzxy(:,:,:),  &            pzyy(:,:,:)#if defined(SPMD)      integer incount, outcount#endif      allocate(pkz(im,jfirst-1:jlast+1,km+1))      allocate(wzz(im,jfirst-1:jlast+1,km+1))      allocate(pzxz(im,jfirst-1:jlast,km+1))      allocate(pzyz(im,jfirst:jlast+1,km+1))      allocate(pzzz(im,jfirst-1:jlast+1,km))#if defined(SPMD)      allocate(pky(im,jfirst-1:jlast+1,kfirst:klastp))      allocate(wzy(im,jfirst-1:jlast+1,kfirst:klastp))      allocate(pzxy(im,jfirst-1:jlast,kfirst:klastp))      allocate(pzyy(im,jfirst:jlast+1,kfirst:klastp))#endif!! Gather pk,wz into full z arrays!#if defined(SPMD)      if (myid_z .eq. 0) then#endif!$omp  parallel do     &!$omp  default(shared) &!$omp  private(i,j,k)        do k = kfirst, klast+1        do j = jfirst-1, jlast+1        do i = 1, im          pkz(i,j,k) = pk(i,j,k)          wzz(i,j,k) = wz(i,j,k)        enddo        enddo        enddo#if defined(SPMD)      endif#endif#if defined(SPMD)      if (npr_z .gt. 1) then        do k = kfirst, klastp        do j = jfirst-1, jlast+1        do i = 1, im          pky(i,j,k) = pk(i,j,k)          wzy(i,j,k) = wz(i,j,k)        enddo        enddo        enddo        call pargatherreal( comm_z, 0, pky, strip3zatypj2, pkz)        call pargatherreal( comm_z, 0, wzy, strip3zatypj2, wzz)      endif#endif      js1g1  = max(1,jfirst-1)! E-W PG!     js2g1  = max(2,jfirst-1)      jn2g0  = min(jm-1,jlast)! N-S PG      js2g0  = max(2,jfirst)      jn1g1  = min(jm,jlast+1)      it = im / nx      jp = nx * ( jn1g1 - js1g1  + 1 )!$omp  parallel do           &!$omp  default(shared)       &!$omp  private(i1, i2, ixj, i, j, k, tmp, pka, pkb, pf) &!$omp  private(pza, pzb, wza, wzb, dka, dkb, im1)      do 1000 ixj=1, jp! ***! E-W! ***         j  = js1g1 + (ixj-1)/nx         i1 = 1 + it * mod(ixj-1, nx)         i2 = i1 + it - 1        do i=i1,i2        if( i .eq. i1 ) then           if ( i .eq. 1) then              im1 = im           else              im1 = i-1           endif         do k=1,km+1           pka(k) =  pkz(im1,j,k)           wza(k) =  wzz(im1,j,k)        enddo        do k=1,km           dka(k) =  pka(k+1) - pka(k)           pza(k) = 0.5*(wza(k)-wza(k+1))*(pka(k+1)+pka(k))        enddo        else        do k=1,km+1           pka(k) = pkb(k)           wza(k) = wzb(k)        enddo        do k=1,km           pza(k) = pzb(k)           dka(k) = dkb(k)        enddo        endif        do k=1,km+1           pkb(k) = pkz(i,j,k)           wzb(k) = wzz(i,j,k)        enddo        do k=1,km           dkb(k) = pkb(k+1) - pkb(k)           tmp    = (wzb(k)-wzb(k+1))*(pkb(k+1)+pkb(k))           pzb(k) = 0.5*tmp           pzzz(i,j,k) = tmp        enddo        if ( j .le. jn2g0 ) then        call pxt3 (km,   pf,   pka,  pkb,  wza,  wzb, &                   pza,  pzb,  dka,  dkb )        do k=1,km+1           pzxz(i,j,k) = pf(k)        enddo        endif! ***! N-S! ***! N <-- E at (i,j)        if ( j .ge. js2g0 ) then        do k=1,km+1           pka(k) = pkz(i,j-1,k)           wza(k) = wzz(i,j-1,k)        enddo        do k=1,km           dka(k) = pka(k+1) - pka(k)           pza(k) = 0.5*(wza(k)-wza(k+1))*(pka(k+1)+pka(k))         enddo! need pzy(js2g0:jn2g1)        call pxt3 (km,    pf,   pka,  pkb,  wza,  wzb,  &                   pza,  pzb,   dka,  dkb )        do k=1,km+1           pzyz(i,j,k) = pf(k)        enddo        endif        enddo                  ! i-loop1000  continue!! Scatter pz[xyz]z into local arrays!#if defined(SPMD)      if (myid_z .eq. 0) then#endif!$omp  parallel do     &!$omp  default(shared) &!$omp  private(i,j,k)        do k = kfirst, klast+1        do j = jfirst-1, jlast        do i = 1, im          pzx(i,j,k) = pzxz(i,j,k)          pzy(i,j+1,k) = pzyz(i,j+1,k)        enddo        enddo        enddo!$omp  parallel do      &!$omp  default(shared)  &!$omp  private(i,j,k)        do k = kfirst, klast        do j = jfirst-1, jlast+1        do i = 1, im          pzz(i,j,k) = pzzz(i,j,k)        enddo        enddo        enddo#if defined(SPMD)      endif#endif#if defined(SPMD)      if (npr_z .gt. 1) then        call parscatterreal(comm_z, 0, pzxz, strip3zatypj1, pzxy)        call parscatterreal(comm_z, 0, pzyz, strip3zatypj1, pzyy)        call parscatterreal(comm_z, 0, pzzz, strip3zatyj2, pzz)        if (myid_z .ne. 0) then!$omp  parallel do      &!$omp  default(shared)  &!$omp  private(i,j,k)          do k = kfirst, klastp          do j = jfirst-1, jlast          do i = 1, im            pzx(i,j,k) = pzxy(i,j,k)            pzy(i,j+1,k) = pzyy(i,j+1,k)          enddo          enddo          enddo        endif! Fill in klast+1        incount = 0        outcount = 0        if (kfirst .gt. 1) then          call bufferpack3d(pzx, 1, im, jfirst-1, jlast, kfirst, klast+1,  &                            1, im, jfirst-1, jlast, kfirst, kfirst, buff_s)          incount = im * (jlast-jfirst+2)          call bufferpack3d(pzy, 1, im, jfirst, jlast+1, kfirst, klast+1,  &                            1, im, jfirst, jlast+1, kfirst, kfirst,  &                            buff_s(incount+1))          incount = incount + im * (jlast-jfirst+2)        endif        if (klast .lt. km) then          outcount = 2 * im * (jlast-jfirst+2)        endif        call mp_barrier()        call mp_send(iam-npr_y,iam+npr_y,incount,outcount,buff_s,buff_r)        call mp_barrier()        call mp_recv(iam+npr_y,outcount,buff_r)        if (klast .lt. km) then          call bufferunpack3d(pzx,1,im,jfirst-1,jlast,kfirst,klast+1,    &                              1,im,jfirst-1,jlast,klast+1,klast+1,buff_r)          outcount = im * (jlast-jfirst+2)          call bufferunpack3d( pzy,1,im,jfirst,jlast+1,kfirst,klast+1,   &                               1,im,jfirst,jlast+1,klast+1,klast+1,      &                               buff_r(outcount+1) )        endif      endif#endif#if defined(SPMD)      deallocate(pky)      deallocate(wzy)      deallocate(pzxy)      deallocate(pzyy)#endif      deallocate(pkz)      deallocate(wzz)      deallocate(pzxz)      deallocate(pzyz)      deallocate(pzzz)      return!EOC      end      subroutine pxt3(km,  pf,  pka, pkb, wza, wzb, pza, pzb, &                      dka, dkb ) ! Compute pressure forcing along "horizontal" coordinate surface! for a single column! !USES:      use precision      implicit none      integer km ! Input      real(r8) pka(km+1)     ! p**kappa at the west side of the box      real(r8) pkb(km+1)      real(r8) wza(km+1)      real(r8) wzb(km+1)      real(r8) pza(km)      real(r8) pzb(km)      real(r8) dka(km)      real(r8) dkb(km)! Output      real(r8)  pf(km+1)! Local      integer k      integer ka      integer kb      integer kk      integer kt      real(r8) wa      real(r8) wb      real(r8) tmp      logical found      pf(1) = -(pka(1) + pkb(1))*(wzb(1) - wza(1))         ka = km/2         kb = km/2      do 1000 k=2,km+1          wa = 0.          wb = 0.      if( wzb(k) .gt. wza(k) ) then!!                     * ---->  wzb(k)!                    /!                   /!                  /!                 /!                /!               /!              /!             /!            /!           /!          /!         /!        /!       /!      /!     /!    * ----> wza(k)!! Compute wa (along left edge)!! Top      if(wzb(k) .gt. wza(1)) then          wa = 0.5*(pkb(k)+pka(k))*(wzb(k)-wza(k))! DEBUG!        write(*,*) 'pxt3: ', wa!        stop! DEBUG      else            kk = k            found = .false.         do while (.not. found )            if(wzb(k) .le. wza(kk-1) .and.       &               wzb(k) .ge. wza(kk)       )  then!! find p**cappa at left edge (side A) at height wzb(k)!               tmp = pka(kk-1) + dka(kk-1) *     &                    (wza(kk-1)-wzb(k))/(wza(kk-1)-wza(kk))               wa = wa + 0.5*(wzb(k)-wza(kk))*(pka(kk)+tmp)               found = .true.            else               wa  = wa + pza(kk-1)               kk = kk - 1            endif         enddo      endif! Compute wb         if( k .ne. (km+1)) then            do kk=k,km               if( wza(k) .le. wzb(kk)   .and.    &                   wza(k) .ge. wzb(kk+1)      ) then                   tmp = pkb(kk) + dkb(kk)*(wzb(kk)-wza(k)) &                                 / (wzb(kk)-wzb(kk+1))                      wb = wb + 0.5*(tmp+pkb(kk))*(wzb(kk)-wza(k))                   goto 222               else                  wb = wb + pzb(kk)               endif            enddo222      continue         endif        ! k safety check         if( wza(k) .lt. wzb(km+1)) then! Integrate down along the left edge!!            do kk=kb,k-1            if( wzb(km+1) .le. wza(kk)   .and.    &                wzb(km+1) .ge. wza(kk+1)      ) then                tmp = pka(kk) + dka(kk)*(wza(kk)-wzb(km+1)) &                              / (wza(kk)-wza(kk+1))                wb = wb + 0.5*(pka(kk+1)+tmp)*(wzb(km+1)-wza(kk+1))                if( kk .le. k-2) then                    do kt=kk+1, k-1                       wb = wb + pza(kt)                    enddo                endif                kb = kk                goto 444            endif            enddo444      continue         endif      elseif( wzb(k) .lt. wza(k) ) then!============================! for wzb(k) .lt. wza(k) !============================! Compute wa         if(k .ne. km+1) then            do kk=k,km               if( wzb(k) .le. wza(kk)   .and.   &                   wzb(k) .ge. wza(kk+1)      ) then                   tmp = pka(kk) + dka(kk)*(wza(kk)-wzb(k)) &                                         / (wza(kk)-wza(kk+1))                   wa = wa - 0.5*(tmp+pka(kk))*(wza(kk)-wzb(k))                  goto 666               else                  wa  = wa - pza(kk)               endif            enddo666      continue         endif        ! k safety check         if( wzb(k) .lt. wza(km+1)) then! Integrate  down along the right edge!!            do kk=ka,k-1              if( wza(km+1) .le. wzb(kk)   .and.    &                  wza(km+1) .ge. wzb(kk+1)   ) then                  tmp = pkb(kk) + dkb(kk)*(wzb(kk)-wza(km+1)) &                                        / (wzb(kk)-wzb(kk+1))                  wa = wa - 0.5*(tmp+pkb(kk+1))*(wza(km+1)-wzb(kk+1))                  if(kk .le. k-2) then                     do kt=kk+1, k-1                        wa  = wa - pzb(kt)                     enddo                  endif                  ka = kk                 goto 777              endif            enddo777      continue         endif! Top       if(wza(k) .gt. wzb(1)) then           wb = 0.5*(pkb(k)+pka(k))*(wzb(k)-wza(k))! DEBUG!         write(*,*) 'pxt3: ', wb!         stop! DEBUG       else          do kk=k,2,-1             if(wza(k) .le. wzb(kk-1) .and.    &                wza(k) .ge. wzb(kk)       )  then                tmp = pkb(kk-1)+dkb(kk-1)*(wzb(kk-1)-wza(k)) &                                       / (wzb(kk-1)-wzb(kk))                wb = wb + 0.5*(tmp+pkb(kk))*(wzb(kk)-wza(k))                goto 999             else                wb  = wb - pzb(kk-1)             endif         enddo999     continue       endif   ! end top checck      endif      pf(k) = -(wa + wb) 1000  continue      return      end

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -