module rfxqlo_types

  !  *** derived data types for rfxqlo module ***
  !
  !  CAUTION -- when modifying type definitions, please attend to maintenance
  !             of the NetCDF i/o routines:
  !               rfxqlo_input_io.f90
  !               rfxqlo_output_io.f90
  !             which must be kept up-to-date for process-to-process
  !             communication of RF calculations to work...
  !
  !--------------------------------------------
  !  generally, each data type contains, for some category of information,
  !  the collection of all items needed by any wave code.  Some wave codes
  !  will not use every item of information.
  !
  !  **UNITS** -- MKS; Temperatures in KeV
  !--------------------------------------------
  !  to avoid having to use pointers in the interface data types'
  !  array components, some static limits have to be enforced.
  !
  !  these static limits only affect the interface data types and
  !  can be increased simply by editing this module and rebuilding...
  !--------------------------------------------
  
  integer, parameter :: rfxqlo_mxvvmom = 64  ! max Fourier moments in 
                                             ! vacuum vessel description

  integer, parameter :: rfxqlo_maxspc = 24   ! max no. of ion species

  integer, parameter :: rfxqlo_maxfrq = 20   ! max no. of antennae frequencies

  integer, parameter :: rfxqlo_maxrya = 32   ! max no. of pts in antenna
                                             ! geometry arrays

  integer, parameter :: rfxqlo_maxnphi = 50  ! max no. of Nphi lobes / antenna


  !  REAL kind:
  integer, parameter :: r8qlo = SELECTED_REAL_KIND(12,100)  ! 64 bit precision

  !--------------------------------------------
  !  default values shown in parentheses
  !--------------------------------------------

  real*8, parameter :: cmpm = 100.0_r8qlo    ! cm/m
  real*8, parameter :: vpsv = 300.0_r8qlo    ! volts/stat-volt

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

  type rfxqlo_dims
     ! dimensioning information (must be specified **first**)

     integer :: n_antenna         ! number of antennae (no. of frequencies) (1)

     integer :: max_nphi          ! max no. of Nphi values per antenna (1)

  end type rfxqlo_dims

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

  type rfxqlo_vacuum

     ! information on vacuum region

     real(r8qlo) :: vacden        ! electron density in vacuum region (0) m**-3
     real(r8qlo) :: vactemp       ! electron temperature in vacuum region (0)
                                  ! KeV
     ! if defaulted: vacden = ne(bdy)/2, vactemp = Te(bdy)/2

     ! vacuum vessel (vv) shape (needed by some wave codes)
     integer :: nvvmoms                        ! max moment number (0)
     !   (0:nvvmoms) moments are active
     real(r8qlo) :: vvrmoms(0:rfxqlo_mxvvmom)  ! R cos moments for vv (0) m
     real(r8qlo) :: vvzmoms(0:rfxqlo_mxvvmom)  ! Z sin  moments for vv (0) m

     ! if defaulted: wave codes should use plasma boundary location
     ! instead...

     !  these are used by TORIC3, and, TORIC4 until it is upgraded to 
     !  use the g profile...

     real(r8qlo) :: rmaj0    ! plasma "major radius" (for btor0) (m)
     real(r8qlo) :: btor0    ! *vacuum* toroidal field at rmaj0 (T)

     !  used by TORIC3; optional (xplasma estimate used if omitted)

     real(r8qlo) :: placur   ! toroidal plasma current (A)

     !  used by QLO; optional (xplasma estimate used if omitted)

     real(r8qlo) :: tflux    ! enclosed toroidal flux (Wb = T*m**2).

  end type rfxqlo_vacuum

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

  type rfxqlo_antenna

     !----------------
     ! information on a single antenna

     real(r8qlo) :: freq         ! antenna frequency (Hz) (0)

     real(r8qlo) :: power        ! antenna power (Watts) (0)

     ! the above values cannot be defaulted.

     !----------------
     ! ---> antenna Nphi spectrum

     logical :: sym_nphi         ! .TRUE. to assume +/- symmetric Nphi spectrum
                                 ! (T) -- one wavecode solution will represent
                                 ! both the positive and negative contributions
                                 ! this is an approximation that saves time

     integer :: num_nphi         ! number of Nphi values to represent antenna
                                 ! spectrum (1)

     integer :: nphi(rfxqlo_maxnphi)      ! Nphi spectrum (set of Nphi values)
                                          ! (0) -- CANNOT be defaulted!
                                          ! must be all positive if sym_nphi=T

     real(r8qlo) :: wnphi_vac(rfxqlo_maxnphi) ! Nphi vacuum spectrum 
                                 ! vacuum power weighting for Nphi modes (1)
                                 ! actual power associated with each Nphi
                                 ! value takes into account plasma coupling
                                 ! efficiency and is then normalized to 
                                 ! match total power on the antenna.

     !  the issue of wnphi_vac weightings is moot unless more than one Nphi
     !  mode is specified.  In many runs, still, only one Nphi is employed.

     logical :: wnphi_renorm     ! .TRUE. to request renormalization of
                                 ! antenna power spectrum to take account
                                 ! of coupling efficiencies, after all nphi
                                 ! mode field components have been computed
                                 ! (RF wavecode must provide coupling 
                                 ! efficiency or antenna load factor MW/kA^2).
                                 ! NOTE: moot in num_nphi=1.

     !----------------
     !  resonant harmonics for this antenna
     !  if not set, estimates from mod(B) are computed, assuming
     !  a range of A/Z values in the target plasma

     integer :: nharm_min        ! (default: 0 if not set)
     integer :: nharm_max        ! (default: 0 if not set)

     !----------------
     !  field corrections at "main resonance":
     !  external field, minor & major radius, total plasma current--
     !  default values: all 1.0

     real(r8qlo) :: bzcorr   ! Bphi/Bvac at "main resonance"  (1)
     real(r8qlo) :: bpcorr   ! B/Bphi at "main resonance"  (1)

     !  (1/R) approximation for Bphi is (rmaj0*btor0*bzcorr)/R
     !  (1/R) approximation for B is (rmaj0*btor0*bzcorr*bpcorr)/R

     !----------------
     !  antenna geometry:

     !  simple geometry specification:

     real(r8qlo) :: antRcen,antZcen   ! (R,Z) of antenna center point (m) (0)
     real(r8qlo) :: anthh             ! half height of antenna (m) (0.1)

     !   --OR--

     !  general geometry specification:

     integer :: nantrz           ! no. of ordered (R,Z) pairs defining antenna
                                 ! (0)
     real(r8qlo) :: antRgeo(rfxqlo_maxrya)  ! R values (m) (0)
     real(r8qlo) :: antZgeo(rfxqlo_maxrya)  ! Z values (m) (0)

     !  one of the two specifications must be given;
     !    * if only the simple specification is given, a matching
     !    general specification is generated internally;
     !    * if the general specification is given; an approximate matching
     !    simple specification is generated internally;
     !    * if both are given, the general specification takes precedence.

     !  minimal information to supply: antRcen (antZcen=0.0, anthh=0.1 are
     !  accepted as defaults).

     !----------------
     !  **and also: for TORIC**

     real(r8qlo) :: dx_farsh  ! distance, antenna to Faraday Shield (m)
     !  default value: 0.02 m (used by TORIC; var. name depends on version).

     real(r8qlo) :: antlc     ! antenna propagation constant (TORIC)
     !  default value: 1.0  -->  TORIC ANTLC internal variable.

  end type rfxqlo_antenna

  type rfxqlo_profile
     !  plasma profile information (not indexed by ion species)
     !  units: MKS,KeV

     !  id strings:
     character*20 :: xnam_g,xnam_q,xnam_te,xnam_ne ! default " "
     character*20 :: xnam_tiav,xnam_vloop,xnam_epot,xnam_omega
     !    default of xnam_g is "G".

     !  id numbers:
     integer :: id_g,id_q,id_te,id_ne ! default (0)
     integer :: id_tiav,id_vloop,id_epot,id_omega ! default (0)

     !  xplasma state filename:
     character*180 xplasma_file ! default " "

  end type rfxqlo_profile

  type rfxqlo_ion
     !  information on ions: number of species, names, Z, A, profiles...
     !  units: MKS,KeV

     integer n_ions   ! no. of ion species (0)

     real(r8qlo) :: a_ions(rfxqlo_maxspc)   ! A (amu) of ion species (0)
     real(r8qlo) :: z_ions(rfxqlo_maxspc)   ! Z (charge) of ion species (0)
     character*10 :: name_ions(rfxqlo_maxspc)  ! label string for species (" ")

     !  all xplasma names default (" "); all id no.s default (0)

     character*20 :: xnam_ni(rfxqlo_maxspc)  ! xplasma name for species dens.
     integer :: id_ni(rfxqlo_maxspc)         ! xplasma id for species dens.

     character*20 :: xnam_ti(rfxqlo_maxspc)  ! xplasma name for species Ti
     integer :: id_ti(rfxqlo_maxspc)         ! xplasma id for species Ti

     character*20 :: xnam_tpll(rfxqlo_maxspc) ! xplasma name for species Tpll.
     integer :: id_tpll(rfxqlo_maxspc)       ! xplasma id for species Tpll.

  end type rfxqlo_ion

  type rfxqlo_system
     !  system info -- Fortran LUNs for temporary files;
     !  run_id string (may be used as prefix for temp. file names).
     !  batchmode indicator

     integer :: lunut(5)  ! LUNs for working files (0)
     integer :: luntmp1   ! lower end of range of LUNs for temporary files (0)
     integer :: luntmp2   ! upper end of range of LUNs for temporary files (0)
     character*40 run_id  ! runid string (no imbedded blanks) (" ")
     character*80 run_label  ! longer run description string
     character*150 filepath  ! path to directory for temp. files (" ")
     character*150 workpth_log ! path to directory for log files (" ")
     character*40 wavecode   ! name of wavecode to use for wavefield solution
     logical vv_bdy       ! flag T if wave code uses VV instead of plasma bdy
     logical batchmode    ! flag to reduce message output e.g.
                          ! in "batch mode" (.FALSE.)
     real(r8qlo) :: time  ! simulation time in run (fpp or transport code).

     !  note: use rfxqlo_set_lunmsg to set LUN for rfxqlo module
     !  warning & error messages.

  end type rfxqlo_system

  type rfxqlo_rfgrid
     !  info on RF wave solver grids
     !  all default to zero -- actual values must be supplied.
     !  if nmod is given, nchi_in = max(6*nmod,nchi_in) is enforced.

     integer :: npsi_in   ! no. of radial grid pts.   (128)
     integer :: nchi_in   ! no. of poloidal grid pts. (90)
     integer :: nmod      ! no. of poloidal Fourier modes (15)

     !  ***warning*** these default resolution settings are not always
     !  sufficient!

     !  TORIC runs require nmod to be specified.

     !  QLO grid info

     integer :: id_xqlo         ! xplasma id -- QLO x axis (default = 0)
     character*20 :: xnam_xqlo  ! xplasma name -- QLO x axis (radial grid)
     integer :: id_xpsi         ! xplasma profile id xpsi(x) = sqrt(Psi/Psilim)
     character*20 :: xnam_xpsi  ! xplasma name -- xpsi profile
     integer :: nxmulti         ! radial grid multiplier (default = 1)
     integer :: nvmulti         ! velocity grid multiplier (default = 1)
     logical :: symflag         ! .TRUE. if equilibrium is updown symmetric (F)

     integer :: ncpu            ! #cpus/call (for TORIC)
     integer :: ncptype         ! cpu type code (for TORIC)

  end type rfxqlo_rfgrid

  type rfxqlo_options
     !  option flags for (various) RF wave solvers

     !  *** SPRUCE *** options

     integer mod_dielec(0:rfxqlo_maxspc)  ! DE tensor options for SPRUCE (1)
     !  =1 gives normal Spruce hot plasma DE tensor; =0 & =-1 give various
     !  reduced options per "model" variable in Spruce source code.
     !  ** this should not be touched except by Spruce experts **.

     logical lisotrp   ! assume plasma temperature isotropy to be enforced
     !  default value is .TRUE.

     !  *** SPRUCE & DSPRUCE optino ***
     logical lposabs   ! (default .TRUE.): .TRUE to enforce positive power
     !  absorption.

     !  *** TORIC options ***
     !  interface to version 3 & version 4 of TORIC are available.

     integer :: iflr   ! =1: include ion flr contributions (default: 1)
     !  TORIC IFLR variable. NOTE: =0 required for "high harmonic" mode.

     integer :: ibweld ! =1: include electron damping of IBW waves (default: 1)
     !  TORIC IBWELD variable. NOTE: =0 required for "high harmonic" mode.

     integer :: ibpol  ! =1: include poloidal field effects (default: 1)
     !  TORIC IBPOL variable.

     integer :: iqtor  ! =1: include effect of toroidal broadening of
     !  plasma dispersion function (TORIC IQTOR variable, default = 1).

     integer :: icoll  ! =1: include certain collisional effects--
     !  TORIC ICOLL variable, default = recommended value = 0.

     real(r8qlo) :: enhcol  ! electron collision enhancement factor
     !  default value = 1.0; large value said to be needed for an
     !  effect; TORIC ENHCOL variable.

     !  *** TORIC3 only *** use DEFAULT values unless you have
     !  special expertise... these controls are likely obscolescent.

     real(r8qlo) :: flr_fac  ! TORIC3 only: gradual turn off for ion FLR
     !  correction (btw 0.0 and 1.0; default = 1.0 for full effect).

     integer :: iflre  ! TORIC3 only: 1 for electron FLR contributions
     !  (default is 1; not an option for TORIC4 & later versions).

     real(r8qlo) :: alfvn(20) ! controls for ad hoc collisional broadening
     !  of Alfven and ion-ion resonances (TORIC3 only) -- see
     !  fppmod/fppmod_ic.f90 and TORIC3 source for details...

     !  *** TORIC4 only ***

     logical :: numeric_mhd  ! (default .TRUE.) -- .TRUE. to use
     !  numerical equilibrium and fields.  If .FALSE., use simplified
     !  updown symmetric elongation/triangularity representation as
     !  is required in TORIC3.

     real(r8qlo) :: epsn     ! screen out ion species [i] for which
     !  max(Zi*ni/ne) < epsn; scale up remaining specie densities to 
     !  conserve quasineutrality w.r.t. ne.  An upper limit of 1e-3
     !  is imposed on the value of this parameter (New DMC Feb. 2011).

  end type rfxqlo_options

  type rfxqlo_outpro
     !  for one antenna/frequency/kpll: xplasma ids of all output profiles.
     !  power profiles are integrated powers, Watts., vs. rho.

     integer :: id_pwrs(rfxqlo_maxspc+2)    ! xplasma ids
     character*20 xn_pwrs(rfxqlo_maxspc+2)  ! xplasma names

     !  1:n_ions -- power profiles, all ions species
     !  n_ions+1 -- power to electrons
     !  n_ions+2 -- power to Mode Conversion

     !  some wave codes compute power deposited beyond the separatrix (bdy)
     !  this power is likely treated as lost by the FP/transport model.

     real(r8qlo) :: ext_pwrs(rfxqlo_maxspc+2)  ! power deposited beyond bdy (W)

     !  current drive (integrated current, Amps, vs. rho).
     integer :: id_jrfe    ! current drive (electrons)
     character*20 xn_jrfe  ! xplasma name

  end type rfxqlo_outpro

  !------------------------------------------
  !  wave field block -- one for each nphi for each antenna or frequency
  !  pointers allocated by rfxqlo, values filled in by ICRF wave code...

  type rfxqlo_wave

     ! wave field solution results for a single n_phi toroidal mode number
     ! on a particular antenna

     integer :: nstate    ! wave field data state:

     !  =0 -- initialization only: mode_power=0; mode_coupling=1 (no solution).
     !  =1 -- vacuum normalization: 
     !        mode_power = [antenna_power]*[wnphi_vac(<mode#>)]
     !                     based only on vacuum n_phi spectrum of antenna
     !        (RF wave code should provide mode_coupling data as well:
     !         this can be a resistance, e.g. MW/kA^2 -- units do not 
     !         matter as long as consistent units are used for all 
     !         n_phi modes).
     !  =2 -- coupled normalization:
     !        mode_coupling = antenna load or resistance or coupling
     !        efficiency;
     !        mode_power = 
     !          (1/norm)*[antenna_power]*[wnphi_vac(<mode#>)]*[mode_coupling]
     !        Global renormalization across all n_phi spectrum values
     !        has been done to account for coupling efficiencies.
     !          NOTE#1: if mode_coupling is never set from RF wave code data,
     !          it would be 1 for all n_phi, and the vacuum normalization
     !          would be retained.  NOTE#2 if the number of n_phi modes is
     !          one, the global renormalization step is unnecessary.

     real*8 :: mode_power     ! current power normalization
     real*8 :: mode_coupling  ! load or coupling efficiency factor
 
     real*8, dimension(:,:), pointer :: skperp      ! k_perp, m**-1
     real*8, dimension(:,:), pointer :: eplus       ! |E_plus|, volts/m
     complex*16, dimension(:,:), pointer :: crfpol  ! E_minus/E_plus

  end type rfxqlo_wave

  !------------------------------------------
  !  control block for QLO -- passed directly to rfxqlo_rfoper subroutine
  !
  type rfxqlo_qlocon
     ! an instance of this type is passed to rfxqlo_rfoper, for each radial
     ! shell in a bounced averaged Fokker Planck model...

     !-----------------
     ! INPUT -- values supplied by caller
     !   Note the energy grid here is in eV

     ! these are passed as subroutine arguments directly to rfxqlo_rfoper ...
     ! integer :: numen   ! number of energy zones
     ! integer :: numxsi  ! number of pitch (vpll/v) zones

     ! real*8, dimension(:), pointer :: enerev     ! array (1:numen) of E (eV)
     ! or (0:numen-1)

     ! real*8, dimension(:), pointer :: xsi        ! array (1:numxsi) of pitch

     ! real*8, dimension(:), pointer :: btimes     ! array (1:numxsi) of bounce
     !  times:  (Integral dl/abs(v_parrallel))/(2 pi q Rmaj/v)
     !  normalized, dimensionless

     !  integer :: nshe    ! FP QLO code radial shell index
     !  this refers to the FP QLO code grid cell -- see rfxqlo_rfgrids
     !  (id_xqlo,xnam_xqlo); nshe in range 1 to <# of zones in id_xqlo grid>

     real*8 :: Rmaj     ! major radius used in btimes definition (m)

     real*8 :: Ai       ! A of resonant specie (AMU, =1 for Hydrogen)
     real*8 :: Zi       ! Z of resonant specie (Z=1 for Hydrogen)

     integer :: nharm   ! harmonic resonance to consider (1, 2, ...)

  end type rfxqlo_qlocon

end module rfxqlo_types
