!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module cubetools_speelt_types
  use cubetools_parameters
  use cubeheader_messaging
  use cubetools_consistency_types
  !
  public :: speelt_t, speelt_cons_t
  public :: cubetools_speelt_init,cubetools_speelt_get_and_derive
  public :: cubetools_speelt_final,cubetools_speelt_put
  public :: cubetools_speelt_list,cubetools_speelt_sicdef,cubetools_speelt_copy
  public :: cubetools_speelt_consistency_check,cubetools_speelt_consistency_list
  public :: cubetools_speelt_consistency_init,cubetools_speelt_consistency_final
  public :: cubetools_speelt_consistency_set_tol
  private
  !
  type speelt_t
     real(kind=coor_k) :: c = 0d0 ! [----] Channel
     real(kind=coor_k) :: f = 0d0 ! [ MHz] Signal frequency
     real(kind=coor_k) :: i = 0d0 ! [ MHz] Image frequency
     real(kind=coor_k) :: l = 0d0 ! [ mum] Wavelength
     real(kind=coor_k) :: v = 0d0 ! [km/s] Systemic velocity
     real(kind=coor_k) :: z = 0d0 ! [----] Systemic redshift
  end type speelt_t
  !
  type speelt_cons_t
     logical                    :: check=.true.  ! Check the section
     logical                    :: prob =.false. ! Is there a problem
     logical                    :: mess =.true.  ! Output message for this section?
     type(consistency_desc_t)   :: c  ! Channel consistency          
     type(consistency_desc_t)   :: f  ! Frequency consisntency
     type(consistency_desc_t)   :: i  ! Image frequency consistency
     type(consistency_desc_t)   :: l  ! Wavelength consistency
     type(consistency_desc_t)   :: v  ! Velocity consistency
     type(consistency_desc_t)   :: z  ! Redshift consistency
  end type speelt_cons_t
  !
contains
  !
  subroutine cubetools_speelt_init(speelt,error)
    !-------------------------------------------------------------------
    ! Just initialize the type, ie, set it intent(out)
    !-------------------------------------------------------------------
    type(speelt_t), intent(out)   :: speelt
    logical,        intent(inout) :: error
    !
    character(len=*), parameter :: rname='SPEELT>INIT'
    !
    call cubeheader_message(headseve%trace,rname,'Welcome')
  end subroutine cubetools_speelt_init
  !
  subroutine cubetools_speelt_get_and_derive(speelt,error)
    !-------------------------------------------------------------------
    !
    !-------------------------------------------------------------------
    type(speelt_t), intent(inout) :: speelt
    logical,        intent(inout) :: error
    !
    character(len=*), parameter :: rname='SPEELT>GET>AND>DERIVE'
    !
    call cubeheader_message(headseve%trace,rname,'Welcome')
    !
!!$    speelt%l => lval
!!$    speelt%m => mval
  end subroutine cubetools_speelt_get_and_derive
  !
  subroutine cubetools_speelt_put(speelt,error)
    !-------------------------------------------------------------------
    ! Empty method on purpose as speelt is a pointer set
    !-------------------------------------------------------------------
    type(speelt_t), intent(in)    :: speelt
    logical,        intent(inout) :: error
    !
    character(len=*), parameter :: rname='SPEELT>PUT'
    !
    call cubeheader_message(headseve%trace,rname,'Welcome')
  end subroutine cubetools_speelt_put
  !
  subroutine cubetools_speelt_final(speelt,error)
    !-------------------------------------------------------------------
    ! Just reinitialize the type, ie, set it intent(out)
    !-------------------------------------------------------------------
    type(speelt_t), intent(out)   :: speelt
    logical,        intent(inout) :: error
    !
    character(len=*), parameter :: rname='SPEELT>FINAL'
    !
    call cubeheader_message(headseve%trace,rname,'Welcome')
  end subroutine cubetools_speelt_final
  !
  !---------------------------------------------------------------------
  !
  subroutine cubetools_speelt_list(speelt,error)
    use cubetools_format
    !-------------------------------------------------------------------
    ! Empty method until there is a clear usecase
    !-------------------------------------------------------------------
    type(speelt_t), intent(in)    :: speelt
    logical,        intent(inout) :: error
    !
    character(len=*), parameter :: rname='SPEELT>LIST'
    !
    call cubeheader_message(headseve%trace,rname,'Welcome')
  end subroutine cubetools_speelt_list
  !
  subroutine cubetools_speelt_sicdef(name,elt,readonly,error)
    use gkernel_interfaces
    !-------------------------------------------------------------------
    !
    !-------------------------------------------------------------------
    character(len=*), intent(in)    :: name
    type(speelt_t),   intent(in)    :: elt
    logical,          intent(in)    :: readonly
    logical,          intent(inout) :: error
    !
    character(len=*), parameter :: rname='SPEELT>SICDEF'
    !
    call cubeheader_message(headseve%trace,rname,'Welcome')
    !
    call sic_defstructure(name,global,error)
    if (error) return 
    call sic_def_dble(trim(name)//'%C',elt%c,0,0,readonly,error)
    if (error) return
    call sic_def_dble(trim(name)//'%F',elt%f,0,0,readonly,error)
    if (error) return
    call sic_def_dble(trim(name)//'%I',elt%i,0,0,readonly,error)
    if (error) return
    call sic_def_dble(trim(name)//'%L',elt%l,0,0,readonly,error)
    if (error) return
    call sic_def_dble(trim(name)//'%V',elt%v,0,0,readonly,error)
    if (error) return
    call sic_def_dble(trim(name)//'%Z',elt%z,0,0,readonly,error)
    if (error) return
  end subroutine cubetools_speelt_sicdef
  !
  subroutine cubetools_speelt_copy(in,ou,error)
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    type(speelt_t), intent(in)    :: in
    type(speelt_t), intent(out)   :: ou
    logical,        intent(inout) :: error
    !
    character(len=*), parameter :: rname='SPEELT>COPY'
    !
    call cubeheader_message(headseve%trace,rname,'Welcome')
    !
    ou = in
  end subroutine cubetools_speelt_copy
  !
  !----------------------------------------------------------------------
  !
  subroutine cubetools_speelt_consistency_init(cons,error)
    !----------------------------------------------------------------------
    ! Init spectral element consistency
    !----------------------------------------------------------------------
    type(speelt_cons_t), intent(inout) :: cons
    logical,             intent(inout) :: error
    !
    character(len=*), parameter :: rname='SPEELT>CONSISTENCY>INIT'
    !
    call cubeheader_message(headseve%trace,rname,'Welcome')
    !
    call cubetools_consistency_init(strict,check,mess,cons%c,error)
    if (error) return
    call cubetools_consistency_init(strict,check,mess,cons%f,error)
    if (error) return
    call cubetools_consistency_init(strict,check,mess,cons%i,error)
    if (error) return
    call cubetools_consistency_init(strict,check,mess,cons%l,error)
    if (error) return
    call cubetools_consistency_init(strict,check,mess,cons%v,error)
    if (error) return
    call cubetools_consistency_init(strict,check,mess,cons%z,error)
    if (error) return
  end subroutine cubetools_speelt_consistency_init
  !
  subroutine cubetools_speelt_consistency_set_tol(elttol,cons,error)
    !-------------------------------------------------------------------
    !
    !-------------------------------------------------------------------
    real(kind=tole_k),   intent(in)    :: elttol
    type(speelt_cons_t), intent(inout) :: cons
    logical,             intent(inout) :: error
    !
    character(len=*), parameter :: rname='SPEELT>CONSISTENCY>SET>TOL'
    !
    call cubeheader_message(headseve%trace,rname,'Welcome')
    !
    cons%c%tol = elttol
    cons%f%tol = elttol
    cons%i%tol = elttol
    cons%l%tol = elttol
    cons%v%tol = elttol
    cons%z%tol = elttol
  end subroutine cubetools_speelt_consistency_set_tol
  !
  subroutine cubetools_speelt_consistency_check(cons,inc1,ref1,inc2,ref2,error)
    !----------------------------------------------------------------------
    ! Check spectral element consistency
    !----------------------------------------------------------------------
    type(speelt_cons_t), intent(inout) :: cons
    type(speelt_t),      intent(in)    :: inc1
    type(speelt_t),      intent(in)    :: ref1
    type(speelt_t),      intent(in)    :: inc2
    type(speelt_t),      intent(in)    :: ref2
    logical,             intent(inout) :: error
    !
    character(len=*), parameter :: rname='SPEELT>CONSISTENCY>CHECK'
    !
    call cubeheader_message(headseve%trace,rname,'Welcome')
    !
    if (.not.cons%check) return
    !
    call cubetools_consistency_real_relative_check(cons%c,inc1%c,ref1%c,inc2%c,ref2%c,error)
    if (error) return
    call cubetools_consistency_real_relative_check(cons%f,inc1%f,ref1%f,inc2%f,ref2%f,error)
    if (error) return
    call cubetools_consistency_real_relative_check(cons%i,inc1%i,ref1%i,inc2%i,ref2%i,error)
    if (error) return
    call cubetools_consistency_real_relative_check(cons%l,inc1%l,ref1%l,inc2%l,ref2%l,error)
    if (error) return
    call cubetools_consistency_real_relative_check(cons%v,inc1%v,ref1%v,inc2%v,ref2%v,error)
    if (error) return
    call cubetools_consistency_real_relative_check(cons%z,inc1%z,ref1%z,inc2%z,ref2%z,error)
    if (error) return
    !
    cons%prob = cons%c%prob.or.cons%f%prob.or.cons%i%prob.or.cons%l%prob.or.cons%v%prob.or.cons%z%prob
  end subroutine cubetools_speelt_consistency_check
  !
  subroutine cubetools_speelt_consistency_list(cons,ref1,ref2,error)
    use cubetools_unit
    !----------------------------------------------------------------------
    ! Print spectral element consistency
    !----------------------------------------------------------------------
    type(speelt_cons_t), intent(in)    :: cons
    type(speelt_t),      intent(in)    :: ref1
    type(speelt_t),      intent(in)    :: ref2
    logical,             intent(inout) :: error
    !
    type(unit_user_t) :: unitfreq,unitvelo
    character(len=*), parameter :: rname='SPEELT>CONSISTENCY>LIST'
    !
    call cubeheader_message(headseve%trace,rname,'Welcome')
    !
    if (.not.cons%mess) return
    !
    call cubetools_consistency_title('spectral references',3,cons%check,cons%prob,error)
    if (error) return
    if (cons%check.and.cons%prob) then
       call unitfreq%get_from_code(code_unit_freq,error)
       if (error) return
       call unitvelo%get_from_code(code_unit_velo,error)
       if (error) return
       call cubetools_consistency_real_print('Channel',cons%c,ref1%c,ref2%c,error)
       if (error) return
       call cubetools_consistency_real_print('Rest frequency',unitfreq%name,cons%f,&
            ref1%f*unitfreq%user_per_prog,ref2%f*unitfreq%user_per_prog,error)
       if (error) return
       call cubetools_consistency_real_print('Image frequency',unitfreq%name,cons%i,&
            ref1%i*unitfreq%user_per_prog,ref2%i*unitfreq%user_per_prog,error)
       if (error) return
       call cubetools_consistency_real_print('Wavelength','mum',cons%l,ref1%l,ref2%l,error)
       if (error) return
       call cubetools_consistency_real_print('Velocity',unitvelo%name,cons%v,ref1%v*unitvelo%user_per_prog,&
            ref2%v*unitvelo%user_per_prog,error)
       if (error) return
       call cubetools_consistency_real_print('Redshift',cons%z,ref1%z,ref2%z,error)
       if (error) return
    endif
    call cubeheader_message(seve%r,rname,'')
  end subroutine cubetools_speelt_consistency_list
  !
  subroutine cubetools_speelt_consistency_final(cons,error)
    !----------------------------------------------------------------------
    ! Final spectral element consistency
    !----------------------------------------------------------------------
    type(speelt_cons_t), intent(inout) :: cons
    logical,             intent(inout) :: error
    !
    character(len=*), parameter :: rname='SPEELT>CONSISTENCY>FINAL'
    !
    call cubeheader_message(headseve%trace,rname,'Welcome')
    !
    call cubetools_consistency_final(cons%c,error)
    if (error) return
    call cubetools_consistency_final(cons%f,error)
    if (error) return
    call cubetools_consistency_final(cons%i,error)
    if (error) return
    call cubetools_consistency_final(cons%l,error)
    if (error) return
    call cubetools_consistency_final(cons%v,error)
    if (error) return
    call cubetools_consistency_final(cons%z,error)
    if (error) return
  end subroutine cubetools_speelt_consistency_final
end module cubetools_speelt_types
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
