subroutine atm_init(error)
  use gbl_message
  use gkernel_interfaces
  use atm_params
  use ast_astro
  !---------------------------------------------------------------------
  ! @ private
  ! ATM
  !
  ! One time instantiation of the ASTRO variables which are used (as
  ! input and output) by the command ASTRO\ATM. These variables and
  ! their startup values are not needed if the programmer does want
  ! to make use of the command ASTRO\ATM.
  !---------------------------------------------------------------------
  logical, intent(inout) :: error   ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='ATM_INIT'
  !
  if (atm_initdone) return
  !
  call atm_sicvariables(error)
  if (error) then
    call astro_message(seve%e,rname,'Error creating ATM% variables')
    return
  endif
  !
  ! Default values of input parameters
  t0 = 273.0
  p0 = 1013.0
  water = 1.0
  airmass = 1.414
  feff = 0.95
  freqs = 110.0
  freqi = 113.0
  gim = 1.0
  trec = 60
  !
  ! Input parameters
  call sic_def_real ('TEMPERATURE',t0,0,1,.false.,error)
  if (error) return
  call sic_def_real ('TRUE_PRESSURE',p1,0,1,.true.,error)
  if (error) return
  call sic_def_real ('ZERO_PRESSURE',p0,0,1,.false.,error)
  if (error) return
  call sic_def_dble ('ALTITUDE',altitude,0,1,.true.,error)
  if (error) return
  call sic_def_real ('WATER',water,0,1,.false.,error)
  !! if (error) return
  call sic_def_real ('AIRMASS',airmass,0,1,.false.,error)
  if (error) return
  call sic_def_real ('FORWARD_EFF',feff,0,1,.false.,error)
  !! if (error) return
  call sic_def_real ('FREQ_SIG',freqs,0,1,.false.,error)
  if (error) return
  call sic_def_real ('FREQ_IMA',freqi,0,1,.false.,error)
  if (error) return
  call sic_def_real ('GAIN_IMAGE',gim,0,1,.false.,error)
  !! if (error) return
  call sic_def_real ('TREC',trec,0,1,.false.,error)
  if (error) return
  !
  ! Output parameters
  call sic_def_real ('TSYS',tsys,0,1,.true.,error)
  !! if (error) return
  call sic_def_real ('TAU_O2',tauox,0,1,.true.,error)
  if (error) return
  call sic_def_real ('TAU_H2O',tauw,0,1,.true.,error)
  if (error) return
  call sic_def_real ('TAU_TOT',taut,0,1,.true.,error)
  if (error) return
  call sic_def_real ('EMIS_SIG',temis,0,1,.true.,error)
  if (error) return
  call sic_def_real ('EMIS_IMA',temii,0,1,.true.,error)
  if (error) return
  call sic_def_real ('PATH_SIG',paths,0,1,.true.,error)
  if (error) return
  call sic_def_real ('PATH_IMA',pathi,0,1,.true.,error)
  if (error) return
  call sic_def_real ('ATM_SIG',tatms,0,1,.true.,error)
  if (error) return
  call sic_def_real ('ATM_IMA',tatmi,0,1,.true.,error)
  if (error) return
  call sic_def_real ('TANT',tant,0,1,.true.,error)
  if (error) return
  !
  call astro_message(seve%d,rname,'ATM-ASTRO interface initialized')
  atm_initdone = .true.
  !
end subroutine atm_init
!
subroutine astro_atm(line,error)
  use gildas_def
  use gkernel_interfaces
  use atm_params
  use atm_interfaces_public
  use ast_astro
  !---------------------------------------------------------------------
  ! @ private
  ! ATM
  !
  ! Purpose: compute atmospheric properties
  !     from a full set of SIC variables
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line   ! Input command line
  logical,          intent(inout) :: error  ! Logical error flag
  ! Local
  integer(kind=4), parameter :: optprint=1
  integer(kind=4), parameter :: optfrequ=2
  integer(kind=4) :: ier,nfile,nf
  real(kind=4) :: frequ,fmin,fmax
  character(len=filename_length) :: file
  integer(kind=4), parameter :: mact=3
  integer(kind=4) :: nact,nname
  character(len=11) :: actions(mact) = (/'INTERPOLATE','MAKE       ','SAVE       '/)
  character(len=16) :: action,name
  logical, save :: first
  ! Data
  data first /.true./
  !
  ! Optionally print ATM status before the actions below
  if (sic_present(optprint,0))  call astro_atm_print(error)
  !
  h0 = altitude
  if (.not.sic_present(0,1)) then
    !
    p1 = p0*2.0**(-h0/5.5)     ! Pressure at altitude H0
    call atm_atmosp(t0,p1,h0)
    !
    if (sic_present(optfrequ,0)) then
      call astro_atm_compute_1d(line,error)
    else
      call astro_atm_compute_0d(line,error)
    endif
    if (error)  return
    !
  else
    ! Read binary file once.
    if (first) then
      call atm_i(error)
      first = .false.
    endif
    ! Retrieve and analyze first argument
    call sic_ke(line,0,1,name,nname,.true.,error)
    if (error) return
    call sic_ambigs('ATMOSPHERE',name(1:nname),action,nact,actions,mact,error)
    if (error) return
    !
    if (action.eq.'INTERPOLATE') then
      ! Interpolate from file:
      call atm_atmosp_i(t0,p1,h0)
      !
      frequ = freqi
      call atm_transm_i(water,airmass,frequ,temii,tatmi,tauox,tauw,taut,ier)
      call atm_path_i(water,airmass,frequ,pathi,ier)
      pathi = pathi*10         ! -> mm
      !
      frequ = freqs
      call atm_transm_i(water,airmass,frequ,temis,tatms,tauox,tauw,taut,ier)
      call atm_path_i(water,airmass,frequ,paths,ier)
      paths = paths*10         ! -> mm
      !
      tant = (gim * (feff*temii+(1.0-feff)*t0 + trec) +  &
             (feff*temis+(1.0-feff)*t0 + trec) ) / (1.0+gim)
      tsys = exp(taut*airmass) * (gim * (feff*temii+(1.0-feff)*t0 + trec) +  &
             (feff*temis+(1.0-feff)*t0 + trec) ) / feff
      !
    elseif (action.eq.'MAKE') then
      ! Make a file: ATM Make filename nf fmin fmax
      file = ' '
      call sic_ch(line,0,2,file,nfile,.true.,error)
      if (error) return
      nf = 200
      fmin = 75.
      fmax = 300.
      call sic_i4(line,0,3,nf,.false.,error)
      if (error) return
      call sic_r4(line,0,4,fmin,.false.,error)
      if (error) return
      call sic_r4(line,0,5,fmax,.false.,error)
      if (error) return
      call atmos_i_table(.true.,file,nfile,nf,fmin,fmax,h0,error)
      !
    elseif (action.eq.'SAVE') then
      ! Save on file previously loaded table: ATM Save filename
      ! This one may be used to save with the current machine byte order a
      ! table previously loaded whose byte order was different.
      file = ' '
      call sic_ch(line,0,2,file,nfile,.true.,error)
      if (error) return
      nf = 200
      fmin = 75.
      fmax = 300.
      call atmos_i_table(.false.,file,nfile,nf,fmin,fmax,h0,error)
      !
    endif
  endif
  !
end subroutine astro_atm
!
subroutine astro_atm_print(error)
  use gbl_message
  use atm_params
  use ast_astro
  !---------------------------------------------------------------------
  ! @ private
  ! ATM
  !
  ! Support routine for command:
  !   ASTRO\ATM /PRINT
  !---------------------------------------------------------------------
  logical, intent(inout) :: error   ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='ATM_PRINT'
  character(len=message_length) :: mess
  !
  call astro_message(seve%r,rname,'Current status of ATM is')
  !
  ! Print ATM internal parameters
  call atm_print(error)
  !
  ! Print ASTRO_ATM internal parameters
  write(mess,101) 'TEMPERATURE',t0,'[K]','Ground temperature'
  call astro_message(seve%r,rname,mess)
  !
  write(mess,101) 'ZERO_PRESSURE',p0,'[hPa]','Pressure at sea level'
  call astro_message(seve%r,rname,mess)
  !
  write(mess,101) 'ALTITUDE',altitude,'[km]','Altitude of the observatory'
  call astro_message(seve%r,rname,mess)
  !
  write(mess,101) 'WATER',water,'[mm]','Precipitable water vapor'
  call astro_message(seve%r,rname,mess)
  !
  write(mess,101) 'AIRMASS',airmass,'[]','Number of airmasses'
  call astro_message(seve%r,rname,mess)
  !
  write(mess,101) 'FORWARD_EFF',feff,'[]','Forward efficiency'
  call astro_message(seve%r,rname,mess)
  !
  write(mess,101) 'FREQ_SIG',freqs,'[GHz]','Signal frequency'
  call astro_message(seve%r,rname,mess)
  !
  write(mess,101) 'FREQ_IMA',freqi,'[GHz]','Image frequency'
  call astro_message(seve%r,rname,mess)
  !
  write(mess,101) 'GAIN_IMAGE',gim,'[]','Gain image'
  call astro_message(seve%r,rname,mess)
  !
  write(mess,101) 'TREC',trec,'[K]','Receiver temperature'
  call astro_message(seve%r,rname,mess)
  !
101 format(A,T23,F12.3,T36,A6,T43,A)
  !
end subroutine astro_atm_print
!
subroutine astro_atm_compute_0d(line,error)
  use atm_interfaces_public
  use atm_params
  !---------------------------------------------------------------------
  ! @ private
  ! Support routine for command
  !   ASTRO\ATM
  ! i.e. compute (direct call to libatm) the atmosphere according to
  ! user inputs found in Sic variables (scalar version)
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line   ! Input command line
  logical,          intent(inout) :: error  ! Logical error flag
  ! Local
  integer(kind=4) :: ier
  !
  call atm_transm(water,airmass,freqi,temii,tatmi,tauox,tauw,taut,ier)
  call atm_path(water,airmass,freqi,pathi,ier)
  pathi = pathi*10  ! -> mm
  !
  call atm_transm(water,airmass,freqs,temis,tatms,tauox,tauw,taut,ier)
  call atm_path(water,airmass,freqs,paths,ier)
  paths = paths*10  ! -> mm
  !
  tant = (gim * (feff*temii+(1.0-feff)*t0 + trec) +  &
         (feff*temis+(1.0-feff)*t0 + trec) ) / (1.0+gim)
  tsys = exp(taut*airmass) * (gim * (feff*temii+(1.0-feff)*t0 + trec) +  &
                             (feff*temis+(1.0-feff)*t0 + trec) ) / feff
  !
end subroutine astro_atm_compute_0d
!
subroutine astro_atm_compute_1d(line,error)
  use gildas_def
  use gbl_message
  use gkernel_types
  use gkernel_interfaces
  use atm_interfaces_public
  use atm_params
  !---------------------------------------------------------------------
  ! @ private
  ! Support routine for command
  !   ASTRO\ATM /FREQ SIGNAL IMAGE
  ! i.e. compute (direct call to libatm) the atmosphere according to
  ! user inputs found in Sic variables, and to the frequency arrays
  ! passed to the option (1D version)
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: line   ! Input command line
  logical,          intent(inout) :: error  ! Logical error flag
  ! Local
  character(len=*), parameter :: rname='ATM'
  integer(kind=4), parameter :: optfrequ=2
  type(sic_descriptor_t) :: sdesc
  real(kind=4) :: intfreq
  integer(kind=4) :: ier
  integer(kind=size_length) :: ifreq,nfreq
  real(kind=4), allocatable :: sig(:),ima(:)  ! R*4 for atm_transm
  real(kind=4), allocatable :: mytemii(:),mytatmi(:),mytemis(:),mytatms(:)
  real(kind=4), allocatable :: mytauox(:),mytauw(:),mytaut(:),mytant(:),mytsys(:)
  integer(kind=4), allocatable :: myier(:)
  !
  ! First: do not leave ambiguous products if the command needs to stop
  ! before the end.
  call delete_variables()
  !
  ! Retrieve user inputs: signal frequencies can be scalar explicit value,
  ! scalar variable, or array variable:
  call sic_de(line,optfrequ,1,sdesc,.true.,error)  ! Signal
  if (error)  return
  intfreq = 0.  ! Default 0 means image freq == signal freq
  call sic_r4(line,optfrequ,2,intfreq,.false.,error)
  if (error)  goto 10
  !
  ! Incarnate the frequency arrays from user inputs
  nfreq = desc_nelem(sdesc)
  allocate(sig(nfreq),ima(nfreq),stat=ier)
  if (failed_allocate(rname,'freq. arrays',ier,error))  goto 10
  call sic_descriptor_getval(sdesc,sig,nfreq,error)
10 continue
  call sic_volatile(sdesc)  ! Not needed anymore
  if (error)  return
  if (intfreq.le.0.) then
    ima(:) = sig(:)
  else
    do ifreq=1,nfreq
      ima(ifreq) = 2.*intfreq-sig(ifreq)
    enddo
  endif
  !
  ! Temporary arrays: we could avoid them if one day we will be able
  ! to get a Fortran R*4 pointer to the Sic variable allocated memory...
  allocate(mytemii(nfreq),mytatmi(nfreq),mytemis(nfreq),mytatms(nfreq),  &
           mytauox(nfreq),mytauw(nfreq),mytaut(nfreq),myier(nfreq),      &
           mytant(nfreq),mytsys(nfreq),stat=ier)
  if (failed_allocate(rname,'output arrays',ier,error))  return
  !
  ! Actual ATM computations:
  call atm_transm(water,airmass,ima,mytemii,mytatmi,mytauox,mytauw,mytaut,myier)
  call atm_transm(water,airmass,sig,mytemis,mytatms,mytauox,mytauw,mytaut,myier)
  mytant(:) = (gim * (feff*mytemii+(1.0-feff)*t0 + trec) +  &
                     (feff*mytemis+(1.0-feff)*t0 + trec) ) / (1.0+gim)
  mytsys(:) = exp(mytaut*airmass) * (gim * (feff*mytemii+(1.0-feff)*t0 + trec) +  &
                                           (feff*mytemis+(1.0-feff)*t0 + trec) ) / feff
  !
  ! Save the products in Sic variables
  call define_variables(nfreq,error)
  if (error)  return
  call fill_variables(error)
  if (error)  return
  !
  ! Cleaning: let Fortran deallocate the allocatable arrays
  !
contains
  !
  subroutine delete_variables()
    !-------------------------------------------------------------------
    !
    !-------------------------------------------------------------------
    call sic_delvariable('ATM%EMIS_IMA',.false.,error)
    error = .false.
    call sic_delvariable('ATM%ATM_IMA',.false.,error)
    error = .false.
    call sic_delvariable('ATM%EMIS_SIG',.false.,error)
    error = .false.
    call sic_delvariable('ATM%ATM_SIG',.false.,error)
    error = .false.
    call sic_delvariable('ATM%TAU_O2',.false.,error)
    error = .false.
    call sic_delvariable('ATM%TAU_H2O',.false.,error)
    error = .false.
    call sic_delvariable('ATM%TAU_TOT',.false.,error)
    error = .false.
    call sic_delvariable('ATM%IER',.false.,error)
    error = .false.
    call sic_delvariable('ATM%TANT',.false.,error)
    error = .false.
    call sic_delvariable('ATM%TSYS',.false.,error)
    error = .false.
  end subroutine delete_variables
  !
  subroutine define_variables(nfreq,error)
    !-------------------------------------------------------------------
    ! Create Sic variables which will hold the results
    !-------------------------------------------------------------------
    integer(kind=size_length), intent(in)    :: nfreq
    logical,                   intent(inout) :: error
    ! Local
    character(len=8) :: dims
    !
    write(dims,'(A,I0,A)') '[',nfreq,']'
    call sic_defvariable(fmt_r4,'ATM%EMIS_IMA'//dims,.true.,error)
    if (error)  return
    call sic_defvariable(fmt_r4,'ATM%ATM_IMA'//dims,.true.,error)
    if (error)  return
    call sic_defvariable(fmt_r4,'ATM%EMIS_SIG'//dims,.true.,error)
    if (error)  return
    call sic_defvariable(fmt_r4,'ATM%ATM_SIG'//dims,.true.,error)
    if (error)  return
    call sic_defvariable(fmt_r4,'ATM%TAU_O2'//dims,.true.,error)
    if (error)  return
    call sic_defvariable(fmt_r4,'ATM%TAU_H2O'//dims,.true.,error)
    if (error)  return
    call sic_defvariable(fmt_r4,'ATM%TAU_TOT'//dims,.true.,error)
    if (error)  return
    call sic_defvariable(fmt_i4,'ATM%IER'//dims,.true.,error)
    if (error)  return
    call sic_defvariable(fmt_r4,'ATM%TANT'//dims,.true.,error)
    if (error)  return
    call sic_defvariable(fmt_r4,'ATM%TSYS'//dims,.true.,error)
    if (error)  return
  end subroutine define_variables
  !
  subroutine fill_variables(error)
    !-------------------------------------------------------------------
    !
    !-------------------------------------------------------------------
    logical, intent(inout) :: error
    !
    call sic_variable_fill(rname,'ATM%EMIS_IMA',mytemii,nfreq,error)
    if (error)  return
    call sic_variable_fill(rname,'ATM%ATM_IMA',mytatmi,nfreq,error)
    if (error)  return
    call sic_variable_fill(rname,'ATM%EMIS_SIG',mytemis,nfreq,error)
    if (error)  return
    call sic_variable_fill(rname,'ATM%ATM_SIG',mytatms,nfreq,error)
    if (error)  return
    call sic_variable_fill(rname,'ATM%TAU_O2',mytauox,nfreq,error)
    if (error)  return
    call sic_variable_fill(rname,'ATM%TAU_H2O',mytauw,nfreq,error)
    if (error)  return
    call sic_variable_fill(rname,'ATM%TAU_TOT',mytaut,nfreq,error)
    if (error)  return
    call sic_variable_fill(rname,'ATM%IER',myier,nfreq,error)
    if (error)  return
    call sic_variable_fill(rname,'ATM%TANT',mytant,nfreq,error)
    if (error)  return
    call sic_variable_fill(rname,'ATM%TSYS',mytsys,nfreq,error)
    if (error)  return
  end subroutine fill_variables
  !
end subroutine astro_atm_compute_1d
