geometry_inputprofiles_interface.f90 Source File


Source Code

module geometry_inputprofiles_interface

   implicit none

   public :: read_inputprof_geo, read_inputprof_spec

   private

   integer :: n_exp

   real, dimension(:), allocatable :: rhotor, rmin, rmaj_in, qinp, kappa
   real, dimension(:), allocatable :: delta, Te, ne, z_eff, omega0
   real, dimension(:), allocatable :: ni, Ti
   real, dimension(:), allocatable :: dr
   real, dimension(:), allocatable :: rhoc, rmaj, shift
   real, dimension(:), allocatable :: shat, d2qdr2
   real, dimension(:), allocatable :: tri, triprim
   real, dimension(:), allocatable :: kapprim
   real, dimension(:), allocatable :: neprim, Teprim
   real, dimension(:), allocatable :: niprim, Tiprim
   real, dimension(:), allocatable :: nedbprim, Tedbprim
   real, dimension(:), allocatable :: nidbprim, Tidbprim
   real, dimension(:), allocatable :: betaprim, betadbprim
   real, dimension(:), allocatable :: psitor
   real, dimension(:), allocatable :: drhotordrho, dpsitordrho, d2psitordrho2
   real, dimension(:), allocatable :: pres_tot
   real, dimension(:), allocatable :: loglam

   real :: bref, omega_ref, rho_ref
   real :: bunit

contains

   subroutine read_inputprof_geo(surf)

      use constants, only: pi
      use common_types, only: flux_surface_type
      use finite_differences, only: fd3pt, d2_3pt
      use splines, only: geo_spline
      use geometry_miller, only: local

      implicit none

      type(flux_surface_type), intent(in out) :: surf

      integer :: in_unit = 101
      character(10) :: dum
      character(500) :: line

      real :: bt_exp
      real :: arho_exp

      real :: aref
      real :: mu0

      integer :: ir

      open (unit=in_unit, file='input.profiles', status='old', action='read')

      ! read in header and ignore
      read (in_unit, *) line
      read (in_unit, *) line
      read (in_unit, *) line
      read (in_unit, *) line
      read (in_unit, *) line

      read (in_unit, *) dum, n_exp
      read (in_unit, *) dum, bt_exp
      read (in_unit, *) dum, arho_exp

      call allocate_arrays_geo

      ! read in more headers
      read (in_unit, *) line
      read (in_unit, *) line

      do ir = 1, n_exp
         read (in_unit, *) rhotor(ir), rmin(ir), rmaj_in(ir), qinp(ir), kappa(ir)
      end do

      ! aref is stella reference length (device minor radius)
      aref = rmin(n_exp)

      rhoc = rmin / aref
      rmaj = rmaj_in / aref

      ! read in more headers
      read (in_unit, *) line
      read (in_unit, *) line

      do ir = 1, n_exp
         read (in_unit, *) delta(ir), Te(ir), ne(ir), line
      end do

      ! stella redefines delat to be ArcSin(delta_miller)
      tri = asin(delta)

      ! read in more headers
      read (in_unit, *) line
      read (in_unit, *) line

      ! read in some stuff we don't need to use at the moment
      do ir = 1, n_exp
         read (in_unit, *) line
      end do

      ! read in more headers
      read (in_unit, *) line
      read (in_unit, *) line

      ! read in some stuff we don't need to use at the moment
      do ir = 1, n_exp
         read (in_unit, *) line
      end do

      ! read in more headers
      read (in_unit, *) line
      read (in_unit, *) line

      do ir = 1, n_exp
         read (in_unit, *) ni(ir), line
      end do

      ! read in more headers
      read (in_unit, *) line
      read (in_unit, *) line

      do ir = 1, n_exp
         read (in_unit, *) Ti(ir), line
      end do

      close (in_unit)

      dr = rhoc(2:) - rhoc(:n_exp - 1)

      ! obtain s_hat
      call fd3pt(qinp, shat, dr)
      shat = rhoc * shat / qinp

      ! obtain d2q/dr2
      call d2_3pt(qinp, d2qdr2, dr)

      ! obtain d (kappa) / drho
      call fd3pt(kappa, kapprim, dr)

      ! obtain d (ArcSin(delta_miller)) / drho
      call fd3pt(tri, triprim, dr)

      ! obtain dR/drho
      call fd3pt(rmaj, shift, dr)

      pres_tot = ne * Te + ni * Ti
      call fd3pt(pres_tot, betaprim, dr)
      call d2_3pt(pres_tot, betadbprim, dr)

      mu0 = 4.*pi * 1.e-7
      betaprim = -mu0 * betaprim * 1.6022e3 / bt_exp**2
      betadbprim = -mu0 * betadbprim * 1.6022e3 / bt_exp**2

      ! this is psi_toroidal/(Bref aref**2)/2pi
      ! assumption here is that Bref = BT_EXP
      psitor = 0.5 * rhotor * rhotor * (arho_exp / aref)**2

      ! get drhotordr
      call fd3pt(rhotor, drhotordrho, dr)
      call fd3pt(psitor, dpsitordrho, dr)
      call d2_3pt(psitor, d2psitordrho2, dr)

      ! this sets the reference B-field to be bt_exp
!    dpsitordrho = rhotor*drhotordrho*(arho_exp/aref)**2

      ! next need to pick out the correct flux surface
      ! and assign various local% values
      call geo_spline(rhoc, rmaj, local%rhoc, local%rmaj)
      call geo_spline(rhoc, dpsitordrho, local%rhoc, local%dpsitordrho)
      call geo_spline(rhoc, d2psitordrho2, local%rhoc, local%d2psitordrho2)
      call geo_spline(rhoc, shift, local%rhoc, local%shift)
      call geo_spline(rhoc, kappa, local%rhoc, local%kappa)
      call geo_spline(rhoc, kapprim, local%rhoc, local%kapprim)
      call geo_spline(rhoc, qinp, local%rhoc, local%qinp)
      call geo_spline(rhoc, shat, local%rhoc, local%shat)
      call geo_spline(rhoc, d2qdr2, local%rhoc, local%d2qdr2)
      call geo_spline(rhoc, tri, local%rhoc, local%tri)
      call geo_spline(rhoc, triprim, local%rhoc, local%triprim)
      call geo_spline(rhoc, betaprim, local%rhoc, local%betaprim)
      call geo_spline(rhoc, betadbprim, local%rhoc, local%betadbprim)
      call geo_spline(rhoc, rhotor, local%rhoc, local%rhotor)
      call geo_spline(rhoc, drhotordrho, local%rhoc, local%drhotordrho)
      local%psitor_lcfs = psitor(n_exp)
      local%zed0_fac = 1.0

      surf = local

      call deallocate_arrays_geo

   end subroutine read_inputprof_geo

   subroutine read_inputprof_spec(nspec, spec)

      use mp, only: mp_abort
      use finite_differences, only: fd3pt, d2_3pt
      use splines, only: geo_spline
      use common_types, only: spec_type
      use geometry_miller, only: local
      use parameters_physics, only: vnew_ref, rhostar

      implicit none

      integer, intent(in) :: nspec
      type(spec_type), dimension(:), intent(in out) :: spec

      integer, parameter :: electron_species = 2

      integer :: in_unit = 102
      character(10) :: dum
      character(500) :: line

      real :: bt_exp
      real :: arho_exp

      real :: aref
      real :: mref, nref, tref
      real :: vtref, local_loglam

      integer :: ir, is

      open (unit=in_unit, file='input.profiles', status='old', action='read')

      ! read in header and ignore
      read (in_unit, *) line
      read (in_unit, *) line
      read (in_unit, *) line
      read (in_unit, *) line
      read (in_unit, *) line

      read (in_unit, *) dum, n_exp
      read (in_unit, *) dum, bt_exp
      read (in_unit, *) dum, arho_exp

      call allocate_arrays_spec

      ! read in more headers
      read (in_unit, *) line
      read (in_unit, *) line

      do ir = 1, n_exp
         read (in_unit, *) rhotor(ir), rmin(ir), line
      end do

      ! aref is stella reference length (device minor radius)
      aref = rmin(n_exp)

      rhoc = rmin / aref

      ! read in more headers
      read (in_unit, *) line
      read (in_unit, *) line

      do ir = 1, n_exp
         read (in_unit, *) dum, Te(ir), ne(ir), z_eff(ir), omega0(ir)
      end do

      ! read in more headers
      read (in_unit, *) line
      read (in_unit, *) line

      ! read in some stuff we don't need to use at the moment
      do ir = 1, n_exp
         read (in_unit, *) line
      end do

      ! read in more headers
      read (in_unit, *) line
      read (in_unit, *) line

      ! read in some stuff we don't need to use at the moment
      do ir = 1, n_exp
         read (in_unit, *) line
      end do

      ! read in more headers
      read (in_unit, *) line
      read (in_unit, *) line

      do ir = 1, n_exp
         read (in_unit, *) ni(ir), line
      end do

      ! read in more headers
      read (in_unit, *) line
      read (in_unit, *) line

      do ir = 1, n_exp
         read (in_unit, *) Ti(ir), line
      end do

      close (in_unit)

      dr = rhoc(2:) - rhoc(:n_exp - 1)

      ! obtain -d ln(ne) / drho
      call fd3pt(ne, neprim, dr)
      call d2_3pt(ne, nedbprim, dr)
      neprim = -neprim / ne
      nedbprim = nedbprim / ne

      ! obtain -d ln(Te) / drho
      call fd3pt(Te, Teprim, dr)
      call d2_3pt(Te, Tedbprim, dr)
      Teprim = -Teprim / Te
      Tedbprim = Tedbprim / Te

      ! obtain -d ln(ni) / drho
      call fd3pt(ni, niprim, dr)
      call d2_3pt(ni, nidbprim, dr)
      niprim = -niprim / ni
      nidbprim = nidbprim / ni

      ! obtain -d ln(Ti) / drho
      call fd3pt(Ti, Tiprim, dr)
      call d2_3pt(Ti, Tidbprim, dr)
      Tiprim = -Tiprim / Ti
      Tidbprim = Tidbprim / Ti

      ! next need to pick out the correct flux surface
      ! and assign various local% values

      ! choose first species as reference species
      is = 1
      spec(is)%dens = 1.0
      spec(is)%temp = 1.0
      ! get reference density and temperature
      if (spec(is)%type == electron_species) then
         call geo_spline(rhoc, Te, local%rhoc, tref)
         call geo_spline(rhoc, ne, local%rhoc, nref)
         ! only needed for collisions -- reference mass in units of proton mass
         ! and is only included for clarity -- factors of mref cancel in the end
         mref = 5.44625e-4
      else
         call geo_spline(rhoc, Ti, local%rhoc, tref)
         call geo_spline(rhoc, ni, local%rhoc, nref)
         ! only needed for collisions -- reference mass in units of proton mass
         ! and is only included for clarity -- factors of mref cancel in the end
         mref = 2.0
      end if
      ! next get the normalized density and temperature for all other species
      if (nspec == 2) then
         do is = 2, nspec
            if (spec(is)%type == electron_species) then
               call geo_spline(rhoc, Te / tref, local%rhoc, spec(is)%temp)
               call geo_spline(rhoc, ne / nref, local%rhoc, spec(is)%dens)
            else
               call geo_spline(rhoc, Ti / tref, local%rhoc, spec(is)%temp)
               call geo_spline(rhoc, ni / tref, local%rhoc, spec(is)%dens)
            end if
         end do
      else if (nspec > 2) then
         call mp_abort('multiple ion species not currently supported for input.profiles. aborting.')
      end if

      ! now get the density and temperature gradients at the requested flux surface
      do is = 1, nspec
         if (spec(is)%type == electron_species) then
            call geo_spline(rhoc, Teprim, local%rhoc, spec(is)%tprim)
            call geo_spline(rhoc, Tedbprim, local%rhoc, spec(is)%d2Tdr2)
            call geo_spline(rhoc, neprim, local%rhoc, spec(is)%fprim)
            call geo_spline(rhoc, nedbprim, local%rhoc, spec(is)%d2ndr2)
         else
            call geo_spline(rhoc, Tiprim, local%rhoc, spec(is)%tprim)
            call geo_spline(rhoc, Tidbprim, local%rhoc, spec(is)%d2Tdr2)
            call geo_spline(rhoc, niprim, local%rhoc, spec(is)%fprim)
            call geo_spline(rhoc, nidbprim, local%rhoc, spec(is)%d2ndr2)
         end if
      end do

      ! get collisionalities for stella
      loglam = 24.0 - log(1e4 * sqrt(0.1 * ne) / te)
      call geo_spline(rhoc, loglam, local%rhoc, local_loglam)

      ! vtref = sqrt(2*Tref/mref), with Tref and mref in SI units
      ! so vtref has dimensions of meters / second
      ! note that tref below is T in units of keV and mref is in units of proton mass
      vtref = 3.09497e5 * sqrt(2.*tref / mref)

      ! reference collision frequency for stella
      ! uses the mass, density and temperature of the reference species,
      ! along with the proton charge in the expression
      ! vnew_ref = (aref/vtref)*(4/3)sqrt(2pi)/(4pi*epsilon_0)**2 * nref * e**4 * loglam / sqrt(mref) / Tref**1.5
      ! note that all quantities are given in SI units and epsilon_0 is permittivity of vacuum
      vnew_ref = 28.5134 * (aref / vtref) * local_loglam * nref / (sqrt(mref) * tref**1.5)

      bref = bt_exp
      omega_ref = 9.5791e7 * bref / mref

      rho_ref = vtref / omega_ref

      rhostar = rho_ref / aref
      ! I think this is incorrect -- MAB
      bunit = (bref * arho_exp**2) / (local%rhotor / aref / local%rhoc) * local%drhotordrho

!    vnewki = 9.21e-5*aref*zi**4/sqrt(2.)*loglam*ni/ti**2
!    vnewke = 3.95e-3*aref*zi**2*sqrt(0.5*mi)*loglam*ne &
!         /(sqrt(ti)*te**1.5)

      call deallocate_arrays_spec

   end subroutine read_inputprof_spec

   subroutine allocate_arrays_geo

      implicit none

      allocate (rhotor(n_exp))
      allocate (psitor(n_exp))
      allocate (rmin(n_exp))
      allocate (rmaj_in(n_exp))
      allocate (qinp(n_exp))
      allocate (kappa(n_exp))
      allocate (rhoc(n_exp))
      allocate (rmaj(n_exp))
      allocate (delta(n_exp))
      allocate (tri(n_exp))
      allocate (ne(n_exp))
      allocate (Te(n_exp))
      allocate (ni(n_exp))
      allocate (Ti(n_exp))
      allocate (dr(n_exp - 1))
      allocate (shat(n_exp))
      allocate (d2qdr2(n_exp))
      allocate (kapprim(n_exp))
      allocate (triprim(n_exp))
      allocate (shift(n_exp))
      allocate (betaprim(n_exp))
      allocate (betadbprim(n_exp))
      allocate (pres_tot(n_exp))
      allocate (drhotordrho(n_exp))
      allocate (dpsitordrho(n_exp))
      allocate (d2psitordrho2(n_exp))

   end subroutine allocate_arrays_geo

   subroutine allocate_arrays_spec

      implicit none

      allocate (rhotor(n_exp))
      allocate (rmin(n_exp))
      allocate (rhoc(n_exp))
      allocate (Te(n_exp))
      allocate (ne(n_exp))
      allocate (z_eff(n_exp))
      allocate (omega0(n_exp))
      allocate (ni(n_exp))
      allocate (Ti(n_exp))
      allocate (dr(n_exp - 1))
      allocate (neprim(n_exp))
      allocate (nedbprim(n_exp))
      allocate (Teprim(n_exp))
      allocate (Tedbprim(n_exp))
      allocate (niprim(n_exp))
      allocate (nidbprim(n_exp))
      allocate (Tiprim(n_exp))
      allocate (Tidbprim(n_exp))
      allocate (loglam(n_exp))
!    allocate (vnewki(n_exp))
!    allocate (vnewke(n_exp))

   end subroutine allocate_arrays_spec

   subroutine deallocate_arrays_geo

      implicit none

      deallocate (rhotor)
      deallocate (rmin)
      deallocate (rmaj_in)
      deallocate (rmaj)
      deallocate (qinp)
      deallocate (kappa)
      deallocate (rhoc)
      deallocate (delta)
      deallocate (Te)
      deallocate (ne)
      deallocate (tri)
      deallocate (ni)
      deallocate (Ti)
      deallocate (dr)
      deallocate (shat)
      deallocate (d2qdr2)
      deallocate (kapprim)
      deallocate (triprim)
      deallocate (shift)
      deallocate (betaprim)
      deallocate (betadbprim)
      deallocate (pres_tot)
      deallocate (drhotordrho)
      deallocate (dpsitordrho)
      deallocate (d2psitordrho2)

   end subroutine deallocate_arrays_geo

   subroutine deallocate_arrays_spec

      implicit none

      deallocate (rhotor)
      deallocate (rmin)
      deallocate (rhoc)
      deallocate (Te)
      deallocate (ne)
      deallocate (z_eff)
      deallocate (omega0)
      deallocate (ni)
      deallocate (Ti)
      deallocate (dr)
      deallocate (neprim)
      deallocate (nedbprim)
      deallocate (Teprim)
      deallocate (Tedbprim)
      deallocate (niprim)
      deallocate (nidbprim)
      deallocate (Tiprim)
      deallocate (Tidbprim)
      deallocate (loglam)
!    deallocate (vnewki)
!    deallocate (vnewke)

   end subroutine deallocate_arrays_spec

end module geometry_inputprofiles_interface