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

📄 phcs.f90

📁 CCSM Research Tools: Community Atmosphere Model (CAM)
💻 F90
字号:
#include <misc.h>#include <params.h>subroutine phcs(pmn     ,hmn     ,ix      ,x1)!----------------------------------------------------------------------- ! ! Purpose: ! Compute associated Legendre functions of the first kind of order m and! degree n, and the associated derivatives for arg x1.! Method: ! Compute associated Legendre functions of the first kind of order m and! degree n, and the associated derivatives for arg x1.  The associated! Legendre functions are evaluated using relationships contained in! "Tables of Normalized Associated Legendre Polynomials",! S. L. Belousov (1962).  Both the functions and their derivatives are! ordered in a linear stored rectangular array (with a large enough! domain to contain the particular wavenumber truncation defined in the! pspect common block) by column. m = 0->ptrm, and  n = m->ptrn + m !                m! The functions P (x) are normalized such that !                n!                          /   m     2!                          | [P  (x)] dx = 1/2!                          /   n!                             __! and must be multiplied by  |2  to match Belousov tables.!                           \|!                  m! The derivatives H (x) are defined as !                  n        m           2    m!                          H (x) = -(1-x ) dP (x)/dx!                           n                n!! and are evaluated using the recurrence relationship!                          _________________________!      m          m       |  2   2                     m!     H (x) = nx P (x) -  |(n - m )(2n + 1)/(2n - 1)  P   (x)!      n          n      \|                            n-1!! Modified 1/23/97 by Jim Rosinski to use real*16 arithmetic in order to ! achieve (nearly) identical values on all machines.! ! Author: CCM1! !-----------------------------------------------------------------------!! $Id: phcs.F90,v 1.1 2001/11/06 18:42:49 erik Exp $! $Author: erik $!!-----------------------------------------------------------------------  use precision  use pmgrid  use pspect  implicit none!------------------------------Arguments--------------------------------  integer , intent(in)  :: ix       ! Dimension of Legendre funct arrays  real(r8), intent(in)  :: x1       ! sin of latitude, [sin(phi), or mu]  real(r8), intent(out) ::  pmn(ix) ! Legendre function array  real(r8), intent(out) ::  hmn(ix) ! Derivative array!-----------------------------------------------------------------------!---------------------------Local variables-----------------------------#ifdef PGF90  integer, parameter :: r16 = selected_real_kind(12)#else  integer, parameter :: r16 = selected_real_kind(17)#endif  integer jmax       ! Loop limit (N+1=> 2D wavenumber limit +1)  integer nmax       ! Large enough n to envelope truncation  integer n          ! 2-D wavenumber index (up/down column)  integer ml         ! intermediate scratch variable  integer k          ! counter on terms in trig series expansion  integer n2         ! 2*n  integer m          ! zonal wavenumber index  integer nto        ! intermediate scratch variable  integer mto        ! intermediate scratch variable  integer j          ! 2-D wavenumber index in recurrence evaluation  integer nmaxm      ! loop limit in recurrence evaluation  real(r16) xtemp(3,pmmax+ptrn+1)  ! Workspace for evaluating recurrence!                                    ! relation where xtemp(m-2,n) and!                                    ! xtemp(m-1,n) contain Pmn's required !                                    ! to evaluate xtemp(m,n) (i.e.,always!                                    ! contains three adjacent columns of!                                    ! the Pmn data structure)!  real(r16) xx1        ! x1 in extended precision  real(r16) xte        ! cosine latitude [cos(phi)]  real(r16) teta       ! pi/2 - latitute (colatitude)  real(r16) an         ! coefficient on trig. series expansion  real(r16) sinpar     ! accumulator in trig. series expansion   real(r16) cospar     ! accumulator in trig. series expansion   real(r16) p          ! 2-D wavenumber (series expansion)  real(r16) q          ! intermediate variable in series expansion   real(r16) r          ! zonal wavenumber (recurrence evaluation)  real(r16) p2         ! intermediate variable in series expansion   real(r16) rr         ! twice the zonal wavenumber (recurrence)  real(r16) sqp        ! intermediate variable in series expansion   real(r16) cosfak     ! coef. on cos term in series expansion  real(r16) sinfak     ! coef. on sin term in series expansion  real(r16) ateta      ! intermediate variable in series expansion   real(r16) costet     ! cos term in trigonometric series expansion  real(r16) sintet     ! sin term in trigonometric series expansion!  real(r16) t          ! intermediate variable (recurrence evaluation)  real(r16) wm2        ! intermediate variable (recurrence evaluation)  real(r16) wmq2       ! intermediate variable (recurrence evaluation)  real(r16) w          ! intermediate variable (recurrence evaluation)  real(r16) wq         ! intermediate variable (recurrence evaluation)  real(r16) q2         ! intermediate variable (recurrence evaluation)  real(r16) wt         ! intermediate variable (recurrence evaluation)  real(r16) q2d        ! intermediate variable (recurrence evaluation)  real(r16) cmn        ! cmn  recurrence coefficient (see Belousov)  real(r16) xdmn       ! dmn  recurrence coefficient (see Belousov)  real(r16) emn        ! emn  recurrence coefficient (see Belousov)  real(r16) n2m1       ! n2 - 1 in extended precision  real(r16) n2m3       ! n2 - 3 in extended precision  real(r16) n2p1nnm1   ! (n2+1)*(n*n-1) in extended precision  real(r16) twopmq     ! p + p - q in extended precision!-----------------------------------------------------------------------!! Begin procedure by evaluating the first two columns of the Legendre! function matrix (i.e., all n for m=0,1) via a trigonometric series ! expansion (see eqs. 19 and 21 in Belousov, 1962).  Note that indexing! is offset by one (e.g., m index for wavenumber m=0 is 1 and so on)! Setup first ...!  xx1  = x1  jmax = ptrn + 1  nmax = pmmax + jmax  xte = sqrt(1.-xx1*xx1)  teta = acos(xx1)  an = 1.  xtemp(1,1) = 0.5    ! P00!! begin loop over n (2D wavenumber, or degree of associated Legendre ! function) beginning with n=1 (i.e., P00 was assigned above)! note n odd/even distinction yielding 2 results per n cycle!  do n=2,nmax     sinpar = 0.     cospar = 0.     ml = n     p = n - 1     p2 = p*p     sqp = 1./sqrt(p2+p)     an = an*sqrt(1. - 1./(4.*p2))     cosfak = 1.     sinfak = p*sqp     do k=1,ml,2        q = k - 1        twopmq = p + p - q        ateta = (p-q)*teta        costet = cos(ateta)        sintet = sin(ateta)        if (n==k) costet = costet*0.5        if (k/=1) then           cosfak = (q-1.)/q*(twopmq+2.)/(twopmq+1.)*cosfak           sinfak = cosfak*(p-q)*sqp        end if        cospar = cospar + costet*cosfak        sinpar = sinpar + sintet*sinfak     end do     xtemp(1,n)   = an*cospar      ! P0n vector     xtemp(2,n-1) = an*sinpar      ! P1n vector  end do!! Assign Legendre functions and evaluate derivatives for all n and m=0,1!  pmn(1) = 0.5  pmn(1+jmax) = xtemp(2,1)  hmn(1) = 0.  hmn(1+jmax) = xx1*xtemp(2,1)  do n=2,jmax     pmn(n) = xtemp(1,n)     pmn(n+jmax) = xtemp(2,n)     n2 = n + n     n2m1 = n2 - 1     n2m3 = n2 - 3     n2p1nnm1 = (n2+1)*(n*n-1)     hmn(n) = (n-1)*(xx1*xtemp(1,n)-sqrt(n2m1/n2m3)*xtemp(1,n-1))     hmn(n+jmax) = n*xx1*xtemp(2,n)-sqrt(n2p1nnm1/n2m1)*xtemp(2,n-1)  end do!! Evaluate recurrence relationship for remaining Legendre functions! (i.e., m=2 ... PTRM) and associated derivatives (see eq 17, Belousov)!  do m=3,pmmax     r = m - 1     rr = r + r     xtemp(3,1) = sqrt(1.+1./rr)*xte*xtemp(2,1)     nto = (m-1)*jmax     pmn(nto+1) = xtemp(3,1)     hmn(nto+1) = r*xx1*xtemp(3,1)     nmaxm = nmax - m!! Loop over 2-D wavenumber (i.e., degree of Legendre function)! Pmn's and Hmn's for current zonal wavenumber, r!     do j=2,nmaxm        mto = nto + j        t = j - 1        q = rr + t - 1        wm2 = q + t        w = wm2 + 2        wq = w*q        q2 = q*q - 1        wmq2 = wm2*q2        wt = w*t        q2d = q2 + q2        cmn = sqrt((wq*(q-2.))/(wmq2-q2d))        xdmn = sqrt((wq*(t+1.))/wmq2)        emn = sqrt(wt/((q+1.)*wm2))        xtemp(3,j) = cmn*xtemp(1,j) - xx1*(xdmn*xtemp(1,j+1)-emn*xtemp(3,j-1))        pmn(mto) = xtemp(3,j)        hmn(mto) = (r+t)*xx1*xtemp(3,j) - sqrt(wt*(q+1.)/wm2)*xtemp(3,j-1)     end do!! shift Pmn's to left in workspace (setup for next recurrence pass)!!++pjr! not initialized above     xtemp(2,nmax) = 0.     do j=nmaxm,nmax        xtemp(3,j) = 0.     end do!--pjr     do n=1,nmax        xtemp(1,n) = xtemp(2,n)        xtemp(2,n) = xtemp(3,n)     end do  end do  returnend subroutine phcs

⌨️ 快捷键说明

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