module rfxqlo_interface

  use rfxqlo_types
  implicit NONE

  !
  !  public module -- define data types and methods to facilitate
  !    communication btw:
  !       Fokker Planck code (driver)
  !       RF wave solver
  !       Fokker Planck code (quasilinear operator)
  !
  !  this is derived from fppmod and its interface to 4 wave solvers:
  !  "Dave Smithe" spruce, "Michel Evrard" spruce, toric (vsn 3), and
  !  toric (vsn 4).
  !
  !  dmc -- 2 July 2003
  !
  !  data types defined in rfxqlo_types, used here...

  !====================================================================

  interface

     !---------------------------------------------------------
     !  free rfxqlo private data after completion of RF calculations
     subroutine rfxqlo_free(iwarn)
       integer, intent(out) :: iwarn  ! =0: normal; =1: no prior allocation.
     end subroutine rfxqlo_free

     !---------------------------------------------------------
     !  dimensioning information:
     !    these dimensions will indicate: no. of antennae, 
     !    max no. of Nphi spectrum values per antenna.

     !  get *default* rfxqlo private data dimensions
     subroutine rfxqlo_dim_dflts(zdim)
       use rfxqlo_types
       type (rfxqlo_dims), intent(out) :: zdim
     end subroutine rfxqlo_dim_dflts

     !  set rfxqlo private data dimensions -- allocate arrays
     subroutine rfxqlo_dim_set(zdim,ierr)
       use rfxqlo_types
       type (rfxqlo_dims), intent(in) :: zdim
       integer, intent(out) :: ierr   ! 0: OK; 1: invalid dimension value
     end subroutine rfxqlo_dim_set

     !  get rfxqlo private data dimensions (as previously set)
     subroutine rfxqlo_dim_get(zdim,ierr)
       use rfxqlo_types
       type (rfxqlo_dims), intent(out) :: zdim
       integer, intent(out) :: ierr   ! 0: OK; 1: dimensions were never set.
     end subroutine rfxqlo_dim_get

     !---------------------------------------------------------
     !  vacuum region information

     !  get *default* rfxqlo vacuum region data
     subroutine rfxqlo_vacuum_dflts(zvac)
       use rfxqlo_types
       type (rfxqlo_vacuum), intent(out) :: zvac
     end subroutine rfxqlo_vacuum_dflts

     !  set rfxqlo vacuum region data
     subroutine rfxqlo_vacuum_set(zvac,ierr)
       use rfxqlo_types
       type (rfxqlo_vacuum), intent(in) :: zvac
       integer, intent(out) :: ierr     ! 0: OK; 1: error
     end subroutine rfxqlo_vacuum_set

     !  get rfxqlo vacuum region data (as previously set)
     subroutine rfxqlo_vacuum_get(zvac,ierr)
       use rfxqlo_types
       type (rfxqlo_vacuum), intent(out) :: zvac
       integer, intent(out) :: ierr     ! 0: ok; 1: vacuum data never set.
     end subroutine rfxqlo_vacuum_get

     !---------------------------------------------------------
     ! choose antenna, to which subsequent calls will refer...

     subroutine rfxqlo_select_antenna(i_antenna,ierr)
       integer, intent(in) :: i_antenna   ! antenna index
       integer, intent(out) :: ierr       ! set =1 if i_antenna out of range
     end subroutine rfxqlo_select_antenna

     !---------------------------------------------------------
     ! having chosen antenna, select specific Nphi value from spectrum;
     !  this call should be preceeded by an rfxqlo_select_antenna call...

     subroutine rfxqlo_select_nphi(i_nphi,ierr)
       integer, intent(in) :: i_nphi      ! Nphi index
       integer, intent(out) :: ierr       ! 0=OK; set =1 if i_nphi out of range
     end subroutine rfxqlo_select_nphi

     !---------------------------------------------------------
     !  antenna region information

     !  get *default* rfxqlo antenna data
     subroutine rfxqlo_antenna_dflts(zant)
       use rfxqlo_types
       type (rfxqlo_antenna), intent(out) :: zant
     end subroutine rfxqlo_antenna_dflts

     !  set rfxqlo antenna data 
     !    (preceeding rfxqlo_select_antenna call required).
     subroutine rfxqlo_antenna_set(zant,ierr)
       use rfxqlo_types
       type (rfxqlo_antenna), intent(in) :: zant
       integer, intent(out) :: ierr      ! 0: OK; 1: error in antenna data.
     end subroutine rfxqlo_antenna_set

     !  get rfxqlo antenna data (as previously set)
     !    (preceeding rfxqlo_select_antenna call required).
     subroutine rfxqlo_antenna_get(zant,ierr)
       use rfxqlo_types
       type (rfxqlo_antenna), intent(out) :: zant
       integer, intent(out) :: ierr      ! 0: OK; 1: antenna data never set.
     end subroutine rfxqlo_antenna_get

     !---------------------------------------------------------
     !  set/get lun for messages

     subroutine rfxqlo_set_lunmsg(ilun)
       integer, intent(in) :: ilun      ! fortran unit to use for messages
     end subroutine rfxqlo_set_lunmsg

     subroutine rfxqlo_get_lunmsg(ilun)
       integer, intent(out) :: ilun     ! fortran now being used for messages
     end subroutine rfxqlo_get_lunmsg

     !---------------------------------------------------------
     !  basic system information

     !  get *default* system info
     subroutine rfxqlo_system_dflts(zsys)
       use rfxqlo_types
       type (rfxqlo_system), intent(out) :: zsys
     end subroutine rfxqlo_system_dflts

     !  set rfxqlo system info
     subroutine rfxqlo_system_set(zsys,ierr)
       use rfxqlo_types
       type (rfxqlo_system), intent(in) :: zsys
       integer, intent(out) :: ierr     ! 0: OK; 1: error
     end subroutine rfxqlo_system_set

     !  get rfxqlo system info
     subroutine rfxqlo_system_get(zsys,ierr)
       use rfxqlo_types
       type (rfxqlo_system), intent(out) :: zsys
       integer, intent(out) :: ierr     ! 0: ok; 1: system data never set.
     end subroutine rfxqlo_system_get

     !---------------------------------------------------------
     !  plasma profile information (except ions)
     !  q, g, Te, ne ... and xplasma state filename if available.

     !  get *default* profile info
     subroutine rfxqlo_profile_dflts(zprof)
       use rfxqlo_types
       type (rfxqlo_profile), intent(out) :: zprof
     end subroutine rfxqlo_profile_dflts

     !  set rfxqlo profile info
     subroutine rfxqlo_profile_set(zprof,ierr)
       use rfxqlo_types
       type (rfxqlo_profile), intent(in) :: zprof
       integer, intent(out) :: ierr     ! 0: OK; 1: error
     end subroutine rfxqlo_profile_set

     !  get rfxqlo profile info
     subroutine rfxqlo_profile_get(zprof,ierr)
       use rfxqlo_types
       type (rfxqlo_profile), intent(out) :: zprof
       integer, intent(out) :: ierr     ! 0: ok; 1: profile data never set.
     end subroutine rfxqlo_profile_get

     !---------------------------------------------------------
     !  ion species information -- Z, A, temperatures & densities

     !  get *default* info on ions
     subroutine rfxqlo_ion_dflts(zions)
       use rfxqlo_types
       type (rfxqlo_ion), intent(out) :: zions
     end subroutine rfxqlo_ion_dflts

     !  set rfxqlo info on ions
     subroutine rfxqlo_ion_set(zions,ierr)
       use rfxqlo_types
       type (rfxqlo_ion), intent(in) :: zions
       integer, intent(out) :: ierr     ! 0: OK; 1: error
     end subroutine rfxqlo_ion_set

     !  get rfxqlo info on ions
     subroutine rfxqlo_ion_get(zions,ierr)
       use rfxqlo_types
       type (rfxqlo_ion), intent(out) :: zions
       integer, intent(out) :: ierr     ! 0: ok; 1: ion data never set.
     end subroutine rfxqlo_ion_get

     !---------------------------------------------------------
     !  RF wave code grid information

     !  get *default* rfgrid info
     subroutine rfxqlo_rfgrid_dflts(zgrid)
       use rfxqlo_types
       type (rfxqlo_rfgrid), intent(out) :: zgrid
     end subroutine rfxqlo_rfgrid_dflts

     !  set rfxqlo rfgrid info
     subroutine rfxqlo_rfgrid_set(zgrid,ierr)
       use rfxqlo_types
       type (rfxqlo_rfgrid), intent(in) :: zgrid
       integer, intent(out) :: ierr     ! 0: OK; 1: error
     end subroutine rfxqlo_rfgrid_set

     !  get rfxqlo rfgrid info
     subroutine rfxqlo_rfgrid_get(zgrid,ierr)
       use rfxqlo_types
       type (rfxqlo_rfgrid), intent(out) :: zgrid
       integer, intent(out) :: ierr     ! 0: ok; 1: rfgrid data never set.
     end subroutine rfxqlo_rfgrid_get

     !---------------------------------------------------------
     !  information on RF wave code options & controls

     !  get *default* options info
     subroutine rfxqlo_options_dflts(zopt)
       use rfxqlo_types
       type (rfxqlo_options), intent(out) :: zopt
     end subroutine rfxqlo_options_dflts

     !  set rfxqlo options info
     subroutine rfxqlo_options_set(zopt,ierr)
       use rfxqlo_types
       type (rfxqlo_options), intent(in) :: zopt
       integer, intent(out) :: ierr     ! 0: OK; 1: error
     end subroutine rfxqlo_options_set

     !  get rfxqlo options info
     subroutine rfxqlo_options_get(zopt,ierr)
       use rfxqlo_types
       type (rfxqlo_options), intent(out) :: zopt
       integer, intent(out) :: ierr     ! 0: ok; 1: options data never set.
     end subroutine rfxqlo_options_get

     !---------------------------------------------------------
     !  RF wave code profile *** outputs ***
     !  for one antenna/frequency/kpll point

     subroutine rfxqlo_outpro_init(zpro,ierr)
       use rfxqlo_types
       type (rfxqlo_outpro), intent(out) :: zpro
       integer, intent(out) :: ierr
     end subroutine rfxqlo_outpro_init

     subroutine rfxqlo_outpro_store(zpro,ierr)
       use rfxqlo_types
       type (rfxqlo_outpro), intent(in) :: zpro
       integer, intent(out) :: ierr
     end subroutine rfxqlo_outpro_store

     subroutine rfxqlo_outpro_fetch(zpro,ierr)
       use rfxqlo_types
       type (rfxqlo_outpro), intent(out) :: zpro
       integer, intent(out) :: ierr
     end subroutine rfxqlo_outpro_fetch

     !---------------------------------------------------------
     !  get basic information for one wave field calculation:
     !  frequency, power, Nphi mode number.
     !  --> preceding calls to rfxqlo_select_antenna and
     !      rfxqlo_select_nphi are *required*
     !  --> rfxqlo_verify should also have been called ***.
     !
     !  normally, the prerequisite calls would be made by the "driver"
     !  code, but this call is made by the wave code solver itself.

     subroutine rfxqlo_rfbasic(freq,power,nphi,ksym,ierr)
       use rfxqlo_types
       real(r8qlo), intent(out) :: freq    ! RF frequency (Hz).
       real(r8qlo), intent(out) :: power   ! power (watts) -- this Nphi
       integer, intent(out) :: nphi        ! Nphi mode no.
       integer, intent(out) :: ksym        ! =2 if called for +/-symmetric nphi
                                           ! =1 otherwise
       integer, intent(out) :: ierr        ! =0: OK
     end subroutine rfxqlo_rfbasic

     !---------------------------------------------------------
     !  after all input data for RF wave calculations has been
     !  specified, call this routine to perform error checks and
     !  Nphi spectrum weighting renormalization, and set up the
     !  QLO-related grids

     subroutine rfxqlo_verify_input(ierr)
       integer, intent(out) :: ierr
     end subroutine rfxqlo_verify_input

     !---------------------------------------------------------
     !  verify that rfxqlo is ready -- meaning, all necessary input
     !  has been provided, and, rfxqlo_verify_input has been called.

     subroutine rfxqlo_verify_ready(ierr)
       integer, intent(out) :: ierr
     end subroutine rfxqlo_verify_ready

     !---------------------------------------------------------
     !  fetch wavefield array dimension(s) and x grid

     subroutine rfxqlo_wavefield_dims(nx,nticrfp1,ierr)
       integer,intent(out) :: nx        ! radial dimension
       integer,intent(out) :: nticrfp1  ! poloidal dimension (+1: dupl. endpts)
       integer,intent(out) :: ierr      ! status code (0=OK)
     end subroutine rfxqlo_wavefield_dims

     subroutine rfxqlo_wavefield_nx(nx,ierr)
       integer,intent(out) :: nx        ! radial dimension
       integer,intent(out) :: ierr      ! status code (0=OK)
     end subroutine rfxqlo_wavefield_nx

     subroutine rfxqlo_wavefield_x(x,ierr)
       real*8, dimension(:) :: x        ! radial dimension (zone ctrs)
       integer,intent(out) :: ierr      ! status code (0=OK)
     end subroutine rfxqlo_wavefield_x

     subroutine rfxqlo_wavefield_xb(xb,ierr)
       real*8, dimension(:) :: xb       ! radial dimension (bdys)
       integer,intent(out) :: ierr      ! status code (0=OK)
     end subroutine rfxqlo_wavefield_xb

     subroutine rfxqlo_wavefield_xpsi(xpsi,ierr)
       real*8, dimension(:) :: xpsi     ! radial dimension (Psi/Psilim bdys)
       integer,intent(out) :: ierr      ! status code (0=OK)
     end subroutine rfxqlo_wavefield_xpsi

     !---------------------------------------------------------
     !  copy wavefield data...

     subroutine rfxqlo_wavefield_set1(skperp,eplus,crfpol,ierr)
       !  vacuum norm setup of wavefield for current (antenna, nphi)
       real*8, dimension(:,:), intent(in) :: skperp, eplus ! m^-1, volt/m
       complex*16, dimension(:,:), intent(in) :: crfpol    ! e_minus/e_plus
       integer, intent(out) :: ierr    ! status code (0=OK)
     end subroutine rfxqlo_wavefield_set1

     subroutine rfxqlo_wavefield_get1(nstate,skperp,eplus,crfpol,ierr)
       !  retrieve wavefield for current (antenna, nphi)

       integer, intent(out) :: nstate  ! =0: undefined; =1: vacuum norm
       ! =2: global coupling normalization completed.

       real*8, dimension(:,:), intent(out) :: skperp, eplus ! m^-1, volt/m
       complex*16, dimension(:,:), intent(out) :: crfpol    ! e_minus/e_plus
       integer, intent(out) :: ierr    ! status code (0=OK)

     end subroutine rfxqlo_wavefield_get1

     !---------------------------------------------------------
     !  expand vacuum vessel moments into an actual (R,Z) contour
     !  enclosing the plasma.  If the vacuum vessel moments are
     !  invalid, construct an enclosing contour anyway.

     subroutine rfx_vvxpand(r0,nvec,rvec,zvec,nmoms,rmoms,zmoms)
       use rfxqlo_types
       real(r8qlo), intent(out) :: R0          ! R0 of vacuum vessel (m)
       integer, intent(in) :: nvec   ! no. of pts wanted; all (m):
       real(r8qlo), intent(out) :: rvec(nvec)  ! R pts; R(1)=R(nvec) on output
       real(r8qlo), intent(out) :: zvec(nvec)  ! Z pts; Z(1)=Z(nvec) on output
       
       integer, intent(in) :: nmoms  ! no. of moments
       real(r8qlo), intent(in) :: rmoms(0:nmoms) ! R cos moments (m)
       real(r8qlo), intent(in) :: zmoms(0:nmoms) ! Z sin moments (m)
     end subroutine rfx_vvxpand

     !---------------------------------------------------------
     !  QLO -- note, units of output diffusion coefficients still
     !    to be determined! (dmc -- Oct 2004)
     !
     subroutine rfxqlo_sum( &
          nshe,numen,numxsi,enerkev,xsi,xsi_trap,btime, &
          deb,dec,dab,dac,io,ierr)
        use rfxqlo_types
        integer, intent(in) :: nshe       ! radial shell index -- this refers
                                          ! to the xplasma grid "id_xqlo" as
                                          ! passed to rfxqlo_rfgrids_set in its
                                          ! compound type argument

        integer, intent(in) :: numen      ! number of energy points
        integer, intent(in) :: numxsi     ! number of pitch points

        real*8, intent(in) :: enerkev(0:numen-1) ! energy grid, ** KeV **
        real*8, intent(in) :: xsi(1:numxsi) ! pitch grid, vpll/v, dimensionless
        real*8, intent(in) :: xsi_trap    ! trapping pitch angle
                                          !  |xsi(j)| < xsi_trap => trapped

        real*8, intent(in) :: btime(1:numxsi) ! normalized bounce time:
        !    (Integral dl/abs(v_parrallel))/(2 pi q Rmaj/v)
        !    Rmaj (m) in "io" argument...

        !-----------------
        ! OUTPUT -- space allocated by caller
        !           quasilinear diffusion coefficients
        ! **these are sums over all harmonics, antennae, nphi**

        ! df/dt = (1./qjac) ( d/dE ( deb df/dE + dec df/d(xsi) )
        !               + d/d(xsi) ( dab df/d(xsi) + dac df/dE ) )

        real*8, intent(out) :: deb(0:numen-1,1:numxsi)
        real*8, intent(out) :: dec(0:numen-1,1:numxsi)
        real*8, intent(out) :: dab(0:numen-1,1:numxsi)
        real*8, intent(out) :: dac(0:numen-1,1:numxsi)

        type(rfxqlo_qlocon) :: io

        integer, intent(out) :: ierr      ! return status, 0=OK

      end subroutine rfxqlo_sum
      subroutine rfxqlo_rfoper( &
           nshe,numen,numxsi,enerkev,xsi,xsi_trap,btime, &
           deb,dec,dab,dac,io,ierr)
        use rfxqlo_types
        integer, intent(in) :: nshe       ! radial shell index -- this refers
                                        ! to the xplasma grid "id_xqlo" as
                                        ! passed to rfxqlo_rfgrids_set in its
                                        ! compound type argument

        integer, intent(in) :: numen      ! number of energy points
        integer, intent(in) :: numxsi     ! number of pitch points

        real*8, intent(in) :: enerkev(0:numen-1) ! energy grid, ** KeV **
        real*8, intent(in) :: xsi(1:numxsi) ! pitch grid, vpll/v, dimensionless
        real*8, intent(in) :: xsi_trap    ! trapping pitch angle
                                          !  |xsi(j)| < xsi_trap => trapped

        real*8, intent(in) :: btime(1:numxsi) ! normalized bounce time:
        !    (Integral dl/abs(v_parrallel))/(2 pi q Rmaj/v)
        !    Rmaj (m) in "io" argument...

        !-----------------
        ! OUTPUT -- space allocated by caller
        !           quasilinear diffusion coefficients
        ! **these are sums over all harmonics, antennae, nphi**

        ! df/dt = (1./qjac) ( d/dE ( deb df/dE + dec df/d(xsi) )
        !               + d/d(xsi) ( dab df/d(xsi) + dac df/dE ) )

        real*8, intent(inout) :: deb(0:numen-1,1:numxsi)
        real*8, intent(inout) :: dec(0:numen-1,1:numxsi)
        real*8, intent(inout) :: dab(0:numen-1,1:numxsi)
        real*8, intent(inout) :: dac(0:numen-1,1:numxsi)

        type(rfxqlo_qlocon) :: io

        integer, intent(out) :: ierr      ! return status, 0=OK

      end subroutine rfxqlo_rfoper

     !---------------------------------------------------------

  end interface

end module rfxqlo_interface
