subroutine da_calc_power(max_wavenumber, r_cvsize, rcv, power) 2

   !----------------------------------------------------------------------
   ! Purpose: Performs spectral to gridpoint transformation on a sphere.
   !----------------------------------------------------------------------

   implicit none

   integer, intent(in) :: max_wavenumber ! Smallest scale required (ni/2 - 1)
   integer, intent(in) :: r_cvsize               ! Size of rcv vector.
   real, intent(in)    :: rcv(1:r_cvsize)        ! Spectral modes.
   real, intent(out)   :: power(0:max_wavenumber)! Power spectrum.

   integer             :: n, m                   ! Loop counters.
   integer             :: index, indexx          ! Position markers in cv.
   integer             :: cv_size                ! Complex cv size.
   complex, allocatable:: ccv(:)                 ! Complex control variable.

   ! Create complex array:
   cv_size = r_cvsize / 2
   allocate(ccv(1:cv_size))
   do index = 1, cv_size
      indexx = 2 * index - 1
      ccv(index) = cmplx(rcv(indexx), rcv(indexx+1))
   end do

   power(:) = 0.0

   ! Calculate power spectrum from input 1D spectral mode vector:

   do n = 0, max_wavenumber

      ! First consider m=0:
      m = 0
      index = m * (max_wavenumber + 1 - m) + m * (m + 1) / 2 + 1 + n - m
      power(n) = real(ccv(index))**2

      ! Now add m>0 terms:
      do m = 1, n
         index = m * (max_wavenumber + 1 - m) + m * (m + 1) / 2 + 1 + n - m
         power(n) = power(n) + 2.0 *(real(ccv(index))**2 + aimag(ccv(index))**2)
      end do

   end do

   deallocate(ccv)
      
end subroutine da_calc_power