ssht_dl_mod.f90

Go to the documentation of this file.
00001 ! SSHT package to perform spin spherical harmonic transforms
00002 ! Copyright (C) 2011  Jason McEwen
00003 ! See LICENSE.txt for license details
00004 
00005 
00006 !------------------------------------------------------------------------------
00007 ! ssht_dl_mod
00008 !
00016 
00017 module ssht_dl_mod
00018 
00019   use ssht_types_mod, only: dp, SQRT2, PION2
00020   use ssht_error_mod
00021 
00022   implicit none
00023 
00024   private
00025 
00026   
00027   !---------------------------------------
00028   ! Subroutine and function scope
00029   !---------------------------------------
00030 
00031   public :: &
00032        ssht_dl_beta_operator, &
00033        ssht_dl_beta_risbo_full, &
00034        ssht_dl_beta_risbo_full_table, &
00035        ssht_dl_beta_risbo_half_table, &
00036        ssht_dl_beta_risbo_fill_half2full, &
00037        ssht_dl_halfpi_trapani_eighth, &
00038        ssht_dl_halfpi_trapani_eighth_table, &
00039        ssht_dl_halfpi_trapani_fill_eighth2full, &
00040        ssht_dl_halfpi_trapani_fill_eighth2full_table, &
00041        ssht_dl_halfpi_trapani_fill_eighth2tophalf, &
00042        ssht_dl_halfpi_trapani_fill_eighth2tophalf_table, &
00043        ssht_dl_halfpi_trapani_fill_eighth2righthalf, &
00044        ssht_dl_halfpi_trapani_fill_eighth2righthalf_table, &
00045        ssht_dl_halfpi_trapani_fill_eighth2quarter, &
00046        ssht_dl_halfpi_trapani_fill_eighth2quarter_table
00047 
00048 
00049   !----------------------------------------------------------------------------
00050 
00051   contains
00052 
00053 
00054     !--------------------------------------------------------------------------
00055     ! Risbo's method
00056     !--------------------------------------------------------------------------
00057 
00058     !--------------------------------------------------------------------------
00059     ! ssht_dl_beta_risbo_full
00060     !
00076 
00077     subroutine ssht_dl_beta_risbo_full(dl, beta, l)
00078 
00079       integer, intent(in) :: l
00080       real(kind = dp), intent(out) :: dl(-l:l,-l:l)
00081       real(kind = dp), intent(in) :: beta
00082 
00083       integer :: sign, i, j, k, m, mm
00084       real(kind = dp) :: sinb, cosb, sinhb, coshb, rj, dlj, ddj
00085       real(kind = dp) :: sqrt_jmk, sqrt_kp1, sqrt_jmi, sqrt_ip1
00086       real(kind=dp) :: dd(0: 2 * l + 1, 0: 2 * l + 1)
00087 
00088       if (l < 0) then
00089 
00090          call ssht_error(SSHT_ERROR_ARG_INVALID, 'ssht_dl_beta_recursion', &
00091               comment_add='el < 0');
00092 
00093       ! For the special cases of l = 0 use the direct formula.
00094       else if (l == 0) then
00095 
00096          dl(0, 0) = 1.0_dp
00097 
00098       ! For the special cases of l = 1 use the direct formula.
00099       else if (l == 1) then
00100 
00101          ! These formulae are taken directly from Brink & Satchler.
00102 
00103          cosb = cos(beta)
00104          sinb = sin(beta)
00105 
00106          coshb = cos(beta / 2.0)
00107          sinhb = sin(beta / 2.0)
00108 
00109          dl(- 1, - 1) = coshb**2
00110          dl(- 1, 0) = sinb / SQRT2
00111          dl(- 1, 1) = sinhb**2
00112 
00113          dl(0, - 1) = - sinb / SQRT2
00114          dl(0, 0) = cosb
00115          dl(0, 1) = sinb / SQRT2
00116 
00117          dl(1, - 1) = sinhb**2
00118          dl(1, 0) = - sinb / SQRT2
00119          dl(1, 1) = coshb**2
00120 
00121       else
00122 
00123          sinhb = sin(beta / 2.0) ! p
00124          coshb = - cos(beta / 2.0) !-q
00125 
00126          ! Initialise the plane of the dl-matrix to 0.0 for the recursion
00127          ! from l - 1 to l - 1/2.
00128 
00129          dd(0: 2 * l + 1, 0: 2 * l + 1) = 0.0_dp
00130 
00131          j = 2 * l - 1
00132          rj = real(j)
00133          do k = 0, j - 1
00134             sqrt_jmk = dsqrt(real(j-k,kind=dp))
00135             sqrt_kp1 = dsqrt(real(k+1,kind=dp))
00136             do i = 0, j - 1
00137                sqrt_jmi = dsqrt(real(j-i,kind=dp))
00138                sqrt_ip1 = dsqrt(real(i+1,kind=dp))
00139                dlj = dl(k - (l - 1), i - (l - 1)) / rj
00140                dd(i, k) = dd(i, k) &
00141                     + sqrt_jmi * sqrt_jmk * dlj * coshb
00142                dd(i + 1, k) = dd(i + 1, k) &
00143                     - sqrt_ip1 * sqrt_jmk * dlj * sinhb
00144                dd(i, k + 1) = dd(i, k + 1) &
00145                     + sqrt_jmi * sqrt_kp1 * dlj * sinhb
00146                dd(i + 1, k + 1) = dd(i + 1, k + 1) &
00147                     + sqrt_ip1 * sqrt_kp1 * dlj * coshb
00148             end do
00149          end do
00150 
00151          ! Having constructed the d^(l+1/2) matrix in dd, do the second
00152          ! half-step recursion from dd to dl. Start by initilalising  
00153          ! the plane of the dl-matrix to 0.0.
00154 
00155          dl(- l: l, - l: l) = 0.0_dp
00156 
00157          j = 2 * l
00158          rj = real(j)
00159          do k = 0, j - 1
00160             sqrt_jmk = dsqrt(real(j-k,kind=dp))
00161             sqrt_kp1 = dsqrt(real(k+1,kind=dp))
00162             do i = 0, j - 1
00163                sqrt_jmi = dsqrt(real(j-i,kind=dp))
00164                sqrt_ip1 = dsqrt(real(i+1,kind=dp))
00165                ddj = dd(i, k) / rj
00166                dl(k - l, i - l) = dl(k - l, i - l) &
00167                     + sqrt_jmi * sqrt_jmk * ddj * coshb
00168                dl(k - l, i + 1 - l) = dl(k - l, i + 1 - l) &
00169                     - sqrt_ip1 * sqrt_jmk * ddj * sinhb
00170                dl(k + 1 - l, i - l) = dl(k + 1 - l, i - l) &
00171                     + sqrt_jmi * sqrt_kp1 * ddj * sinhb
00172                dl(k + 1 - l, i + 1 - l) = dl(k + 1 - l, i + 1 - l) &
00173                     + sqrt_ip1 * sqrt_kp1 * ddj * coshb
00174             end do
00175          end do
00176 
00177       end if
00178 
00179     end subroutine ssht_dl_beta_risbo_full
00180 
00181 
00182     !--------------------------------------------------------------------------
00183     ! ssht_dl_beta_risbo_full_table
00184     !
00203 
00204     subroutine ssht_dl_beta_risbo_full_table(dl, beta, l, sqrt_tbl)
00205 
00206       integer, intent(in) :: l
00207       real(kind = dp), intent(out) :: dl(-l:l,-l:l)
00208       real(kind = dp), intent(in) :: beta
00209       real(kind = dp), intent(in) :: sqrt_tbl(0:2*l)
00210 
00211       integer :: sign, i, j, k, m, mm
00212       real(kind = dp) :: sinb, cosb, sinhb, coshb, rj, dlj, ddj
00213       real(kind = dp) :: sqrt_jmk, sqrt_kp1, sqrt_jmi, sqrt_ip1
00214       real(kind=dp) :: dd(0: 2 * l + 1, 0: 2 * l + 1)
00215 
00216       if (l < 0) then
00217 
00218          call ssht_error(SSHT_ERROR_ARG_INVALID, 'ssht_dl_beta_recursion', &
00219               comment_add='el < 0');
00220 
00221       ! For the special cases of l = 0 use the direct formula.
00222       else if (l == 0) then
00223 
00224          dl(0, 0) = 1.0_dp
00225 
00226       ! For the special cases of l = 1 use the direct formula.
00227       else if (l == 1) then
00228 
00229          ! These formulae are taken directly from Brink & Satchler.
00230 
00231          cosb = cos(beta)
00232          sinb = sin(beta)
00233 
00234          coshb = cos(beta / 2.0)
00235          sinhb = sin(beta / 2.0)
00236 
00237          dl(- 1, - 1) = coshb**2
00238          dl(- 1, 0) = sinb / SQRT2
00239          dl(- 1, 1) = sinhb**2
00240 
00241          dl(0, - 1) = - sinb / SQRT2
00242          dl(0, 0) = cosb
00243          dl(0, 1) = sinb / SQRT2
00244 
00245          dl(1, - 1) = sinhb**2
00246          dl(1, 0) = - sinb / SQRT2
00247          dl(1, 1) = coshb**2
00248 
00249       else
00250 
00251          sinhb = sin(beta / 2.0) ! p
00252          coshb = - cos(beta / 2.0) !-q
00253 
00254          ! Initialise the plane of the dl-matrix to 0.0 for the recursion
00255          ! from l - 1 to l - 1/2.
00256 
00257          dd(0: 2 * l + 1, 0: 2 * l + 1) = 0.0_dp
00258 
00259          j = 2 * l - 1
00260          rj = real(j)
00261          do k = 0, j - 1
00262             do i = 0, j - 1
00263                dlj = dl(k - (l - 1), i - (l - 1)) / rj
00264                dd(i, k) = dd(i, k) &
00265                     + sqrt_tbl(j-i) * sqrt_tbl(j-k) * dlj * coshb
00266                dd(i + 1, k) = dd(i + 1, k) &
00267                     - sqrt_tbl(i+1) * sqrt_tbl(j-k) * dlj * sinhb
00268                dd(i, k + 1) = dd(i, k + 1) &
00269                     + sqrt_tbl(j-i) * sqrt_tbl(k+1) * dlj * sinhb
00270                dd(i + 1, k + 1) = dd(i + 1, k + 1) &
00271                     + sqrt_tbl(i+1) * sqrt_tbl(k+1) * dlj * coshb
00272             end do
00273          end do
00274 
00275          ! Having constructed the d^(l+1/2) matrix in dd, do the second
00276          ! half-step recursion from dd to dl. Start by initilalising  
00277          ! the plane of the dl-matrix to 0.0.
00278 
00279          dl(- l: l, - l: l) = 0.0_dp
00280 
00281          j = 2 * l
00282          rj = real(j)
00283          do k = 0, j - 1
00284             do i = 0, j - 1
00285                ddj = dd(i, k) / rj
00286                dl(k - l, i - l) = dl(k - l, i - l) &
00287                     + sqrt_tbl(j-i) * sqrt_tbl(j-k) * ddj * coshb
00288                dl(k - l, i + 1 - l) = dl(k - l, i + 1 - l) &
00289                     - sqrt_tbl(i+1) * sqrt_tbl(j-k) * ddj * sinhb
00290                dl(k + 1 - l, i - l) = dl(k + 1 - l, i - l) &
00291                     + sqrt_tbl(j-i) * sqrt_tbl(k+1) * ddj * sinhb
00292                dl(k + 1 - l, i + 1 - l) = dl(k + 1 - l, i + 1 - l) &
00293                     + sqrt_tbl(i+1) * sqrt_tbl(k+1) * ddj * coshb
00294             end do
00295          end do
00296 
00297       end if
00298 
00299     end subroutine ssht_dl_beta_risbo_full_table
00300 
00301 
00302     !--------------------------------------------------------------------------
00303     ! ssht_dl_beta_risbo_half_table
00304     !
00324 
00325     subroutine ssht_dl_beta_risbo_half_table(dl, beta, l, sqrt_tbl)
00326 
00327       integer, intent(in) :: l
00328       real(kind = dp), intent(out) :: dl(-l:l,-l:l)
00329       real(kind = dp), intent(in) :: beta
00330       real(kind = dp), intent(in) :: sqrt_tbl(0:2*l)
00331 
00332       integer :: sign, i, j, k, m, mm
00333       real(kind = dp) :: sinb, cosb, sinhb, coshb, rj, dlj, ddj
00334       real(kind = dp) :: sqrt_jmk, sqrt_kp1, sqrt_jmi, sqrt_ip1
00335       real(kind=dp) :: dd(0: 2 * l + 1, 0: 2 * l + 1)
00336 
00337       if (l < 0) then
00338 
00339          call ssht_error(SSHT_ERROR_ARG_INVALID, 'ssht_dl_beta_recursion', &
00340               comment_add='el < 0');
00341 
00342       ! For the special cases of l = 0 use the direct formula.
00343       else if (l == 0) then
00344 
00345          dl(0, 0) = 1.0_dp
00346 
00347       ! For the special cases of l = 1 use the direct formula.
00348       else if (l == 1) then
00349 
00350          ! These formulae are taken directly from Brink & Satchler.
00351 
00352          cosb = cos(beta)
00353          sinb = sin(beta)
00354 
00355          coshb = cos(beta / 2.0)
00356          sinhb = sin(beta / 2.0)
00357 
00358          dl(- 1, - 1) = coshb**2
00359          dl(- 1, 0) = sinb / SQRT2
00360          dl(- 1, 1) = sinhb**2
00361 
00362          dl(0, - 1) = - sinb / SQRT2
00363          dl(0, 0) = cosb
00364          dl(0, 1) = sinb / SQRT2
00365 
00366          dl(1, - 1) = sinhb**2
00367          dl(1, 0) = - sinb / SQRT2
00368          dl(1, 1) = coshb**2
00369 
00370       else
00371 
00372          sinhb = sin(beta / 2.0) ! p
00373          coshb = - cos(beta / 2.0) !-q
00374 
00375          ! Initialise the plane of the dl-matrix to 0.0 for the recursion
00376          ! from l - 1 to l - 1/2.
00377 
00378          dd(0: 2 * l + 1, 0: 2 * l + 1) = 0.0_dp
00379 
00380          j = 2 * l - 1
00381          rj = real(j)
00382          do k = 0, j - 1
00383             do i = 0, l !j/2 + 1
00384                dlj = dl(k - (l - 1), i - (l - 1)) / rj
00385                dd(i, k) = dd(i, k) &
00386                     + sqrt_tbl(j-i) * sqrt_tbl(j-k) * dlj * coshb
00387                dd(i + 1, k) = dd(i + 1, k) &
00388                     - sqrt_tbl(i+1) * sqrt_tbl(j-k) * dlj * sinhb
00389                dd(i, k + 1) = dd(i, k + 1) &
00390                     + sqrt_tbl(j-i) * sqrt_tbl(k+1) * dlj * sinhb
00391                dd(i + 1, k + 1) = dd(i + 1, k + 1) &
00392                     + sqrt_tbl(i+1) * sqrt_tbl(k+1) * dlj * coshb
00393             end do
00394          end do
00395 
00396          ! Having constructed the d^(l+1/2) matrix in dd, do the second
00397          ! half-step recursion from dd to dl. Start by initilalising  
00398          ! the plane of the dl-matrix to 0.0.
00399 
00400          dl(- l: l, - l: l) = 0.0_dp
00401 
00402          j = 2 * l
00403          rj = real(j)
00404          do k = 0, j - 1
00405             do i = 0, l !j/2
00406                ddj = dd(i, k) / rj
00407                dl(k - l, i - l) = dl(k - l, i - l) &
00408                     + sqrt_tbl(j-i) * sqrt_tbl(j-k) * ddj * coshb
00409                dl(k - l, i + 1 - l) = dl(k - l, i + 1 - l) &
00410                     - sqrt_tbl(i+1) * sqrt_tbl(j-k) * ddj * sinhb
00411                dl(k + 1 - l, i - l) = dl(k + 1 - l, i - l) &
00412                     + sqrt_tbl(j-i) * sqrt_tbl(k+1) * ddj * sinhb
00413                dl(k + 1 - l, i + 1 - l) = dl(k + 1 - l, i + 1 - l) &
00414                     + sqrt_tbl(i+1) * sqrt_tbl(k+1) * ddj * coshb
00415             end do
00416          end do
00417 
00418       end if
00419 
00420     end subroutine ssht_dl_beta_risbo_half_table
00421 
00422 
00423     !--------------------------------------------------------------------------
00424     ! ssht_dl_beta_risbo_fill_half2full
00425     !
00438 
00439     subroutine ssht_dl_beta_risbo_fill_half2full(dl, l)
00440 
00441       integer, intent(in) :: l
00442       real(kind = dp), intent(inout) :: dl(-l:l,-l:l)
00443 
00444       integer :: m, mm
00445 
00446       ! Symmetry through origin.
00447       do m = -l, l
00448          do mm = 1, l
00449             dl(m,mm) = (-1)**(m+mm) * dl(-m,-mm)
00450          end do
00451       end do
00452 
00453     end subroutine ssht_dl_beta_risbo_fill_half2full
00454 
00455 
00456     !--------------------------------------------------------------------------
00457     ! Trapani & Navaza's method
00458     !--------------------------------------------------------------------------    
00459     
00460     !--------------------------------------------------------------------------
00461     ! ssht_dl_halfpi_trapani_eighth
00462     !
00477 
00478     subroutine ssht_dl_halfpi_trapani_eighth(dl, el)
00479 
00480       integer, intent(in) :: el
00481       real(dp), intent(inout) :: dl(-el:el,-el:el)
00482 
00483       real(dp) :: dmm(0:el)
00484       integer :: m, mm
00485       real(dp) :: t1, t2
00486 
00487       if (el == 0) then
00488 
00489          dl(0,0) = 1d0
00490 
00491       else
00492 
00493          ! Eqn (9) of T&N (2006).
00494          dmm(0) = - sqrt( (2d0*el-1d0) / real(2d0*el,dp) ) 
00495               * dl(el-1,0)
00496 
00497          ! Eqn (10) of T&N (2006).
00498          do mm = 1, el
00499             dmm(mm) = sqrt( el/2d0 * (2d0*el-1d0) / real((el+mm) * (el+mm-1), dp) ) 
00500                  * dl(el-1,mm-1)
00501          end do
00502 
00503          dl(el,0:el) = dmm(0:el)
00504 
00505          ! Eqn (11) of T&N (2006).
00506          do mm = 0, el
00507 
00508             ! m = el - 1 case (t2 = 0). 
00509             m = el-1
00510             t1 = ( 2e0 * mm / sqrt(real((el-m) * (el+m+1), dp)) ) * 
00511                  dl(m+1,mm)
00512             dl(m,mm) = t1
00513 
00514             ! Remaining m cases.
00515             do m = el-2, mm, -1
00516                t1 = ( 2e0 * mm / sqrt(real((el-m) * (el+m+1), dp)) ) * 
00517                     dl(m+1,mm)
00518                t2 = sqrt( (el-m-1) * (el+m+2) / real((el-m) * (el+m+1), dp) ) * 
00519                     dl(m+2,mm)
00520                dl(m,mm) = t1 - t2
00521             end do
00522          end do
00523 
00524       end if
00525 
00526     end subroutine ssht_dl_halfpi_trapani_eighth
00527 
00528 
00529     !--------------------------------------------------------------------------
00530     ! ssht_dl_halfpi_trapani_eighth_table
00531     !
00549 
00550     subroutine ssht_dl_halfpi_trapani_eighth_table(dl, el, sqrt_tbl)
00551 
00552       integer, intent(in) :: el
00553       real(dp), intent(inout) :: dl(0:el,0:el)
00554       real(kind = dp), intent(in) :: sqrt_tbl(0:2*el+1)
00555 
00556 
00557       real(dp) :: dmm(0:el)
00558       integer :: m, mm
00559       real(dp) :: t1, t2
00560 
00561       if (el == 0) then
00562 
00563          dl(0,0) = 1d0
00564 
00565       else
00566 
00567          ! Eqn (9) of T&N (2006).
00568          dmm(0) = - sqrt_tbl(2*el-1) / sqrt_tbl(2*el) &
00569               * dl(el-1,0)
00570 
00571          ! Eqn (10) of T&N (2006).
00572          do mm = 1, el
00573             dmm(mm) = sqrt_tbl(el) / SQRT2 &
00574                  * sqrt_tbl(2*el-1) / sqrt_tbl(el+mm) / sqrt_tbl(el+mm-1) &
00575                  * dl(el-1,mm-1)
00576          end do
00577 
00578          dl(el,0:el) = dmm(0:el)
00579 
00580          ! Eqn (11) of T&N (2006).
00581          do mm = 0, el
00582 
00583             ! m = el-1 case (t2 = 0). 
00584             m = el-1
00585             dl(m,mm) = 2e0 * mm / sqrt_tbl(el-m) / sqrt_tbl(el+m+1) &
00586                  * dl(m+1,mm)
00587 
00588             ! Remaining m cases.
00589             do m = el-2, mm, -1
00590                t1 = 2e0 * mm / sqrt_tbl(el-m) / sqrt_tbl(el+m+1) &
00591                     * dl(m+1,mm)
00592                t2 = sqrt_tbl(el-m-1) * sqrt_tbl(el+m+2) / sqrt_tbl(el-m) / sqrt_tbl(el+m+1) &
00593                     * dl(m+2,mm)
00594                dl(m,mm) = t1 - t2
00595             end do
00596          end do
00597 
00598       end if
00599 
00600     end subroutine ssht_dl_halfpi_trapani_eighth_table
00601 
00602 
00603     !--------------------------------------------------------------------------
00604     ! ssht_dl_halfpi_trapani_fill_eighth2full
00605     !
00618  
00619     subroutine ssht_dl_halfpi_trapani_fill_eighth2full(dl, el)
00620 
00621       integer, intent(in) :: el
00622       real(kind = dp), intent(inout) :: dl(-el:el,-el:el)
00623 
00624       integer :: m, mm
00625 
00626       ! Diagonal symmetry to fill in quarter.
00627       do m = 0, el
00628          do mm = m+1, el
00629             dl(m,mm) = (-1)**(m+mm) * dl(mm,m)
00630          end do
00631       end do
00632 
00633       ! Symmetry in m to fill in half.
00634       do mm = 0, el
00635          do m = -el, -1
00636             dl(m,mm) = (-1)**(el+mm) * dl(-m,mm)
00637          end do
00638       end do
00639 
00640       ! Symmetry in mm to fill in remaining plane.
00641       do mm = -el, -1
00642          do m = -el, el
00643             dl(m,mm) = (-1)**(el+m) * dl(m,-mm)
00644          end do
00645       end do
00646 
00647     end subroutine ssht_dl_halfpi_trapani_fill_eighth2full
00648 
00649 
00650     !--------------------------------------------------------------------------
00651     ! ssht_dl_halfpi_trapani_fill_eighth2full_table
00652     !
00667  
00668     subroutine ssht_dl_halfpi_trapani_fill_eighth2full_table(dl, el, signs)
00669 
00670       integer, intent(in) :: el
00671       real(kind = dp), intent(inout) :: dl(-el:el,-el:el)
00672       real(kind = dp), intent(in) :: signs(0:el)
00673 
00674       integer :: m, mm
00675 
00676       ! Diagonal symmetry to fill in quarter.
00677       do m = 0, el
00678          do mm = m+1, el
00679             dl(m,mm) = signs(m) * signs(mm) * dl(mm,m)
00680          end do
00681       end do
00682 
00683       ! Symmetry in m to fill in half.
00684       do mm = 0, el
00685          do m = -el, -1
00686             dl(m,mm) = signs(el) * signs(mm) * dl(-m,mm)
00687          end do
00688       end do
00689 
00690       ! Symmetry in mm to fill in remaining plane.
00691       do mm = -el, -1
00692          do m = -el, el
00693             dl(m,mm) = signs(el) * signs(abs(m)) * dl(m,-mm)
00694          end do
00695       end do
00696 
00697     end subroutine ssht_dl_halfpi_trapani_fill_eighth2full_table
00698 
00699 
00700     !--------------------------------------------------------------------------
00701     ! ssht_dl_halfpi_trapani_fill_eighth2tophalf
00702     !
00715  
00716     subroutine ssht_dl_halfpi_trapani_fill_eighth2tophalf(dl, el)
00717 
00718       integer, intent(in) :: el
00719       real(kind = dp), intent(inout) :: dl(-el:el,0:el)
00720 
00721       integer :: m, mm
00722 
00723       ! Diagonal symmetry to fill in quarter.
00724       do m = 0, el
00725          do mm = m+1, el
00726             dl(m,mm) = (-1)**(m+mm) * dl(mm,m)
00727          end do
00728       end do
00729 
00730       ! Symmetry in m to fill in half.
00731       do m = -el, -1
00732          do mm = 0, el
00733             dl(m,mm) = (-1)**(el+mm) * dl(-m,mm)
00734          end do
00735       end do
00736 
00737     end subroutine ssht_dl_halfpi_trapani_fill_eighth2tophalf
00738 
00739 
00740     !--------------------------------------------------------------------------
00741     ! ssht_dl_halfpi_trapani_fill_eighth2tophalf_table
00742     !
00757  
00758     subroutine ssht_dl_halfpi_trapani_fill_eighth2tophalf_table(dl, el, signs)
00759 
00760       integer, intent(in) :: el
00761       real(kind = dp), intent(inout) :: dl(-el:el,0:el)
00762       real(kind = dp), intent(in) :: signs(0:el)
00763 
00764       integer :: m, mm
00765 
00766       ! Diagonal symmetry to fill in quarter.
00767       do m = 0, el
00768          do mm = m+1, el
00769             dl(m,mm) = signs(m) * signs(mm) * dl(mm,m)
00770          end do
00771       end do
00772 
00773       ! Symmetry in m to fill in half.
00774       do mm = 0, el
00775          do m = -el, -1
00776             dl(m,mm) = signs(el) * signs(mm) * dl(-m,mm)
00777          end do
00778       end do
00779 
00780     end subroutine ssht_dl_halfpi_trapani_fill_eighth2tophalf_table
00781 
00782 
00783     !--------------------------------------------------------------------------
00784     ! ssht_dl_halfpi_trapani_fill_eighth2righthalf
00785     !
00798  
00799     subroutine ssht_dl_halfpi_trapani_fill_eighth2righthalf(dl, el)
00800 
00801       integer, intent(in) :: el
00802       real(kind = dp), intent(inout) :: dl(0:el,-el:el)
00803 
00804       integer :: m, mm
00805 
00806       ! Diagonal symmetry to fill in quarter.
00807       do m = 0, el
00808          do mm = m+1, el
00809             dl(m,mm) = (-1)**(m+mm) * dl(mm,m)
00810          end do
00811       end do
00812 
00813       ! Symmetry in mm to fill in half.
00814       do m = 0, el
00815          do mm = -el, -1
00816             dl(m,mm) = (-1)**(el+m) * dl(m,-mm)
00817          end do
00818       end do
00819 
00820     end subroutine ssht_dl_halfpi_trapani_fill_eighth2righthalf
00821 
00822 
00823     !--------------------------------------------------------------------------
00824     ! ssht_dl_halfpi_trapani_fill_eighth2righthalf_table
00825     !
00840  
00841     subroutine ssht_dl_halfpi_trapani_fill_eighth2righthalf_table(dl, el, signs)
00842 
00843       integer, intent(in) :: el
00844       real(kind = dp), intent(inout) :: dl(0:el,-el:el)
00845       real(kind = dp), intent(in) :: signs(0:el)
00846 
00847       integer :: m, mm
00848 
00849       ! Diagonal symmetry to fill in quarter.
00850       do m = 0, el
00851          do mm = m+1, el
00852             dl(m,mm) = signs(m) * signs(mm) * dl(mm,m)
00853          end do
00854       end do
00855 
00856       ! Symmetry in mm to fill in half.
00857       do mm = -el, -1
00858          do m = 0, el
00859             dl(m,mm) = signs(el) * signs(m) * dl(m,-mm)
00860          end do
00861       end do
00862 
00863     end subroutine ssht_dl_halfpi_trapani_fill_eighth2righthalf_table
00864 
00865 
00866     !--------------------------------------------------------------------------
00867     ! ssht_dl_halfpi_trapani_fill_eighth2quarter
00868     !
00881 
00882     subroutine ssht_dl_halfpi_trapani_fill_eighth2quarter(dl, el)
00883 
00884       integer, intent(in) :: el
00885       real(kind = dp), intent(inout) :: dl(0:el,0:el)
00886 
00887       integer :: m, mm
00888 
00889       ! Diagonal symmetry to fill in quarter.
00890       do m = 0, el
00891          do mm = m+1, el
00892             dl(m,mm) = (-1)**(m+mm) * dl(mm,m)
00893          end do
00894       end do
00895 
00896     end subroutine ssht_dl_halfpi_trapani_fill_eighth2quarter
00897 
00898 
00899     !--------------------------------------------------------------------------
00900     ! ssht_dl_halfpi_trapani_fill_eighth2quarter_table
00901     !
00916 
00917     subroutine ssht_dl_halfpi_trapani_fill_eighth2quarter_table(dl, el, signs)
00918 
00919       integer, intent(in) :: el
00920       real(kind = dp), intent(inout) :: dl(0:el,0:el)
00921       real(kind = dp), intent(in) :: signs(0:el)
00922 
00923       integer :: m, mm
00924 
00925       ! Diagonal symmetry to fill in quarter.
00926       do m = 0, el
00927          do mm = m+1, el
00928             dl(m,mm) = signs(m) * signs(mm) * dl(mm,m)
00929          end do
00930       end do
00931 
00932     end subroutine ssht_dl_halfpi_trapani_fill_eighth2quarter_table
00933 
00934 
00935     !--------------------------------------------------------------------------
00936     ! Operator method
00937     !--------------------------------------------------------------------------
00938 
00939     !--------------------------------------------------------------------------
00940     ! ssht_dl_beta_operator
00941     !
00956     
00957     subroutine ssht_dl_beta_operator(dl, beta, l)
00958 
00959       integer, intent(in) :: l
00960       real(dp), intent(out) :: dl(-l:l,-l:l)
00961       real(dp), intent(in) :: beta
00962   
00963       ! Fill in the top quarter of the d-matrix.
00964       call ssht_dl_beta_operator_quarter(dl(-l:l,-l:l), beta, l)
00965   
00966       ! Use its symmetry properties to fill in the rest of it.
00967       call ssht_dl_beta_operator_fill(dl(-l:l,-l:l), l)
00968   
00969     end subroutine ssht_dl_beta_operator
00970 
00971 
00972     !--------------------------------------------------------------------------
00973     ! ssht_dl_beta_operator_quarter
00974     !
00992 
00993     subroutine ssht_dl_beta_operator_quarter(dl, beta, l)
00994 
00995       integer, intent(in) :: l
00996       real(kind = dp), intent(out) :: dl(-l:l,-l:l)
00997       real(kind = dp), intent(in) :: beta
00998 
00999   
01000       real(kind = dp) :: lambda, xllp1, xm, big, bigi, bigi2, c, s, omc, 
01001         lbig, expo, renorm, ratio, c2, t, si, ang, big_const
01002       real(kind = dp) :: cp(1:2 * l + 1)
01003       real(kind = dp) :: cpi(1:2 * l + 1)
01004       real(kind = dp) :: cp2(1:2 * l + 1)
01005       real(kind = dp) :: log_first_row(1:2 * l + 1)
01006       real(kind = dp) :: sign(1:2 * l + 1)
01007       real(kind = dp) :: lrenorm(1:2 * l + 1)
01008 
01009       integer :: index, i, m, im, j, lp1
01010   
01011       ! Added by Jason McEwen 19/11/05
01012       ! If beta=0 then dl=identity
01013       real(kind = dp) :: ZERO_TOL = 1d-5
01014       if(abs(beta) < ZERO_TOL) then
01015         dl(-l:l,-l:l) = 0d0
01016         do i = -l,l
01017           dl(i,i) = 1d0
01018         end do
01019         return      ! ** Exit routine
01020       end if
01021   
01022       lp1 = l + 1
01023       big_const = 1.0d150
01024 
01025       ang=beta
01026       c=dcos(ang)
01027       s=dsin(ang)
01028       si=1.d0/s
01029       t=dtan(-ang/2.d0)
01030       c2=dcos(ang/2.d0)
01031       omc=1.d0-c
01032   
01033       do i=1,2*l+1
01034         lrenorm(i)=0.d0
01035       end do
01036   
01037       ! Compute first row.
01038   
01039       log_first_row(1)=(2.d0*real(l,kind=dp))*dlog(dabs(c2))
01040       sign(1)=1.d0
01041       do i=2, 2*l+1
01042         m=l+1-i
01043         ratio=dsqrt(real(l+m+1,kind=dp)/real(l-m,kind=dp))
01044         log_first_row(i)=log_first_row(i-1) &
01045           +dlog(ratio)+dlog(dabs(t))
01046         sign(i)=sign(i-1)*t/dabs(t)
01047       end do
01048   
01049       big=big_const
01050       lbig=dlog(big)
01051       bigi=1.d0/big_const
01052       bigi2=1.d0/big_const**2
01053       xllp1=real(l*(l+1),kind=dp)
01054   
01055       ! Initialising coefficients cp(m)= cplus(l-m).
01056   
01057       do m=1,l
01058         xm=real(l-m,kind=dp)
01059         cpi(m)=2.d0/dsqrt(xllp1-xm*(xm+1))
01060         cp(m)=1.d0/cpi(m)
01061       end do
01062       do m=2,l
01063         cp2(m)=cpi(m)*cp(m-1)
01064       end do
01065       dl(1 - lp1, 1 - lp1)=1.d0
01066       dl(2*l+1 - lp1, 1 - lp1)=1.d0
01067   
01068       ! Use recurrrence relation to fill columns down to diagonals.
01069   
01070       do index= 2,l+1
01071         dl(index - lp1, 1 - lp1)=1.d0
01072         lambda=(real(l+1,kind=dp)*omc-real(index,kind=dp)+c)*si
01073         dl(index - lp1, 2 - lp1)=lambda*dl(index - lp1, 1 - lp1)*cpi(1)
01074         if(index.gt.2) then
01075           do m=2,index-1
01076             lambda=(real(l+1,kind=dp)*omc 
01077               -real(index,kind=dp)+real(m,kind=dp)*c)/s
01078             dl(index - lp1, m+1 - lp1)= &
01079               lambda*cpi(m)*dl(index - lp1, m - lp1)-cp2(m) &
01080               *dl(index - lp1, m-1 - lp1)
01081             if(dl(index - lp1, m+1 - lp1).gt.big) then
01082               lrenorm(index)=lrenorm(index)-lbig
01083               do im=1,m+1
01084                 dl(index - lp1, im - lp1)=dl(index - lp1, im - lp1)*bigi
01085               end do
01086             end if
01087           end do
01088         end if
01089       end do   
01090   
01091       ! Other half of triangle.
01092   
01093       do index= l+2,2*l
01094         dl(index - lp1, 1 - lp1)=1.d0
01095         lambda=(real(l+1,kind=dp)*omc-real(index,kind=dp)+c)/s
01096         dl(index - lp1, 2 - lp1)=lambda*dl(index - lp1, 1 - lp1)*cpi(1)
01097         if(index.lt.2*l) then
01098           do m=2,2*l-index+1
01099             lambda=(real(l+1,kind=dp)*omc-real(index,kind=dp) 
01100               +real(m,kind=dp)*c)/s
01101             dl(index - lp1, m+1 - lp1)= &
01102               lambda*cpi(m)*dl(index - lp1, m - lp1)-cp2(m)&
01103               *dl(index - lp1, m-1 - lp1)
01104             if(dl(index - lp1, m+1 - lp1).gt.big) then
01105               do im=1,m+1
01106                 dl(index - lp1, im - lp1)=dl(index - lp1, im - lp1)*bigi
01107               end do
01108               lrenorm(index)=lrenorm(index)-lbig
01109             end if
01110           end do
01111         end if
01112       end do   
01113   
01114       do i=1, l+1
01115         renorm=sign(i)*dexp(log_first_row(i)-lrenorm(i))
01116         do j=1, i
01117           dl(i - lp1, j - lp1)= dl(i - lp1, j - lp1)*renorm
01118         end do
01119       end do
01120       do i=l+2,2*l+1
01121         expo=log_first_row(i)-lrenorm(i)
01122         renorm=sign(i)*dexp(log_first_row(i)-lrenorm(i))
01123         do j=1,2*l+2-i
01124           dl(i - lp1, j - lp1)=dl(i - lp1, j - lp1)*renorm
01125         end do
01126       end do
01127   
01128     end subroutine ssht_dl_beta_operator_quarter
01129 
01130     
01131     !--------------------------------------------------------------------------
01132     ! ssht_dl_beta_operator_fill
01133     !
01147 
01148     subroutine ssht_dl_beta_operator_fill(dl, l)
01149 
01150       integer, intent(in) :: l
01151       real(kind = dp), intent(inout) :: dl(-l:l,-l:l)
01152   
01153       integer :: i, j,sgn, lp1
01154   
01155       lp1 = l + 1
01156   
01157       ! Reflect across anti-diagonal.
01158   
01159       do i = 1, l
01160         do j = l + 1, 2 * l + 1 - i
01161           dl(2 * l + 2 - i - lp1, 2 * l + 2 - j - lp1) = dl(j - lp1, i - lp1)
01162         end do
01163       end do
01164   
01165       ! Reflect across diagonal.
01166   
01167       do i = 1, l + 1
01168         sgn = - 1
01169         do j = i + 1, l + 1
01170           dl(i - lp1, j - lp1) = dl(j - lp1, i - lp1) * sgn
01171           sgn = sgn * (- 1)
01172         end do
01173       end do
01174   
01175       ! Fill in right quarter of matrix.
01176   
01177       do i = l + 2, 2 * l + 1
01178         sgn = (- 1)**(i + 1)
01179         do j = 1, 2 * l + 2 - i
01180           dl(j - lp1, i - lp1) = dl(i - lp1, j - lp1) * sgn
01181           sgn = sgn * (- 1)
01182         end do
01183         do j = i, 2 * l + 1
01184           dl(j - lp1, i - lp1) = dl(2 * l + 2 - i - lp1, 2 * l + 2 - j - lp1)
01185         end do
01186       end do
01187   
01188       do i = l + 2, 2 * l + 1
01189         do j = 2 * l + 3 - i, i - 1
01190           dl(j - lp1, i - lp1) = dl(2 * l + 2 - i - lp1, 2 * l + 2 - j - lp1)
01191         end do
01192       end do
01193   
01194     end subroutine ssht_dl_beta_operator_fill
01195 
01196 
01197 end module ssht_dl_mod
Generated on Mon Oct 31 01:20:05 2011 by  doxygen 1.6.3