<HTML> <BODY BGCOLOR=#ccccdd LINK=#0000aa VLINK=#0000ff ALINK=#ff0000 ><BASE TARGET="bottom_target"><PRE>
<A NAME='DA_CALC_POWER_SPECTRUM'><A href='../../html_code/spectral/da_calc_power_spectrum.inc.html#DA_CALC_POWER_SPECTRUM' TARGET='top_target'><IMG SRC="../../gif/bar_red.gif" border=0></A>

subroutine da_calc_power_spectrum(max_wave, power) 1,6

   !-----------------------------------------------------------------------
   ! Purpose: Calculate power spectrum
   !-----------------------------------------------------------------------
    
   implicit none
    
   integer, parameter  :: nj = 200          ! #Gaussian lats (even).

   integer, intent(in) :: max_wave          ! Smallest wavenumber for grid.
   real*8, intent(out) :: power(0:max_wave) ! Power spectrum.

   real                :: glats(1:nj)       ! Gaussian latitudes.
   real                :: gwgts(1:nj)       ! Gaussian weights.
   real                :: sinlat(1:nj)      ! sine.
   real                :: coslat(1:nj)      ! cosine.

   integer             :: max_wave_nj       ! Maximum wavenumber.
   integer             :: i,j, l            ! Loop counters.
   real                :: corr_scale        ! Correlation scale.
   real                :: corr_scale_inv    ! 1/corr_scale
   real                :: variance          ! Variance = sum(power).
   real                :: d(1:nj)           ! Temp array.
   real                :: corr(1:nj)        ! Correlation function.
   logical             :: odd               ! true if odd.
   real, allocatable   :: alp(:,:)          ! Associated Legendre Polynomials.
   real, allocatable   :: power_nj(:)       ! Power spectrum.
   character (len=filename_len) :: filename
   
   do i=1,num_alpha_corr_types
      call da_get_unit(alpha_corr_unit1(i))
      call da_get_unit(alpha_corr_unit2(i))
      write (unit=filename,fmt='(A,I1)') "alpha_corr1_",i
      open(unit=alpha_corr_unit1(i),file=filename,status="replace")
      write (unit=filename,fmt='(A,I1)') "alpha_corr2_",i
      open(unit=alpha_corr_unit2(i),file=filename,status="replace")
   end do

   !-----------------------------------------------------------------------------
   ! [1] Switch lats from -pi/2 to pi/2 to 0 to pi:
   !-----------------------------------------------------------------------------

   max_wave_nj = nj / 2 - 1
   allocate(alp(1:nj,0:max_wave_nj))
   allocate(power_nj(0:max_wave_nj))

   call da_get_gausslats(nj, glats, gwgts, sinlat, coslat)
   glats = glats + 0.5 * pi

   ! Get m=0 Associated Legendre Polynomials:

   do l = 0, max_wave_nj
      odd = .false.
      if (real(int(0.5 * real(l))) /= 0.5 * l) odd = .true.

      do j = 1, nj
         call da_asslegpol(l, 0, sinlat(j), coslat(j), alp(j,l))
         ! Reverse order of alps to account for latitude/angle difference:
         if (odd) alp(j,l) = -alp(j,l)
      end do
   end do

   !-----------------------------------------------------------------------------
   ! [2] Define correlation function:
   !-----------------------------------------------------------------------------

   corr_scale = alpha_corr_scale / earth_radius 
   corr_scale_inv = 1.0 / corr_scale

   do j = 1, nj
      ! d(j) = 0.5 * glats(j) * corr_scale_inv
      d(j) = glats(j) * corr_scale_inv

      if (alpha_corr_type == alpha_corr_type_exp) then ! Exponential.
         corr(j) = exp(-d(j))
      else if (alpha_corr_type == alpha_corr_type_soar) then ! SOAR
         d(j) = 2.0 * d(j)
         corr(j) = (1.0 + d(j)) * exp(-d(j))
      else if (alpha_corr_type == alpha_corr_type_gaussian) then ! Gaussian
         corr(j) = exp(-d(j) * d(j))
      end if
   end do

   do j = 1, nj
      write(unit=alpha_corr_unit1(alpha_corr_type),fmt='(i4,2f12.4)') &amp;
        j, earth_radius * glats(j), corr(j)
   end do

   !--------------------------------------------------------------------------
   ! [3] Calculate power spectra:
   !--------------------------------------------------------------------------

   ! Calculate power spectrum (and truncate if has -ve values).
   ! Power spectrum at this stage is is the Dl=sqrt(2l+1)*Bl of Boer(1983).
   ! This ensures the total variance = sum(Dl).

   power_nj(:) = 0.0
   do l = 0, max_wave_nj
      power_nj(l) = 0.5 * sqrt(2.0 * real(l) + 1.0) * &amp;
                    sum(gwgts(1:nj) * corr(1:nj) * alp(1:nj,l))

      if (power_nj(l) &lt; 0.0) power_nj(l) = 0.0
   end do
   write(unit=stdout,fmt='(a,2f12.5)')' Total, unscale variance = ', &amp;
                sum(power_nj(0:max_wave_nj))

   ! Rescale so variance = 1 (take out later?):
   variance = sum(power_nj(0:max_wave_nj))
   power_nj(0:max_wave_nj) = power_nj(0:max_wave_nj) / variance

   do l = 0, max_wave_nj
      write(unit=alpha_corr_unit2(alpha_corr_type),fmt='(i4,2f12.4)') &amp;
        l, power_nj(l), sum(power_nj(0:l))
   end do

   write(unit=stdout,fmt='(a,2i6)')' Total, truncated wave_max = ', &amp;
                     max_wave_nj, max_wave
   write(unit=stdout,fmt='(a,2f12.5)')' Total, truncated variance = ', &amp;
                sum(power_nj(0:max_wave_nj)), sum(power_nj(0:max_wave))

   power(0:max_wave) = power_nj(0:max_wave)

   ! Add compactly supported correlation from calc_globalspectral later?

   deallocate(alp)
   deallocate(power_nj)
   
   do i=1,num_alpha_corr_types
      close (alpha_corr_unit1(i))
      close (alpha_corr_unit2(i))
      call da_free_unit (alpha_corr_unit1(i))
      call da_free_unit (alpha_corr_unit2(i))
   end do

end subroutine da_calc_power_spectrum