LCOV - code coverage report
Current view: top level - dynamics/se/dycore - quadrature_mod.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 122 279 43.7 %
Date: 2025-01-13 21:54:50 Functions: 7 18 38.9 %

          Line data    Source code
       1             : #undef _GAUSS_TABLE
       2             : module quadrature_mod
       3             :   use shr_kind_mod,   only: r8=>shr_kind_r8
       4             : 
       5             :   implicit none
       6             :   private
       7             : 
       8             :   type, public :: quadrature_t
       9             :     real (kind=r8), dimension(:), pointer :: points
      10             :     real (kind=r8), dimension(:), pointer :: weights
      11             :   end type quadrature_t
      12             : 
      13             :   public  :: gausslobatto
      14             :   public  :: test_gausslobatto
      15             :   public  :: gauss
      16             :   public  :: test_gauss
      17             :   public  :: legendre
      18             :   public  :: jacobi
      19             :   public  :: quad_norm
      20             : 
      21             :   public  :: trapezoid
      22             :   private :: trapN
      23             :   public  :: simpsons
      24             :   public  :: gaussian_int
      25             : 
      26             :   private :: gausslobatto_pts
      27             :   private :: gausslobatto_wts
      28             :   private :: gauss_pts
      29             :   private :: gauss_wts
      30             :   private :: jacobi_polynomials
      31             :   private :: jacobi_derivatives
      32             : 
      33             : 
      34             : contains
      35             : 
      36             :   ! ==============================================================
      37             :   ! gauss:
      38             :   !
      39             :   ! Find the Gauss collocation points and the corresponding weights.
      40             :   !
      41             :   ! ==============================================================
      42             : 
      43           0 :   function gauss(npts) result(gs)
      44             :     integer, intent(in) :: npts
      45             :     type (quadrature_t) :: gs
      46             : 
      47           0 :     allocate(gs%points(npts))
      48           0 :     allocate(gs%weights(npts))
      49             : 
      50           0 :     gs%points=gauss_pts(npts)
      51           0 :     gs%weights=gauss_wts(npts,gs%points)
      52             : 
      53           0 :   end function gauss
      54             : 
      55             : #if defined(_GAUSS_TABLE)
      56             :   function gauss_pts(npts) result(pts)
      57             : 
      58             :     integer, intent(in) :: npts
      59             :     real (kind=r8) :: pts(npts)
      60             : 
      61             :     pts(1) = -0.93246951420315202781_r8
      62             :     pts(2) = -0.66120938646626451366_r8
      63             :     pts(3) = -0.23861918608319690863_r8
      64             :     pts(4) = -pts(3)
      65             :     pts(5) = -pts(2)
      66             :     pts(6) = -pts(1)
      67             : 
      68             :   end function gauss_pts
      69             : 
      70             : 
      71             :   function gauss_wts(npts,pts) result(wts)
      72             : 
      73             :     integer, intent(in) :: npts
      74             :     real (kind=r8) :: pts(npts)
      75             :     real (kind=r8) :: wts(npts)
      76             : 
      77             :     wts(1)  =  0.17132449237917034504_r8
      78             :     wts(2)  =  0.36076157304813860756_r8
      79             :     wts(3)  =  0.46791393457269104738_r8
      80             :     wts(4)  =  wts(3)
      81             :     wts(5)  =  wts(2)
      82             :     wts(6)  =  wts(1)
      83             : 
      84             :   end function gauss_wts
      85             : #else
      86             : 
      87             :   ! ==============================================================
      88             :   ! gauss_pts:
      89             :   !
      90             :   ! Compute the Gauss Collocation points
      91             :   ! for Jacobi Polynomials
      92             :   !
      93             :   ! ==============================================================
      94             : 
      95           0 :   function gauss_pts(np1) result(pts)
      96             :     use physconst, only: pi
      97             : 
      98             :     integer, intent(in)     :: np1        ! Number of velocity grid points
      99             :     real (kind=r8) :: pts(np1)
     100             : 
     101             :     ! Local variables
     102             : 
     103             :     real (kind=r8) :: alpha,beta
     104           0 :     real (kind=r8) :: xjac(0:np1-1)
     105           0 :     real (kind=r8) :: jac(0:np1)
     106           0 :     real (kind=r8) :: djac(0:np1)
     107             : 
     108             :     integer  prec                    ! number of mantissa bits
     109             :     real (kind=r8) eps      ! machine epsilon
     110             :     real (kind=r8), parameter :: convthresh = 10  ! convergence threshold relative\
     111             : 
     112             :     ! to machine epsilon
     113             :     integer, parameter :: kstop = 30 ! max iterations for polynomial deflation
     114             : 
     115             :     real (kind=r8) :: poly
     116             :     real (kind=r8) :: pder
     117             :     real (kind=r8) :: recsum,thresh
     118             :     real (kind=r8) :: dth
     119             : 
     120             :     real (kind=r8) :: x
     121             :     real (kind=r8) :: delx
     122             :     real (kind=r8) :: c0,c1,c2,c10
     123             : 
     124             :     integer i,j,k
     125             :     integer n, nh
     126             : 
     127           0 :     n  = np1 - 1
     128           0 :     c0 = 0.0_r8
     129           0 :     c1 = 1.0_r8
     130           0 :     c2 = 2.0_r8
     131           0 :     c10 = 10.0_r8
     132           0 :     alpha = c0
     133           0 :     beta  = c0
     134             : 
     135             :     ! =========================================================
     136             :     ! compute machine precision and set the convergence
     137             :     ! threshold thresh to 10 times that level
     138             :     ! =========================================================
     139             : 
     140           0 :     prec   = precision(c10)
     141           0 :     eps    = c10**(-prec)
     142           0 :     thresh = convthresh*eps
     143             : 
     144             :     ! ============================================================
     145             :     ! Compute first half of the roots by "polynomial deflation".
     146             :     ! ============================================================
     147             : 
     148           0 :     dth = PI/(2*n+2)
     149             : 
     150           0 :     nh  = (n+1)/2
     151             : 
     152           0 :     do j=0,nh-1
     153           0 :        x=COS((c2*j+1)*dth)          ! first guess at root
     154           0 :        k=0
     155           0 :        delx=c1
     156           0 :        do while(k<kstop .and. ABS(delx) > thresh)
     157           0 :           call jacobi(n+1,x,alpha,beta,jac(0:n+1),djac(0:n+1))
     158           0 :           poly =  jac(n+1)
     159           0 :           pder = djac(n+1)
     160           0 :           recsum=c0
     161           0 :           do i=0,j-1
     162           0 :              recsum = recsum + c1/(x-xjac(i))
     163             :           end do
     164           0 :           delx = -poly/(pder-recsum*poly)
     165           0 :           x = x + delx
     166           0 :           k = k + 1
     167             :        end do
     168             : 
     169           0 :        xjac(j)=x
     170             : 
     171             :     end do
     172             : 
     173             :     ! ================================================
     174             :     ! compute the second half of the roots by symmetry
     175             :     ! ================================================
     176             : 
     177           0 :     do j=0,nh
     178           0 :        xjac(n-j) = -xjac(j)
     179             :     end do
     180             : 
     181           0 :     if (MODULO(n,2)==0) xjac(nh)=c0
     182             : 
     183             :     ! ====================================================
     184             :     ! Reverse the sign of everything so that indexing
     185             :     ! increases with position
     186             :     ! ====================================================
     187             : 
     188           0 :     do j=0,n
     189           0 :        pts(j+1) = -xjac(j)
     190             :     end do
     191             : 
     192           0 :   end function gauss_pts
     193             : 
     194             :   ! ================================================
     195             :   ! gauss_wts:
     196             :   !
     197             :   ! Gauss Legendre Weights
     198             :   ! ================================================
     199             : 
     200           0 :   function gauss_wts(np1, gpts) result(wts)
     201             : 
     202             :     integer, intent(in)                 :: np1
     203             :     real (kind=r8), intent(in) :: gpts(np1)  ! Gauss-Legendre points
     204             :     real (kind=r8)             :: wts(np1)   ! Gauss-Legendre weights
     205             : 
     206             :     ! Local variables
     207             : 
     208             :     real (kind=r8) :: c0,c1,c2
     209             :     real (kind=r8) :: alpha
     210             :     real (kind=r8) :: beta
     211           0 :     real (kind=r8) :: djac(np1)
     212             :     integer i,n
     213             : 
     214           0 :     c0    = 0.0_r8
     215           0 :     c1    = 1.0_r8
     216           0 :     c2    = 2.0_r8
     217             : 
     218           0 :     alpha = c0
     219           0 :     beta  = c0
     220           0 :     n     = np1-1
     221             : 
     222           0 :     djac=jacobi_derivatives(np1,alpha,beta,np1,gpts)     
     223             : 
     224           0 :     do i=1,np1
     225           0 :        wts(i)=c2/((c1-gpts(i)**2)*djac(i)*djac(i))
     226             :     end do
     227             : 
     228           0 :   end function gauss_wts
     229             : 
     230             : #endif
     231             : 
     232             :   ! ==============================================================
     233             :   ! test_gauss:
     234             :   !
     235             :   ! Unit Tester for Gaussian Points, Weights
     236             :   ! ==============================================================
     237             : 
     238           0 :   subroutine test_gauss(npts)
     239             : 
     240             :     integer, intent(in) :: npts
     241             :     type (quadrature_t) :: gs
     242             : 
     243             :     integer i
     244             :     real (kind=r8) :: gssum
     245           0 :     gs=gauss(npts)
     246             : 
     247           0 :     print *
     248           0 :     print *,"============================================"
     249           0 :     print *,"        Testing Gaussian Quadrature..."
     250           0 :     print *
     251           0 :     print *,"          points              weights"
     252           0 :     print *,"============================================"
     253           0 :     do i=1,npts
     254           0 :        print *,i,gs%points(i),gs%weights(i)
     255             :     end do
     256           0 :     print *,"============================================"
     257           0 :     gssum=SUM(gs%weights(:))
     258           0 :     print *,"sum of Gaussian weights=",gssum
     259           0 :     print *,"============================================"
     260             : 
     261           0 :     deallocate(gs%points)
     262           0 :     deallocate(gs%weights)
     263             : 
     264           0 :   end subroutine test_gauss
     265             : 
     266             :   ! ==============================================================
     267             :   ! gausslobatto:
     268             :   !
     269             :   ! Find the Gauss-Lobatto Legendre collocation points xgl(i) and the
     270             :   ! corresponding weights.
     271             :   !
     272             :   ! ==============================================================
     273             : 
     274     2622024 :   function gausslobatto(npts) result(gll)
     275             : 
     276             :     integer, intent(in) :: npts
     277             :     type (quadrature_t) :: gll
     278             : 
     279     7866072 :     allocate(gll%points(npts))
     280     5244048 :     allocate(gll%weights(npts))
     281             : 
     282    13110120 :     gll%points=gausslobatto_pts(npts)
     283    15732144 :     gll%weights=gausslobatto_wts(npts,gll%points)
     284             : 
     285     2622024 :   end function gausslobatto
     286             : 
     287             :   ! ==============================================================
     288             :   ! gausslobatto_pts:
     289             :   !
     290             :   ! Compute the Gauss-Lobatto Collocation points 
     291             :   ! for Jacobi Polynomials
     292             :   !
     293             :   ! ==============================================================
     294             : 
     295     5244048 :   function gausslobatto_pts(np1) result(pts)
     296             :     use physconst, only: pi
     297             : 
     298             :     integer, intent(in)     :: np1        ! Number of velocity grid points
     299             :     real (kind=r8) :: pts(np1)
     300             : 
     301             :     ! Local variables
     302             : 
     303             :     real (kind=r8) :: alpha,beta
     304     5244048 :     real (kind=r8) :: xjac(0:np1-1)
     305     5244048 :     real (kind=r8) :: jac(0:np1)
     306     5244048 :     real (kind=r8) :: jacm1(0:np1)
     307     2622024 :     real (kind=r8) :: djac(0:np1)
     308             : 
     309             :     integer  prec                    ! number of mantissa bits 
     310             :     real (kind=r8) eps      ! machine epsilon
     311             :     real (kind=r8), parameter :: convthresh = 10  ! convergence threshold relative 
     312             :     ! to machine epsilon 
     313             :     integer, parameter :: kstop = 30 ! max iterations for polynomial deflation
     314             : 
     315             :     real (kind=r8) :: a,b,det
     316             :     real (kind=r8) :: poly
     317             :     real (kind=r8) :: pder
     318             :     real (kind=r8) :: recsum,thresh
     319             :     real (kind=r8) :: dth,cd,sd,cs,ss,cstmp
     320             : 
     321             :     real (kind=r8) :: x
     322             :     real (kind=r8) :: delx
     323             :     real (kind=r8) :: c0,c1,c2,c10
     324             : 
     325             :     integer i,j,k
     326             :     integer n, nh
     327             : 
     328     2622024 :     n  = np1 - 1
     329     2622024 :     c0 = 0.0_r8
     330     2622024 :     c1 = 1.0_r8
     331     2622024 :     c2 = 2.0_r8
     332     2622024 :     c10 = 10.0_r8
     333             : 
     334     2622024 :     alpha = c0
     335     2622024 :     beta  = c0
     336             : 
     337             :     ! =========================================================
     338             :     ! compute machine precision and set the convergence
     339             :     ! threshold thresh to 10 times that level 
     340             :     ! =========================================================
     341             : 
     342     2622024 :     prec   = PRECISION(c10)
     343     2622024 :     eps    = c10**(-prec)
     344     2622024 :     thresh = convthresh*eps
     345             : 
     346             :     ! =====================================================
     347             :     ! initialize the end points
     348             :     ! =====================================================
     349             : 
     350     2622024 :     xjac(0) =  c1
     351     2622024 :     xjac(n) = -c1
     352             : 
     353             :     ! ============================================================
     354             :     ! Compute first half of the roots by "polynomial deflation".
     355             :     ! ============================================================
     356             : 
     357             :     ! ============================================================
     358             :     ! compute the parameters in the polynomial whose 
     359             :     ! roots are desired...
     360             :     ! ============================================================
     361             : 
     362     2622024 :     call jacobi(n+1, c1,alpha,beta,jac(0:n+1),djac(0:n+1))
     363     2622024 :     call jacobi(n+1,-c1,alpha,beta,jacm1(0:n+1),djac(0:n+1))
     364             : 
     365     2622024 :     det =   jac(n  )*jacm1(n-1)-jacm1(n  )*jac(n-1)
     366     2622024 :     a   = -(jac(n+1)*jacm1(n-1)-jacm1(n+1)*jac(n-1))/det
     367     2622024 :     b   = -(jac(n  )*jacm1(n+1)-jacm1(n  )*jac(n+1))/det
     368             : 
     369     2622024 :     dth = PI/(2*n+1)
     370     2622024 :     cd  = COS(c2*dth)
     371     2622024 :     sd  = SIN(c2*dth)
     372     2622024 :     cs  = COS(dth)
     373     2622024 :     ss  = SIN(dth)
     374             : 
     375     2622024 :     nh  = (n+1)/2
     376             : 
     377     5244048 :     do j=1,nh-1
     378     2622024 :        x=cs          ! first guess at root 
     379     2622024 :        k=0
     380     2622024 :        delx=c1
     381    20976192 :        do while(k<kstop .and. ABS(delx) > thresh)
     382    18354168 :           call jacobi(n+1,x,alpha,beta,jac(0:n+1),djac(0:n+1))
     383    18354168 :           poly =  jac(n+1)+a* jac(n)+b* jac(n-1)
     384    18354168 :           pder = djac(n+1)+a*djac(n)+b*djac(n-1)
     385    18354168 :           recsum=c0
     386    36708336 :           do i=0,j-1
     387    36708336 :              recsum = recsum + c1/(x-xjac(i))
     388             :           end do
     389    18354168 :           delx = -poly/(pder-recsum*poly)
     390    18354168 :           x = x + delx
     391    18354168 :           k = k + 1
     392             :        end do
     393             : 
     394     2622024 :        xjac(j)=x
     395             : 
     396             :        ! =====================================================
     397             :        !  compute the guesses for the roots
     398             :        !  for the next points, i.e :
     399             :        !
     400             :        !  ss = sn(theta) => sin(theta+2*dth)
     401             :        !  cs = cs(theta) => cs(theta+2*dth)
     402             :        ! =====================================================
     403             : 
     404     2622024 :        cstmp=cs*cd-ss*sd      
     405     2622024 :        ss=cs*sd+ss*cd    
     406     5244048 :        cs=cstmp          
     407             :     end do
     408             : 
     409             :     ! ================================================
     410             :     ! compute the second half of the roots by symmetry
     411             :     ! ================================================
     412             : 
     413     7866072 :     do j=1,nh 
     414     7866072 :        xjac(n-j) = -xjac(j)
     415             :     end do
     416             : 
     417     2622024 :     if (MODULO(n,2)==0) xjac(nh)=c0
     418             : 
     419             :     ! ====================================================
     420             :     ! Reverse the sign of everything so that indexing
     421             :     ! increases with position          
     422             :     ! ====================================================
     423             : 
     424    13110120 :     do j=0,n
     425    13110120 :        pts(j+1) = -xjac(j)
     426             :     end do
     427             : 
     428     2622024 :   end function gausslobatto_pts
     429             : 
     430             :   ! ================================================
     431             :   ! Gauss Lobatto Legendre Weights   
     432             :   ! ================================================ 
     433             : 
     434     5244048 :   function gausslobatto_wts(np1, glpts) result(wts)
     435             : 
     436             :     integer, intent(in)                 :: np1
     437             :     real (kind=r8), intent(in) :: glpts(np1)
     438             :     real (kind=r8)             :: wts(np1)
     439             : 
     440             :     ! Local variables
     441             : 
     442             :     real (kind=r8) :: c0,c2
     443             :     real (kind=r8) :: alpha
     444             :     real (kind=r8) :: beta
     445     2622024 :     real (kind=r8) :: jac(np1)
     446             :     integer i,n
     447             : 
     448     2622024 :     c0    = 0.0_r8
     449     2622024 :     c2    = 2.0_r8
     450     2622024 :     alpha = c0
     451     2622024 :     beta  = c0
     452     2622024 :     n     = np1-1
     453             : 
     454     2622024 :     jac=jacobi_polynomials(n,alpha,beta,np1,glpts)
     455             : 
     456    13110120 :     do i=1,np1
     457    13110120 :        wts(i)=c2/(n*(n+1)*jac(i)*jac(i))
     458             :     end do
     459             : 
     460     2622024 :   end function gausslobatto_wts
     461             : 
     462             :   ! ==============================================================
     463             :   ! test_gausslobatto:
     464             :   !
     465             :   ! Unit Tester for Gaussian Lobatto Quadrature...
     466             :   ! ==============================================================
     467             : 
     468           0 :   subroutine test_gausslobatto(npts)
     469             :     integer, intent(in) :: npts
     470             :     type (quadrature_t) :: gll
     471             : 
     472             :     integer i
     473             :     real (kind=r8) :: gllsum
     474           0 :     gll=gausslobatto(npts)
     475             : 
     476           0 :     print *
     477           0 :     print *,"============================================"
     478           0 :     print *,"      Testing Gauss-Lobatto Quadrature..."
     479           0 :     print *
     480           0 :     print *,"          points              weights"
     481           0 :     print *,"============================================"
     482           0 :     do i=1,npts
     483           0 :        print *,i,gll%points(i),gll%weights(i)
     484             :     end do
     485           0 :     print *,"============================================"
     486           0 :     gllsum=SUM(gll%weights(:))
     487           0 :     print *,"sum of Gauss-Lobatto weights=",gllsum
     488           0 :     print *,"============================================"
     489             : 
     490           0 :     deallocate(gll%points)
     491           0 :     deallocate(gll%weights)
     492             : 
     493           0 :   end subroutine test_gausslobatto
     494             : 
     495             :   ! ================================================
     496             :   !
     497             :   ! subroutine jacobi:
     498             :   !
     499             :   !  Computes the Jacobi Polynomials (jac) and their
     500             :   !  first derivatives up to and including degree n 
     501             :   !  at point x on the interval (-1,1).
     502             :   !
     503             :   !    See for example the recurrence relations 
     504             :   !    in equation 2.5.4 (page 70) in 
     505             :   !
     506             :   !    "Spectral Methods in Fluid Dynamics",
     507             :   !    by C. Canuto, M.Y. Hussaini, A. Quarteroni, T.A.Zang
     508             :   !    Springer-Verlag, 1988.
     509             :   ! ================================================
     510             : 
     511    23598216 :   subroutine jacobi(n, x, alpha, beta, jac, djac)
     512             : 
     513             :     integer, intent(in)                 :: n
     514             :     real (kind=r8), intent(in) :: x
     515             :     real (kind=r8), intent(in) :: alpha
     516             :     real (kind=r8), intent(in) :: beta
     517             :     real (kind=r8)             :: jac(0:n)
     518             :     real (kind=r8)             :: djac(0:n)
     519             : 
     520             :     ! Local variables
     521             : 
     522             :     real (kind=r8) :: a1k
     523             :     real (kind=r8) :: a2k
     524             :     real (kind=r8) :: a3k
     525             :     real (kind=r8) :: da2kdx
     526             : 
     527             :     real (kind=r8) :: c2,c1,c0
     528             : 
     529             :     integer ::  k
     530             : 
     531    23598216 :     c0 = 0.0_r8
     532    23598216 :     c1 = 1.0_r8
     533    23598216 :     c2 = 2.0_r8
     534             : 
     535    23598216 :     jac(0)=c1
     536    23598216 :     jac(1)=(c1 + alpha)*x
     537             : 
     538    23598216 :     djac(0)=c0
     539    23598216 :     djac(1)=(c1 + alpha)
     540             : 
     541    94392864 :     do k=1,n-1
     542    70794648 :        a1k      = c2*( k + c1 )*( k + alpha + beta + c1 )*( c2*k + alpha + beta )
     543    70794648 :        da2kdx   = ( c2*( k + c1 ) + alpha + beta )*( c2*k + alpha + beta + c1 )*( c2*k + alpha + beta )
     544    70794648 :        a2k      = ( c2*k + alpha + beta + c1 )*( alpha*alpha - beta*beta ) + x*da2kdx
     545    70794648 :        a3k      = c2*(k + alpha)*( k + beta )*( c2*k + alpha + beta + c2 )
     546    70794648 :        jac(k+1) = ( a2k*jac(k)-a3k*jac(k-1) )/a1k
     547    94392864 :        djac(k+1)= ( a2k*djac(k) + da2kdx*jac(k) - a3k*djac(k-1) )/a1k          
     548             :     end do
     549             : 
     550    23598216 :   end subroutine jacobi
     551             : 
     552             : 
     553             :   ! ==========================================================
     554             :   ! This routine computes the Nth order Jacobi Polynomials 
     555             :   ! (jac) for a vector of positions x on the interval (-1,1),
     556             :   ! of length npoints.
     557             :   !
     558             :   !    See for example the recurrence relations 
     559             :   !    in equation 2.5.4 (page 70) in 
     560             :   !
     561             :   !     "Spectral Methods in Fluid Dynamics",
     562             :   !     by C. Canuto, M.Y. Hussaini, A. Quarteroni, T.A.Zang
     563             :   !     Springer-Verlag, 1988.
     564             :   !
     565             :   ! ===========================================================
     566             : 
     567     2622024 :   function jacobi_polynomials(n, alpha, beta, npoints, x) result(jac)
     568             : 
     569             :     integer, intent(in)     :: n         ! order of the Jacobi Polynomial
     570             :     real (kind=r8) :: alpha 
     571             :     real (kind=r8) :: beta
     572             :     integer, intent(in)     :: npoints
     573             :     real (kind=r8) :: x(npoints)
     574             :     real (kind=r8) :: jac(npoints)
     575             : 
     576             :     ! Local variables
     577             : 
     578             :     real (kind=r8) :: a1k
     579             :     real (kind=r8) :: a2k
     580             :     real (kind=r8) :: a3k
     581             :     real (kind=r8) :: da2kdx
     582             : 
     583             :     real (kind=r8) :: jacp1
     584             :     real (kind=r8) :: jacm1
     585             :     real (kind=r8) :: jac0
     586             :     real (kind=r8) :: xtmp
     587             : 
     588             :     real (kind=r8) :: c2,c1,c0
     589             :     integer j,k
     590             : 
     591             :     c0 = 0.0_r8
     592             :     c1 = 1.0_r8
     593             :     c2 = 2.0_r8
     594             : 
     595    13110120 :     do j = 1,npoints
     596             : 
     597    10488096 :        xtmp=x(j)
     598             : 
     599    10488096 :        jacm1=c1
     600    10488096 :        jac0 =(c1+alpha)*xtmp
     601             : 
     602    31464288 :        do k=1,n-1
     603    20976192 :           a1k=c2*(k+c1)*(k+alpha+beta+c1)*(c2*k+alpha+beta)
     604    20976192 :           da2kdx=(c2*k+alpha+beta+c2)*(c2*k+alpha+beta+c1)*(c2*k+alpha+beta)
     605    20976192 :           a2k=(c2*k+alpha+beta+c1)*(alpha*alpha-beta*beta) + xtmp*da2kdx
     606    20976192 :           a3k=c2*(k+alpha)*(k+beta)*(c2*k+alpha+beta+c2)
     607    20976192 :           jacp1=(a2k*jac0-a3k*jacm1)/a1k
     608    20976192 :           jacm1=jac0
     609    31464288 :           jac0 =jacp1
     610             :        end do
     611             : 
     612    10488096 :        if (n==0)jac0=jacm1
     613    13110120 :        jac(j)=jac0
     614             :     end do
     615             : 
     616     2622024 :   end function jacobi_polynomials
     617             : 
     618             :   ! ================================================
     619             :   ! This routine computes the first derivatives of Nth
     620             :   ! order Jacobi Polynomials (djac) for a vector of 
     621             :   ! positions x on the interval (-1,1), of length npoints.
     622             :   !
     623             :   ! See for example the recurrence relations 
     624             :   ! in equation 2.5.4 (page 70) in 
     625             :   !
     626             :   ! "Spectral Methods in Fluid Dynamics",
     627             :   ! by C. Canuto, M.Y. Hussaini, A. Quarteroni, T.A.Zang
     628             :   ! Springer-Verlag, 1988.
     629             :   !
     630             :   ! ================================================
     631             : 
     632           0 :   function jacobi_derivatives(n, alpha, beta, npoints, x) result(djac)
     633             : 
     634             :     integer                , intent(in) :: n         ! order of the Jacobi Polynomial
     635             :     real (kind=r8), intent(in) :: alpha 
     636             :     real (kind=r8), intent(in) :: beta
     637             :     integer                , intent(in) :: npoints
     638             :     real (kind=r8), intent(in) :: x(npoints)
     639             : 
     640             :     real (kind=r8)             :: djac(npoints)
     641             : 
     642             :     ! Local variables
     643             : 
     644             :     ! Local variables
     645             : 
     646             :     real (kind=r8) :: a1k
     647             :     real (kind=r8) :: a2k
     648             :     real (kind=r8) :: a3k
     649             :     real (kind=r8) :: da2kdx
     650             : 
     651             :     real (kind=r8) :: jacp1
     652             :     real (kind=r8) :: jacm1
     653             :     real (kind=r8) :: jac0
     654             :     real (kind=r8) :: djacp1
     655             :     real (kind=r8) :: djacm1
     656             :     real (kind=r8) :: djac0
     657             : 
     658             :     real (kind=r8) :: xtmp
     659             : 
     660             :     real (kind=r8) :: c2,c1,c0
     661             :     integer j,k
     662             : 
     663             :     c0 = 0.0_r8
     664             :     c1 = 1.0_r8
     665             :     c2 = 2.0_r8
     666             : 
     667           0 :     do j = 1,npoints
     668             : 
     669           0 :        xtmp=x(j)
     670             : 
     671           0 :        jacm1=c1
     672           0 :        jac0 =(c1+alpha)*xtmp
     673             : 
     674           0 :        djacm1 = c0
     675           0 :        djac0  = (c1+alpha)
     676             : 
     677           0 :        do k=1,n-1
     678           0 :           a1k=c2*(k+c1)*(k+alpha+beta+c1)*(c2*k+alpha+beta)
     679           0 :           da2kdx=(c2*k+alpha+beta+c2)*(c2*k+alpha+beta+c1)*(c2*k+alpha+beta)
     680           0 :           a2k=(c2*k+alpha+beta+c1)*(alpha*alpha-beta*beta) + xtmp*da2kdx
     681           0 :           a3k=c2*(k+alpha)*(k+beta)*(c2*k+alpha+beta+c2)
     682             : 
     683           0 :           jacp1=(a2k*jac0-a3k*jacm1)/a1k
     684           0 :           djacp1=(a2k*djac0+da2kdx*jac0-a3k*djacm1)/a1k
     685             : 
     686           0 :           jacm1=jac0
     687           0 :           jac0=jacp1
     688             : 
     689           0 :           djacm1=djac0
     690           0 :           djac0=djacp1
     691             : 
     692             :        end do
     693             : 
     694           0 :        if (n==0)djac0=djacm1
     695           0 :        djac(j)=djac0
     696             : 
     697             :     end do
     698             : 
     699           0 :   end function jacobi_derivatives
     700             : 
     701             :   ! ===================================================
     702             :   !
     703             :   ! legendre:
     704             :   !
     705             :   ! Compute the legendre polynomials using
     706             :   ! the recurrence relationship.
     707             :   ! return leg(m+1) = P_N(x) for m=0..N
     708             :   ! p_3 = Legendre polynomial of degree N
     709             :   ! p_2 = Legendre polynomial of degree N-1 at x
     710             :   ! p_1 = Legendre polynomial of degree N-2 at x
     711             :   !
     712             :   ! ===================================================
     713             : 
     714    20894784 :   function legendre(x,N) result(leg)
     715             : 
     716             :     integer   :: N
     717             :     real (kind=r8) :: x
     718             :     real (kind=r8) :: leg(N+1)
     719             : 
     720             :     real (kind=r8) ::  p_1, p_2, p_3
     721             :     integer   :: k
     722             : 
     723    20894784 :     p_3 = 1.0_r8
     724    20894784 :     leg(1)=p_3
     725    20894784 :     if (n.ne.0) then
     726    20894784 :        p_2 = p_3
     727    20894784 :        p_3 = x
     728    20894784 :        leg(2)=p_3
     729    62684352 :        do k = 2,N
     730    41789568 :           p_1 = p_2
     731    41789568 :           p_2 = p_3
     732    41789568 :           p_3 = ( (2*k-1)*x*p_2 - (k-1)*p_1 ) / k
     733    62684352 :           leg(k+1)=p_3
     734             :        end do
     735             :     end if
     736             : 
     737    20894784 :   end function legendre
     738             : 
     739             : 
     740             :   ! ===========================================
     741             :   ! quad_norm:
     742             :   !
     743             :   ! compute normalization constants 
     744             :   ! for k=1,N order Legendre polynomials
     745             :   !
     746             :   ! e.g. gamma(k) in Canuto, page 58.
     747             :   !
     748             :   ! ===========================================
     749             : 
     750     2608200 :   function quad_norm(gquad,N) result(gamma)
     751             :     type (quadrature_t), intent(in) :: gquad
     752             :     integer            , intent(in) :: N
     753             : 
     754             :     real (kind=r8) :: gamma(N)
     755             : 
     756             :     ! Local variables
     757     2608200 :     real (kind=r8) :: leg(N)
     758             :     integer               :: i,k
     759             : 
     760    13041000 :     gamma(:)=0.0_r8
     761             : 
     762    13041000 :     do i=1,N
     763    10432800 :        leg=legendre(gquad%points(i),N-1)
     764    54772200 :        do k=1,N
     765    52164000 :           gamma(k)= gamma(k)+leg(k)*leg(k)*gquad%weights(i)
     766             :        end do
     767             :     end do
     768             : 
     769     2608200 :   end function quad_norm
     770             : 
     771             :   ! =======================
     772             :   ! TrapN:
     773             :   ! Numerical recipes
     774             :   ! =======================
     775             : 
     776           0 :   subroutine trapN(f,a,b,N,it,s)
     777             :     INTERFACE
     778             :        FUNCTION f(x) RESULT(f_x)   ! Function to be integrated
     779             :          use shr_kind_mod, only: r8=>shr_kind_r8
     780             :          real(kind=r8), INTENT(IN) :: x
     781             :          real(kind=r8) :: f_x
     782             :        END FUNCTION f
     783             :     END INTERFACE
     784             : 
     785             :     real(kind=r8),intent(in) :: a,b
     786             :     integer, intent(in)             :: N
     787             :     integer, intent(inout)          :: it
     788             :     real(kind=r8), intent(inout) :: s
     789             : 
     790             :     real(kind=r8) :: ssum
     791             :     real(kind=r8) :: del
     792             :     real(kind=r8) :: rtnm
     793             :     real(kind=r8) :: x
     794             : 
     795             :     integer :: j
     796             : 
     797           0 :     if (N==1) then
     798           0 :        s = 0.5_r8*(b-a)*(f(a) + f(b))
     799           0 :        it =1
     800             :     else
     801           0 :        ssum = 0.0_r8
     802           0 :        rtnm =1.0_r8/it
     803           0 :        del = (b-a)*rtnm
     804           0 :        x=a+0.5_r8*del
     805           0 :        do j=1,it
     806           0 :           ssum = ssum + f(x)
     807           0 :           x=x+del
     808             :        end do
     809           0 :        s=0.5_r8*(s + del*ssum)
     810           0 :        it=2*it  
     811             :     end if
     812             : 
     813           0 :   end subroutine trapN
     814             : 
     815             :   ! ==========================================
     816             :   ! Trapezoid Rule for integrating functions 
     817             :   ! from a to b with residual error eps
     818             :   ! ==========================================
     819             : 
     820           0 :   function trapezoid(f,a,b,eps) result(Integral)
     821             : 
     822             :     integer, parameter :: Nmax = 25  ! At most 2^Nmax + 1 points in integral
     823             : 
     824             :     INTERFACE
     825             :        FUNCTION f(x) RESULT(f_x)   ! Function to be integrated
     826             :          use shr_kind_mod, only: r8=>shr_kind_r8
     827             :          real(kind=r8), INTENT(IN) :: x
     828             :          real(kind=r8) :: f_x
     829             :        END FUNCTION f
     830             :     END INTERFACE
     831             : 
     832             :     real(kind=r8), intent(in) :: a,b       ! The integral bounds
     833             :     real(kind=r8), intent(in) :: eps       ! relative error bound for integral
     834             :     real(kind=r8)             :: Integral  ! the integral result (within eps)
     835             :     real(kind=r8)             :: s         ! Integral approximation
     836             :     real(kind=r8)             :: sold      ! previous integral approx
     837             : 
     838             :     integer                          :: N
     839             :     integer                          :: it
     840             : 
     841             :     ! ==============================================================
     842             :     ! Calculate I here using trapezoid rule using f and a DO loop...
     843             :     ! ==============================================================
     844             : 
     845           0 :     s    = 1.0e30_r8
     846           0 :     sold = 0.0_r8
     847           0 :     N=1
     848           0 :     it=0
     849           0 :     do while(N<=Nmax .and. ABS(s-sold)>eps*ABS(sold))
     850           0 :        sold=s
     851           0 :        call trapN(f,a,b,N,it,s)
     852           0 :        N=N+1
     853             :     end do
     854             : 
     855           0 :     Integral = s
     856             : 
     857           0 :   end function trapezoid
     858             : 
     859             :   ! ==========================================
     860             :   ! Simpsons Rule for integrating functions 
     861             :   ! from a to b with residual error eps
     862             :   ! ==========================================
     863             : 
     864           0 :   function simpsons(f,a,b,eps) result(Integral)
     865             : 
     866             :     integer, parameter :: Nmax = 25  ! At most 2^Nmax + 1 points in integral
     867             : 
     868             :     INTERFACE
     869             :        FUNCTION f(x) RESULT(f_x)   ! Function to be integrated
     870             :          use shr_kind_mod, only: r8=>shr_kind_r8
     871             :          real(kind=r8), INTENT(IN) :: x
     872             :          real(kind=r8) :: f_x
     873             :        END FUNCTION f
     874             :     END INTERFACE
     875             : 
     876             :     real(kind=r8), intent(in) :: a,b       ! The integral bounds
     877             :     real(kind=r8), intent(in) :: eps       ! relative error bound for integral
     878             :     real(kind=r8)             :: Integral  ! the integral result (within eps)
     879             :     real(kind=r8)             :: s         ! Integral approximation
     880             :     real(kind=r8)             :: os        ! previous integral approx
     881             :     real(kind=r8)             :: st        ! Integral approximation
     882             :     real(kind=r8)             :: ost       ! previous integral approx
     883             : 
     884             :     integer                          :: N
     885             :     integer                          :: it
     886             : 
     887             :     ! ==============================================================
     888             :     ! Calculate I here using trapezoid rule using f and a DO loop...
     889             :     ! ==============================================================
     890             : 
     891           0 :     ost= 0.0_r8
     892           0 :     s  = 1.0e30_r8
     893           0 :     os = 0.0_r8
     894             : 
     895           0 :     N=1
     896           0 :     it=0
     897           0 :     do while ((N<=Nmax .and. ABS(s-os)>eps*ABS(os) ) .or. N<=2)
     898           0 :        os = s
     899           0 :        call trapN(f,a,b,N,it,st)
     900           0 :        s=(4.0_r8*st-ost)/3.0_r8
     901           0 :        ost=st
     902           0 :        N=N+1
     903             :     end do
     904             : 
     905           0 :     Integral = s
     906             : 
     907           0 :   end function simpsons
     908             : 
     909             : 
     910             :   ! ==========================================
     911             :   ! gaussian_int:
     912             :   !
     913             :   ! Gaussian Quadrature Rule for integrating 
     914             :   ! function f from a to b  with gs weights and 
     915             :   ! points with precomputed gaussian quadrature 
     916             :   ! and weights.
     917             :   ! ==========================================
     918             : 
     919           0 :   function gaussian_int(f,a,b,gs) result(Integral)
     920             : 
     921             :     integer, parameter :: Nmax = 10  ! At most 2^Nmax + 1 points in integral
     922             : 
     923             :     INTERFACE
     924             :        FUNCTION f(x) RESULT(f_x)   ! Function to be integrated
     925             :          use shr_kind_mod, only: r8=>shr_kind_r8
     926             :          real(kind=r8), INTENT(IN) :: x
     927             :          real(kind=r8) :: f_x
     928             :        END FUNCTION f
     929             :     END INTERFACE
     930             : 
     931             :     real(kind=r8), intent(in) :: a,b       ! The integral bounds
     932             :     type(quadrature_t), intent(in)   :: gs        ! gaussian points/wts
     933             :     real(kind=r8)             :: Integral  ! the integral result (within eps)
     934             : 
     935             :     integer                          :: i
     936             :     real (kind=r8)            :: s,x
     937             :     ! ==============================================================
     938             :     ! Calculate I = S f(x)dx here using gaussian quadrature
     939             :     ! ==============================================================
     940             : 
     941           0 :     s = 0.0_r8
     942           0 :     do i=1,SIZE(gs%points)
     943           0 :        x = 0.50_r8*((b-a)*gs%points(i) + (b+a))
     944           0 :        s = s + gs%weights(i)*f(x)
     945             :     end do
     946           0 :     Integral = s*(0.5_r8*(b-a))
     947             : 
     948           0 :   end function gaussian_int
     949             : 
     950           0 : end module quadrature_mod
     951             : 
     952             : 
     953             : 
     954             : 
     955             : 

Generated by: LCOV version 1.14