subroutine da_test_spectral (max_wave, sizec, xbx, field) 3,11

   !-----------------------------------------------------------------------
   ! Purpose: TBD
   !-----------------------------------------------------------------------

   implicit none

   integer,         intent(in) :: max_wave ! Maximum wavenumber.
   integer,         intent(in) :: sizec    ! Size of complex cv.
   type (xbx_type), intent(in) :: xbx  ! For header & non-grid arrays.
   real,            intent(in) :: field(its:ite,jts:jte)    ! Gridpoint field.

   real    :: field_out(its:ite,jts:jte)
   real*8  :: power(0:max_wave)   ! Power spectrum
   real    :: rcv(1:2*sizec)      ! Spectral modes.
   real    :: rcv_out(1:2*sizec)  ! Spectral modes.
   integer :: m,mm, index_start, index_end
   complex :: r_leg(1:jde)     
   complex :: ccv(1:sizec)     ! Spectral modes.
   complex :: ccv1(1:sizec)    ! Spectral modes.
   real    :: den, num, xx

   if (trace_use) call da_trace_entry("da_test_spectral")

   write (unit=stdout, fmt='(A)') &
      ' Test orthogonality of Associated Legendre Polynomials:'

   ! Initialise Power spectrum
   power  = 1.0
   call da_setlegpol_test( jde, max_wave, xbx%alp_size, xbx%int_wgts, xbx%alp )

   write(unit=stdout,fmt='(A)') &
      ' Test invertibility of spectral (Fourier, Legendre) transforms:'

   ! Gridpoint to spectral:
   rcv = 0.0
   call da_vv_to_v_spectral( xbx%ni, xbx%nj, max_wave, xbx%inc, xbx%lenr, xbx%lensav, xbx%lenwrk, &
                             xbx%alp_size, 2*sizec, xbx%alp, xbx%wsave, xbx%int_wgts, rcv, field)

   field_out = 0.0
   ! Spectral to gridpoint:
   call da_vtovv_spectral( max_wave, sizec, &
                             xbx % lenr, xbx % lenwrk, xbx % lensav, &
                             xbx % inc, xbx % alp_size, xbx % alp, &
                             xbx % wsave, power, rcv, field_out)

   write(unit=stdout,fmt='(1x,a,e30.10)') &
      'Domain-Averaged (Grid->Spectral->Grid) Error = ', &
              sqrt( sum( ( field_out(1:xbx%ni,1:xbx%nj) - field(1:xbx%ni,1:xbx%nj) )**2 ) / &
                    sum( field(1:xbx%ni,1:xbx%nj)**2 ) )
   rcv_out = 0.0
   
   ! Gridpoint to spectral (again):
   call da_vv_to_v_spectral( xbx%ni, xbx%nj, max_wave, xbx%inc, xbx%lenr, xbx%lensav, xbx%lenwrk, &
                      xbx%alp_size, 2*sizec, xbx%alp, xbx%wsave, xbx%int_wgts, rcv_out, field_out)

   rcv_out(1:2*sizec) = rcv_out(1:2*sizec) - rcv(1:2*sizec) ! Create difference for test diags.
    
   write(unit=stdout,fmt='(1x,a,e30.10)') &
      ' Domain-Averaged (Spectral->Grid->Spectral) Error = ', &
                       sqrt( sum( rcv_out(1:2*sizec)**2 ) ) / sqrt( sum( rcv(1:2*sizec)**2 ) )

   ! Adjoint test for Spectral Transform
   rcv_out = 0.0
   call da_vtovv_spectral_adj( max_wave, sizec, &
                                 xbx % lenr, xbx % lenwrk, xbx % lensav, &
                                 xbx % inc, xbx % alp_size, xbx % alp, &
                                 xbx % wsave, power, rcv_out, field_out)

   write(unit=stdout,fmt='(A)') ' Adjoint test result for  Spectral -> Grid : '
   write(unit=stdout,fmt='(1x,a,e30.10)') &
      ' LHS  ( LX.LX)       = ',&
      sum( field_out(1:xbx%ni,1:xbx%nj)*field_out(1:xbx%ni,1:xbx%nj) ) 
   write(unit=stdout,fmt='(1x,a,e30.10)') &
      ' RHS  (  X.L^TLX )   = ', sum( rcv(1:2*sizec)*rcv_out(1:2*sizec) ) 

   ! Inverse test for Legendre Transform

   write(unit=stdout,fmt='(A)') '  Inverse and Adjoint Legendre test result:'

   do m = 0, max_wave
      index_start = m * ( max_wave + 1 - m ) + m * ( m + 1 ) / 2 + 1
      index_end   = index_start + max_wave - m

      do mm = index_start, index_end
         if (2*mm > 2*sizec) then
            call da_error(__FILE__,__LINE__, &
               (/"rcv_out index bounce"/))
         end if
         ccv(mm) = cmplx (rcv_out(2*mm-1), rcv_out(2*mm))
      end do
      r_leg = 0.0
      call da_legtra_inv( jds, jde, jts, jte, max_wave, xbx%alp_size, m, xbx%alp, &
                          ccv(index_start:index_end), r_leg )

      ccv1(index_start:index_end) = 0.0
      call da_legtra ( xbx%nj, max_wave, xbx%alp_size, m, xbx%int_wgts, xbx%alp, r_leg, &
                       ccv1(index_start:index_end) )
      ccv1(index_start:index_end) = ccv1(index_start:index_end) - &
                                    ccv(index_start:index_end) 
      num =  sum ( real(ccv1(index_start:index_end))*real(ccv1(index_start:index_end))+&
         aimag(ccv1(index_start:index_end))* aimag(ccv1(index_start:index_end)) )     
      den =  sum ( real(ccv(index_start:index_end))*real(ccv(index_start:index_end))+&
         aimag(ccv(index_start:index_end))* aimag(ccv(index_start:index_end)) )     
      write(unit=stdout,fmt='(A,I4,A,E30.20)') &
         'For zonal wave number',m,' difference ',sqrt(num)/sqrt(den)

      xx = sum( real(r_leg(1:xbx%nj))* real(r_leg(1:xbx%nj))+ &
               aimag(r_leg(1:xbx%nj))*aimag(r_leg(1:xbx%nj)) )
      write(unit=stdout,fmt='(a,i5,a,e30.20)') 'For Wave = ',m,' LX.LX    = ',xx

      ccv1(index_start:index_end) = 0.0
      call da_legtra_inv_adj( jds, jde, jts, jte, max_wave, xbx%alp_size, m, xbx%alp, &
                              ccv1(index_start:index_end), r_leg )
      xx = sum( real(ccv(index_start:index_end))*     &
                real(ccv1(index_start:index_end))     +&
               aimag(ccv(index_start:index_end))* &
               aimag(ccv1(index_start:index_end)) )
      write(unit=stdout,fmt='(a,i5,a,e30.20,/)') 'For Wave = ',m,' X.L^TLX  = ',xx
   end do

   if (trace_use) call da_trace_exit("da_test_spectral")

end subroutine da_test_spectral