Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

https://doi.org/10.5281/zenodo.8075681
29 October 2025, 17:21:42 UTC
  • Code
  • Branches (0)
  • Releases (4)
  • Visits
    • Branches
    • Releases
      • 4
      • 4
      • 3
      • 2
      • 1
    • ea30f42
    • /
    • danielver02-ALPS-220597d
    • /
    • src
    • /
    • ALPS_io.f90
    Raw File Download

    To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
    Select below a type of object currently browsed in order to display its associated SWHID and permalink.

    • content
    • directory
    • snapshot
    • release
    origin badgecontent badge
    swh:1:cnt:c05784bfc3760549576bdff8a388233bd4cd87dd
    origin badgedirectory badge
    swh:1:dir:713ad21bcde4444c62318606c9e4b8ab59cc8bff
    origin badgesnapshot badge
    swh:1:snp:e9971dcac38583a5eceb223e9c3c25638ea32323
    origin badgerelease badge
    swh:1:rel:38e50bdfa887feee20e30d4b944782bd46bda1ba

    This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
    Select below a type of object currently browsed in order to generate citations for them.

    • content
    • directory
    • snapshot
    • release
    (requires biblatex-software package)
    Generating citation ...
    (requires biblatex-software package)
    Generating citation ...
    (requires biblatex-software package)
    Generating citation ...
    (requires biblatex-software package)
    Generating citation ...
    ALPS_io.f90
    !Copyright (c) 2023, Kristopher G. Klein and Daniel Verscharen
    !All rights reserved.
    !
    !This source code is licensed under the BSD-style license found in the
    !LICENSE file in the root directory of this source tree.
    !
    !===============================================================================
    !I                                                                             I
    !I                              A  L  P  S                                     I
    !I                     Arbitrary Linear Plasma Solver                          I
    !I                                                                             I
    !I                              Version 1.0                                    I
    !I                                                                             I
    !I  Kristopher Klein   (kgklein@arizona.edu)                                   I
    !I  Daniel Verscharen  (d.verscharen@ucl.ac.uk)                                I
    !I                                                                             I
    !===============================================================================
    
    module alps_io
      !!Controls input and output functions to and from main program.
      implicit none
    
      integer :: unit
      !!Index for file I/O.
    
      integer, parameter :: stdout_unit=6
      !! Standard unit for I/O.
    
      integer, save :: input_unit_no
      !! Saved input unit for use with multiple read in calls.
    
      integer, save :: error_unit_no=stdout_unit
      !! Error output unit.
    
      private :: get_runname, get_indexed_namelist_unit
      private :: input_unit_exist, input_unit
      private :: map_read, solution_read, spec_read, scan_read, bM_read
      private :: poly_read
      public  :: init_param, read_f0, get_unused_unit, alps_error
      public :: output_time, display_credits, isnancheck
    
    contains
    
    
    
      subroutine init_param
        !!Read in system parameters from *.in file.
        !!Only processor 0 calls this routine:
        use alps_var, only : runname, foldername, kperp, kpar, nroots, D_prec, D_gap
        use alps_var, only : kperp_last, kpar_last, kperp_0, kpar_0
        use alps_var, only : use_map, writeOut, wroots, nspec, numroots, kperp_norm
        use alps_var, only : nperp, npar, arrayName, fit_check, param_fit, fit_type, perp_correction
        use alps_var, only : ns, qs, ms, vA, Bessel_zero, numiter
        use alps_var, only : D_threshold, D_tol, positions_principal
        use alps_var, only : determine_minima, n_resonance_interval, ngamma, npparbar, Tlim
        use alps_var, only : scan_option, n_scan, scan, relativistic, logfit, usebM
        use alps_var, only : maxsteps_fit, n_fits, lambda_initial_fit, lambdafac_fit, epsilon_fit
        use alps_var, only : bMnmaxs, bMBessel_zeros, bMbetas, bMalphas, bMpdrifts
        use alps_var, only : ACmethod, poly_kind, poly_order, polynomials, poly_fit_coeffs
        use alps_var, only : poly_log_max, secant_method
        implicit none
    
        integer :: ik
        !!Solution index for iterating [[(solution_read(subroutine)]].
    
        integer :: is
        !!Species index for iterating [[spec_read(subroutine)]],
        !![[read_f0(subroutine)]], [[bM_read(subroutine)]], and
        !![[fit_read(subroutine)]]
    
        integer :: ifit
        !!Fit index for iterating [[fit_read(subroutine)]].
    
        integer :: ip
        !!Index for iterating [[scan_read(subroutine)]] and
        !!internal looping in [[init_param(subroutine)]].
    
        !Namelist read in from input file:
        nameList /system/ &
             kperp, kpar, nspec, nroots, use_map, writeOut,&
             nperp, npar, ngamma, npparbar, vA, arrayName, Bessel_zero, &
             secant_method, numiter, kperp_norm, D_threshold, &
             D_prec, D_gap, D_tol, positions_principal, Tlim, &
             maxsteps_fit, lambda_initial_fit, lambdafac_fit, epsilon_fit, fit_check, &
             determine_minima, n_resonance_interval, scan_option, n_scan
    
        !Get a unassigned unit number for input/output:
        call get_unused_unit (input_unit_no)
    
        !Read in system parameters.
        !runname called earlier in alps_error_init:
        unit=input_unit_no
        open (unit=unit,file=trim(foldername)//trim(runname)//".in",status='old',action='read')
        read (unit=unit,nml=system)
    
        if (writeOut) &
             write(*,'(2a)') &
             'Reading from Input File: ', trim(runname)
    
        !save initial kperp,kpar values:
        kperp_last=kperp; kpar_last=kpar
        kperp_0=kperp; kpar_0=kpar
    
        !Allocate solution space for nroots dispersion solutions;
        allocate(wroots(1:numroots));wroots=cmplx(0.d0,0.d0,kind(1.d0))
    
        !Read in map scan parameters:
        if (use_map) then
           if (writeOut) &
                write(*,'(a)') 'MAP ROUTINE'
           ik = 1
           !Read in parameters for complex frequency map:
           unit=input_unit_no
           call get_indexed_namelist_unit (unit, "maps", ik)
           call map_read
           close(unit)
        else
        !OR
        !read in guesses for solutions:
           if (writeOut) &
                write(*,'(a)') 'GUESS ROUTINE: '
           do ik = 1, nroots
              unit=input_unit_no
              call get_indexed_namelist_unit (unit, "guess", ik)
              call solution_read(ik)
              write(*,'(a,i3,a,2es14.4e3)')&
                   'Intial Guess ',ik,' : ', wroots(ik)
              close(unit)
           enddo
        endif
    
        !Read in species density, charge, and mass from input file:
        if (writeOut) &
             write(*,'(a)') 'SPECIES PARAMETERS: '
        allocate(ns(1:nspec)); ns = 0.d0
        allocate(qs(1:nspec)); qs = 0.d0
        allocate(ms(1:nspec)); ms = 0.d0
    
        !Fitting Parameters:
        allocate(n_fits(1:nspec)); n_fits = 1
        allocate(relativistic(1:nspec)); relativistic=.FALSE.
        allocate(logfit(1:nspec)); logfit=.TRUE.
    
        !Bi-Maxwellian/Cold-plasma Parameters:
        allocate(usebM(1:nspec)); usebM=.TRUE.
        allocate(bMnmaxs(1:nspec)); bMnmaxs=500
        allocate(bMBessel_zeros(1:nspec)); bMBessel_zeros=1.d-50
        allocate(bMbetas(1:nspec)); bMbetas=1.d0
        allocate(bMalphas(1:nspec)); bMalphas=1.d0
        allocate(bMpdrifts(1:nspec)); bMpdrifts=0.d0
    
        !Basis Function Parameters:
        allocate(ACmethod(1:nspec)); ACmethod = 1
        allocate(poly_kind(1:nspec)); poly_kind = 0
        allocate(poly_order(1:nspec)); poly_order = 0
        allocate(poly_log_max(1:nspec)); poly_log_max = 0
    
        !READ IN SPECIES PARAMETERS:
        do is = 1, nspec
           unit=input_unit_no
           call get_indexed_namelist_unit (unit, "spec", is)
           call spec_read(is)
           write(*,'(a,i3,a)')'Species ',is,' : '
           write(*,'(a,es14.4e3,a,es14.4e3,a,es14.4e3)')&
                ' ns/nREF = ',ns(is),' | qs/qREF = ',qs(is),' | ms/mREF = ',ms(is)
           select case (ACmethod(is))
           case (0)
              write(*,'(a)') ' Using function defined in distribution/distribution_analyt.f90'
           case (1)
              write(*,'(a,i4)')&
                   ' Number of fitted functions = ',n_fits(is)
           case (2)
              write(*,'(a)')&
                   ' Using a Polynomial Basis Representation'
           end select
           write(*,'(a,l1)')&
                ' Relativistic effects = ',relativistic(is)
           close(unit)
        enddo
    
        allocate(param_fit(1:nspec,0:max(nperp,ngamma),5,maxval(n_fits)))
        allocate(fit_type(1:nspec,maxval(n_fits)))
        allocate(perp_correction(1:nspec,maxval(n_fits)))
    
        write(*,'(a)')'-=-=-=-=-=-=-=-=-'
    
        !READ IN SPECIES FIT PARAMETERS
        do is = 1, nspec
           if (usebM(is)) then
              write (*,'(a,i2,a)') 'Species ',is,&
                   ' uses bi-Maxwellian/cold-plasma calculation... skipping fits. Parameters:'
              call get_indexed_namelist_unit (unit, "bM_spec", is)
              call bM_read(is)
    
              write(*,'(a,es14.4e3,a,es14.4e3,a,es14.4e3)')&
                   '  beta = ',bMbetas(is),', alpha = ',bMalphas(is),', drift momentum = ',bMpdrifts(is)
    
              if (bMbetas(is).EQ.0.d0) then
                  write (*,'(a)') '  Cold-plasma calculation.'
              else
                write(*,'(a,i4,a,es14.4e3)')&
                     '  nmax = ',bMnmaxs(is),',        Bessel_zero = ',bMBessel_zeros(is)
              endif
    
              close(unit)
           else
              !Read in initial guesses for LM fits.
              select case(ACmethod(is))
              case (1)
                 do ifit=1,n_fits(is)
                    call get_indexed_double_namelist_unit (unit, "ffit", is, ifit)
                    call fit_read(is,ifit)
                    select case(fit_type(is,ifit))
                    case(1)
                       write(*,'(a,i2,a,i2,a)')&
                            'Species ',is,', function ',ifit,', Maxwellian fit: '
                    case(2)
                       write(*,'(a,i2,a,i2,a)')&
                            'Species ',is,', function ',ifit,', kappa fit: '
                    case(3)
                       write(*,'(a,i2,a,i2,a)')&
                            'Species ',is,', function ',ifit,', Juettner fit (pperp and ppar): '
                    case(4)
                       write(*,'(a,i2,a,i2,a)')&
                            'Species ',is,', function ',ifit,', Juettner fit (gamma-dependent only): '
                    case(5)
                       write(*,'(a,i2,a,i2,a)')&
                            'Species ',is,', function ',ifit,', Juettner fit (gamma and pparbar): '
                    case(6)
                       write(*,'(a,i2,a,i2,a)')&
                            'Species ',is,', function ',ifit,', bi-Moyal fit: '
                    case default
                       write(*,'(a)')&
                            'Function fit undefined'
                       stop
                    end select
                    
                    do ip = 1, 5
                       write(*,'(a,i2,a,es14.4)')&
                            ' Initial fit parameter ',ip,' = ',param_fit(is,0,ip,ifit)
                    enddo
                    write(*,'(a,es14.4)')&
                         ' Perpendicular correction:  ',perp_correction(is,ifit)
                    close(unit)
                 enddo
              case (2)
                 call get_indexed_namelist_unit (unit, "poly_spec", is)
                 call poly_read(is)
                 select case (poly_kind(is))
                 case (1)
                    write(*,'(a,i0,a,i0)')&
                         'Chebyshev Representation of Order ',poly_order(is),' for species ',is
                 case default
                    call alps_error(10)
                 end select
                 close(unit)
              end select
           endif
        enddo
    
        allocate(polynomials(1:nspec,0:npar,0:maxval(poly_order(:)))); polynomials=0.d0
        allocate(poly_fit_coeffs(1:nspec,0:nperp,0:maxval(poly_order(:)))); poly_fit_coeffs=0.d0
    
        !Read in selection for scan paramter:
        if (n_scan.gt.0) then
           write(*,'(a)')'-=-=-=-=-=-=-=-=-'
           allocate(scan(n_scan))
           do ip = 1, n_scan
              unit=input_unit_no
              call get_indexed_namelist_unit (unit, "scan_input", ip)
              call scan_read(ip)
              close(unit)
           enddo
           write(*,'(a)')'-=-=-=-=-=-=-=-=-'
        endif
        close(unit)
      end subroutine init_param
    
    
    
      subroutine map_read
        !!Reads in complex frequency map parameters.
        use alps_var, only : loggridw, loggridg
        use alps_var, only : omi, omf, gami, gamf, ni, nr
        implicit none
    
        nameList /maps/ &
             loggridw, loggridg, omi, omf, gami, gamf, ni, nr
        read (unit=unit,nml=maps)
    
      end subroutine map_read
    
    
    
      subroutine solution_read(ik)
        !!Reads in initial guesses for dispersion solutions.
        use alps_var, only : wroots
        implicit none
    
        integer, intent(in) :: ik
        !!Solution index.
    
        double precision :: g_om
        !!Guess for real solution \(\omega_{\textrm{r}/\Omega_p \).
    
        double precision :: g_gam
        !!Guess for imaginary solution \(\gamma/\Omega_p \).
    
        nameList /guess/ &
             g_om,g_gam
        read (unit=unit,nml=guess)
        wroots(ik)=cmplx(g_om,g_gam,kind(1.d0))
      end subroutine solution_read
    
    
    
      subroutine spec_read(is)
        !!Subroutine for reading in species parameters
        use alps_var, only : ns, qs, ms, n_fits
        use alps_var, only : relativistic, logfit, usebM
        use alps_var, only : ACmethod
        implicit none
    
        integer,intent(in) :: is
        !!Species index.
    
        double precision :: nn
        !! Read in value for relative density for \(f_j\).
    
        double precision :: qq
        !! Read in value for charge for \(f_j\).
    
        double precision :: mm
        !! Read in value for mass for \(f_j\).
    
        double precision :: AC_method
        !! Read in value for Analytic Continuation Method
        
        integer :: ff
        !!Read in value for number of fitted functions.
    
        logical :: relat=.false.
        !! Treat species as non-relativistic or relativistic.
    
        logical :: log_fit=.true.
        !! Use linear or \(\log_{10}\) fitting routine.
    
        logical :: use_bM=.false.
        !! Use actual numerical integration or bi-Maxwellian/cold-plasma proxy via NHDS.
    
        nameList /spec/ &
             nn,qq,mm,AC_method,ff,relat,log_fit,use_bM
        read (unit=unit,nml=spec)
        ns(is) = nn; qs(is) = qq; ms(is) = mm
        n_fits(is)=ff; relativistic(is)=relat
        logfit(is)=log_fit; usebM(is)=use_bM
        ACmethod(is)=AC_method
      end subroutine spec_read
    
      subroutine poly_read(is)
        !!Reads in Polynomial Basis Function Parameters
        use alps_var, only : poly_kind, poly_order, poly_log_max
        implicit none
    
        integer,intent(in) :: is
        !!Species index.
    
        integer :: kind
        !! Selection of Orthogonal Basis Function
        !! 1) Chebyshev polynomials
    
        integer :: order
        !! Maximum order of Polynomial
    
        double precision :: log_max
        !! Maximum Value of Polynomial Evaluation
    
        nameList /poly_spec/ &
             kind, order, log_max
    
        read(unit=unit,nml=poly_spec)
        poly_kind(is)=kind
        poly_order(is)=order
        poly_log_max(is)=log_max
    
      end subroutine poly_read
    
      subroutine bM_read(is)
        !!Reads in bi-Maxwellian/cold-plasma parameters.
        use alps_var, only : bMnmaxs,bMBessel_zeros,bMbetas
        use alps_var, only : bMalphas,bMpdrifts
        implicit none
    
        integer,intent(in) :: is
        !!Species index.
    
        integer :: bM_nmaxs
        !!Maximum number of resonances to consider.
    
        double precision :: bM_Bessel_zeros
        !!Precision threshold for \(I_n\).
    
        double precision :: bM_betas
        !!\(\beta_{\parallel,j}\) of biMaxwellian distribution \(f_j\).
        !! If bM_betas=0.d0, this species is treated with the cold-plasma susceptibilities.
    
        double precision :: bM_alphas
        !!\(T_{\perp,j}/T_{\parallel,j} \) of biMaxwellian distribution \(f_j\).
    
        double precision :: bM_pdrifts
        !!Relative drift of biMaxwellian distribution \(f_j\),
        !!in units of \(m_p v_{A,p}\). Also used as the drift of the cold-plasma species
        !! if bM_betas is set to 0.d0.
    
        nameList /bM_spec/ &
             bM_nmaxs,bM_Bessel_zeros,bM_betas,bM_alphas,bM_pdrifts
    
        read (unit=unit,nml=bM_spec)
        bMnmaxs(is)=bM_nmaxs; bMBessel_zeros(is)=bM_Bessel_zeros
        bMbetas(is)=bM_betas;
        bMalphas(is)=bM_alphas; bMpdrifts(is)=bM_pdrifts
      end subroutine bM_read
    
    
    
      subroutine scan_read(is)
        !!The most important subroutine.
        !!Reads in wavevector scan parameters.
        !!Defines [[scanner(type)]], which controls the
        !!behavior of the wavevector scan.
      use alps_var, only : scan,kperp_last,kpar_last
      implicit none
    
      integer, intent(in) :: is
      !!Scan index.
    
      integer :: scan_type
      !!Determine kind of wavevector scan.
    
      integer :: ns
      !!Number of output scan values.
    
      integer :: nres
      !!Resolution between output scan values.
    
      double precision :: swi
      !!Initial Scan Value.
    
      double precision :: swf
      !!Final Scan Value.
    
      logical :: swlog
      !!\(\log_{10}\) or linear scan spacing.
    
      logical :: heating
      !!Activate heating calculation.
    
      logical :: eigen
      !!Activate eigenfunction calculation.
    
      double precision :: theta_0
      !!\(\atan(k_\perp/k_\parallel)\)
    
      double precision :: k_0
      !!\(\sqrt{k_\perp^2+k_\parallel^2}\)
    
      nameList /scan_input/ &
           scan_type,swi,swf,swlog,ns,nres,&
           heating,eigen
      read (unit=unit,nml=scan_input)
    
      scan(is)%range_i =swi
      scan(is)%range_f =swf
      scan(is)%log_scan=swlog
      scan(is)%type_s  =scan_type
      scan(is)%n_out   =ns
      scan(is)%n_res   =nres
      scan(is)%eigen_s =eigen
      scan(is)%heat_s  =heating
    
      !Calculate step size:
      select case (scan_type)
      case(0)
         !Scan from k_0 to k_1:
         write(*,'(a,i0,a,es14.4e3,a,es14.4e3,a,es14.4e3,a,es14.4e3,a)')&
              'Scan ',is,': (kpar,kperp) from (',&
              kperp_last,',',kpar_last,') to (',swi,',',swf,')'
         if (swlog) then
            scan(is)%diff =(log10(swi)-log10(kperp_last))/&
                 (1.d0*ns*nres)
            scan(is)%diff2=(log10(swf)-log10(kpar_last))/&
                 (1.d0*ns*nres)
         else
            scan(is)%diff =(swi-kperp_last)/(1.d0*ns*nres)
            scan(is)%diff2=(swf-kpar_last )/(1.d0*ns*nres)
         endif
         kperp_last=swi;kpar_last=swf
      case(1)
         !Scan from theta_0 to theta_1:
         theta_0=atan(kperp_last/kpar_last)
         k_0=sqrt(kperp_last**2+kpar_last**2)
         write(*,'(a,i0,a,es14.4e3,a,es14.4e3)')&
              'Scan ',is,': theta from ',&
              theta_0*180.d0/(4.d0*atan(1.d0)),' to ',swf
         if (swlog) then
            scan(is)%diff=(log10(swf*4.d0*atan(1.d0)/180.)-&
                 log10(theta_0))/(1.d0*ns*nres)
         else
            scan(is)%diff=((swf*4.d0*atan(1.d0)/180.)-theta_0)/&
                 (1.d0*ns*nres)
         endif
         kpar_last=k_0*cos(swf*4.d0*atan(1.d0)/180.d0)
         kperp_last=k_0*sin(swf*4.d0*atan(1.d0)/180.d0)
      case(2)
         !Scan from |k_0| to |k_1| at constant theta.
         theta_0=atan(kperp_last/kpar_last)
         k_0=sqrt(kperp_last**2+kpar_last**2)
         write(*,'(a,i0,a,es14.4e3,a,es14.4e3,a,es14.4e3,a,es14.4e3,a)')&
              'Scan ',is,': |k| from ',&
              k_0,' to ',swf,' at theta=',theta_0*180.d0/&
              (4.d0*atan(1.d0))
         if (swlog) then
            scan(is)%diff =(log10(swf)-log10(k_0))/&
                 (1.d0*ns*nres)
         else
            scan(is)%diff =(swf-k_0)/(1.d0*ns*nres)
         endif
         kpar_last=k_0*cos(theta_0)
         kperp_last=k_0*sin(theta_0)
      case(3)
         !Scan of kperp; kpar constant:
         write(*,'(a,i0,a,es14.4e3,a,es14.4e3)')&
              'Scan ',is,': kperp from ',kperp_last,' to ',swf
         if (swlog) then
            scan(is)%diff=(log10(swf)-log10(kperp_last))/(1.d0*ns*nres)
         else
            scan(is)%diff=(swf-kperp_last)/(1.d0*ns*nres)
         endif
         kperp_last=swf
      case(4)
         !Scan of kpar; kperp constant:
         write(*,'(a,i0,a,es14.4e3,a,es14.4e3)')&
              'Scan ',is,': kpar from ',kpar_last,' to ',swf
         if (swlog) then
            scan(is)%diff=(log10(swf)-log10(kpar_last))/(1.d0*ns*nres)
         else
            scan(is)%diff=(swf-kpar_last)/(1.d0*ns*nres)
         endif
         kpar_last=swf
      end select
    
    end subroutine scan_read
    
    
    
    subroutine fit_read(is,ifit)
      !!Reads in fit parameters for component is.
      use alps_var, only : fit_type, param_fit, perp_correction
      implicit none
    
      integer, intent(in) :: is
      !!Species index.
    
      integer, intent(in) :: ifit
      !Fit index.
    
      double precision :: fit_1
      !! Read in values for fit component 1.
    
      double precision :: fit_2
      !! Read in values for fit component 2.
    
      double precision :: fit_3
      !! Read in values for fit component 3.
    
      double precision :: fit_4
      !! Read in values for fit component 4.
    
      double precision :: fit_5
      !! Read in values for fit component 5.
    
      double precision :: perpcorr
      !!Perpendicular correction to compensate for exponential
      !!dependency of drift to make fit more reliable
      !![\(y\) in Eqn B1 of Verscharen et al 2018].
    
      integer :: fit_type_in
      !!Read in value for type of analytic function.
    
      nameList /ffit/ &
           fit_type_in, fit_1, fit_2, fit_3, fit_4, fit_5, perpcorr
    
      fit_1=0.d0;fit_2=0.d0;fit_3=0.d0;fit_4=0.d0;fit_5=0.d0;perpcorr=0.d0
      read (unit=unit,nml=ffit)
      fit_type(is,ifit)=fit_type_in
      param_fit(is,0,1,ifit)=fit_1
      param_fit(is,0,2,ifit)=fit_2
      param_fit(is,0,3,ifit)=fit_3
      param_fit(is,0,4,ifit)=fit_4
      param_fit(is,0,5,ifit)=fit_5
      perp_correction(is,ifit)=perpcorr
    
    end subroutine fit_read
    
    
    
    subroutine get_runname(runname,foldername)
      !! Get runname for output files from input argument.
      implicit none
    
      integer       :: l
      !!Dummy Length.
    
      integer :: pathend
      !!Directory divider.
    
      character(500) :: arg
      !!Input Argument.
    
      character(500), intent(out) :: runname
      !!Basename for file I/O.
    
      character(500), intent(out) :: foldername
      !!Directory in which input file is stored.
    
      !Get the first argument of the program execution command:
      call getarg(1,arg)
      pathend=0
    
      !Check if this is the input file and trim .in extension to get runname.
      !Also remove any folder structure from the runname:
      l = len_trim (arg)
      pathend = scan(arg, "/", .true.)
      if (l > 3 .and. arg(l-2:l) == ".in") then
         runname = arg(pathend+1:l-3)
         foldername = arg(1:pathend)
      end if
    
      end subroutine get_runname
    
    
    
      subroutine read_f0
        !! Subroutine for reading in background distribution function
        use alps_var, only : nperp, npar, arrayName, f0, pp, nspec
        use alps_var, only : writeOut, usebM
        implicit none
    
        integer :: ipar
        !Parallel index.
    
        integer :: iperp
        !!Perpendicular index.
    
        integer :: is
        !!Species index.
    
        character (100) :: readname
        !!Base I/O name.
    
         if (writeOut) &
              write(*,'(2a)')&
              'Attempting to read f0 array from file: ',trim(arrayName)
    
         call get_unused_unit (input_unit_no)
         unit=input_unit_no
         !The f0 arrays are stored in the distribution folder.
         !arrayName is read in from *.in input file.
         !each species is has a unique file for f0 as a function of pp.
         do is = 1, nspec
    
           if (usebM(is)) then
              write (*,'(a,i2)') ' Bi-Maxwellian/cold-plasma calculation: not reading f0 array for species ',is
              f0(is,:,:)=0.d0
              pp(is,:,:,:)=0.d0
    
           else
    
            write(readname, '(3a,i0,a)') &
                 "distribution/",trim(arrayName),'.',is,".array"
            open (unit=unit, file=trim(readname), status='old', action='read')
    
            do iperp=0,nperp
               do ipar=0,npar
                  read(unit,*) pp(is,iperp,ipar,1),pp(is,iperp,ipar,2),f0(is,iperp,ipar)
               enddo
            enddo
            close(unit)
          endif
         enddo
    
    end subroutine read_f0
    
    
    
    
    
    subroutine get_indexed_namelist_unit (unit, nml, index_in)
      !!Determines unused I/O unit.
      use alps_var, only : runname
      implicit none
    
      integer, intent (out) :: unit
      !!Unit to be defined.
    
      character (*), intent (in) :: nml
      !!Character string for namelist to be read in.
    
      integer, intent (in) :: index_in
      !!Index of namelist to be read in.
    
      character(500) :: line
      !!I/O dummy variable.
    
      integer :: iunit, iostat, in_file
      !!I/O dummy indices.
    
      integer :: ind_slash
      !!I/O dummy index.
    
      logical :: exist
      !!Check if namelist is open.
    
      call get_unused_unit (unit)
      ind_slash=index(runname,"/",.True.)
      if (ind_slash.EQ.0) then !No slash in name
         !Original behaviour
         open (unit=unit, file='.'//trim(runname)//'.scratch')
      else
         !General behaviour
         open (unit=unit, file=trim(runname(1:ind_slash))//"."//trim(runname(ind_slash+1:))//".scratch")
      endif
    
      write (line, *) index_in
      line = nml//"_"//trim(adjustl(line))
      in_file = input_unit_exist(trim(line), exist)
    
      if (exist) then
         iunit = input_unit(trim(line))
      else
         call alps_error(1)
      end if
    
      read (unit=iunit, fmt="(a)") line
      write (unit=unit, fmt="('&',a)") nml
    
      do
         read (unit=iunit, fmt="(a)", iostat=iostat) line
         if (iostat /= 0 .or. trim(adjustl(line)) == "/") exit
         write (unit=unit, fmt="(a)") trim(line)
      end do
      write (unit=unit, fmt="('/')")
      rewind (unit=unit)
    end subroutine get_indexed_namelist_unit
    
    
    
    
    
    
    subroutine get_indexed_double_namelist_unit (unit, nml, spec_in, index_in)
      !!A version of [[get_indexed_namelist_unit(subroutine)]], extended
      !!to allow for double indexing in order to read in multiple fits
      !!for a single species.
      use alps_var, only : runname
    
      implicit none
      integer, intent (out) :: unit
      !!Unit to be defined.
    
      character (*), intent (in) :: nml
      !!Character string for namelist to be read in.
    
      integer, intent (in) :: spec_in
      !!First index of namelist to be read in.
    
      integer, intent (in) :: index_in
      !!Second index of namelist to be read in.
    
      character(500) :: line,lines
      !!I/O dummy variable.
    
      integer :: iunit, iostat, in_file
      !!I/O dummy indices.
    
      integer :: ind_slash
      !!I/O dummy index.
    
      logical :: exist
      !!Check if namelist is open.
    
      call get_unused_unit (unit)
      ind_slash=index(runname,"/",.True.)
      if (ind_slash.EQ.0) then !No slash in name
         !Original behaviour
         open (unit=unit, file='.'//trim(runname)//'.scratch')
      else
         !General behaviour
         open (unit=unit, file=trim(runname(1:ind_slash))//"."//trim(runname(ind_slash+1:))//".scratch")
      endif
    
      write (line, *) index_in
      write (lines, *) spec_in
      line = nml//"_"//trim(adjustl(lines))//"_"//trim(adjustl(line))
      in_file = input_unit_exist(trim(line), exist)
    
      if (exist) then
         iunit = input_unit(trim(line))
      else
         call alps_error(1)
      end if
    
      read (unit=iunit, fmt="(a)") line
      write (unit=unit, fmt="('&',a)") nml
    
      do
         read (unit=iunit, fmt="(a)", iostat=iostat) line
         if (iostat /= 0 .or. trim(adjustl(line)) == "/") exit
         write (unit=unit, fmt="(a)") trim(line)
      end do
      write (unit=unit, fmt="('/')")
      rewind (unit=unit)
    end subroutine get_indexed_double_namelist_unit
    
    
    
    
    
    
    function input_unit_exist (nml,exist)
      !!Determine if a particular namelist already opened.
      implicit none
    
      character(*), intent (in) :: nml
      !!Namelist to be opened.
    
      logical, intent(out) :: exist
      !!Determination if namelist is open.
    
      integer :: input_unit_exist, iostat
      !!I/O dummy indices.
    
      character(500) :: line
      !!I/O dummy variable.
    
        intrinsic adjustl, trim
        input_unit_exist = input_unit_no
        exist = .true.
        if (input_unit_no > 0) then
           rewind (unit=input_unit_no)
           do
              read (unit=input_unit_no, fmt="(a)", iostat=iostat) line
              if (iostat /= 0) then
                 rewind (unit=input_unit_no)
                 exit
              end if
              if (trim(adjustl(line)) == "&"//nml) then
                 backspace (unit=input_unit_no)
                 return
              end if
           end do
        end if
        exist = .false.
      end function input_unit_exist
    
    
    
      function input_unit (nml)
        !!Assigns input unit for namelist opening.
        implicit none
    
        character(*), intent (in) :: nml
        !! Namelist string.
    
        integer :: input_unit, iostat
        !!I/O dummy indices.
    
        character(500) :: line
        !!I/O dummy variable.
    
        intrinsic adjustl, trim
        input_unit = input_unit_no
        if (input_unit_no > 0) then
           rewind (unit=input_unit_no)
           do
              read (unit=input_unit_no, fmt="(a)", iostat=iostat) line
              if (iostat /= 0) then
                 rewind (unit=input_unit_no)
                 exit
              end if
              if (trim(adjustl(line)) == "&"//nml) then
                 backspace (unit=input_unit_no)
                 return
              end if
           end do
        end if
        write (unit=error_unit_no, fmt="('Couldn''t find namelist: ',a)") nml
        write (unit=*, fmt="('Couldn''t find namelist: ',a)") nml
      end function input_unit
    
    
    
    
    
      subroutine get_unused_unit (unit)
        !!Determine unused number for I/O index.
        implicit none
    
        integer, intent (out) :: unit
        !!Unit to be assigned.
    
        logical :: od
        unit = 50
        do
           inquire (unit=unit, opened=od)
           if (.not.od) return
           unit = unit + 1
        end do
      end subroutine get_unused_unit
    
      subroutine alps_error_init
        !!Open a file for the error log.
        use alps_var, only : unit_error, runname, foldername
        implicit none
    
        call get_unused_unit(unit_error)
        !Get the run name, which comes from the name
        !of the input file appended after the executable:
        !mpirun -np 8 ./alps.e sample.in
        !yields a run name of 'sample'
        call get_runname(runname,foldername)
        open (unit=unit_error,file=trim(foldername)//trim(runname)//".log",status='replace')
      end subroutine alps_error_init
    
    
    
      subroutine alps_error(error_id)
        !!Error catching subroutine.
        use alps_var, only : ierror,unit_error,nproc,scan_option
        use mpi
    
        implicit none
        integer :: error_id
        !!Index of error message.
    
    !    if (proc0) then
           select case(error_id)
           case(0) !seen by all processors
              write(*,'(a,i6)')'ERROR: Number of processors must be even and greater than 2: nproc= ',nproc
              write(unit_error,'(a,i6)')'ERROR: Number of processors must be even and greater than 2: nproc= ',nproc
           case(1) !seen by proc0
              write(*,'(2a)') "get_indexed_namelist: required input namelist not found "
              write(unit_error,'(2a)') "get_indexed_namelist: required input namelist not found "
           case(2) !seen by proc0
              write (*,'(a)') "ERROR: More fit parameters than data points."
              write(unit_error,'(a)') "ERROR: More fit parameters than data points."
           case(3) !seen by all processors
              write(*,'(a,i6)')&
                   'ERROR: scan_option not set to allowable value:',scan_option
              write(unit_error,'(a,i6)')&
                   'ERROR: scan_option not set to allowable value:',scan_option
           case(4) !seen by all processors
              write(*,'(a)')&
                   'ERROR: n_scan .ne.2 for scan_option=2'
              write(unit_error,'(a)')&
                   'ERROR: n_scan .ne.2 for scan_option=2'
           case(5) !seen by all processors
              write(*,'(a)')&
                   'ERROR: scan(1)%type_s==scan(2)%type_s for double k scan'
              write(unit_error,'(a)')&
                   'ERROR: scan(1)%type_s==scan(2)%type_s for double k scan'
           case(6) !seen by all processors
              write(*,'(a)')&
                   'ERROR: scan(*)%type_s=0 not allowed for double k scan'
              write(unit_error,'(a)')&
                   'ERROR: scan(*)%type_s=0 not allowed for double k scan'
          case(7) !seen by all processors
              write(*,'(a)')&
                   'ERROR: Fit for analytical continuation failed. Adjustment of perpcorr may resolve this problem.'
              write(unit_error,'(a)')&
                   'ERROR: Fit for analytical continuation failed. Adjustment of perpcorr may resolve this problem.'
          case(8) !seen by all processors
              write(*,'(a)')&
                   'ERROR: Resonance integration covers entire subluminal cone.'
              write(*,'(a)')&
                   '       Adjustment of positions_principal, npar, or a non-relativistic run may resolve this problem.'
              write(unit_error,'(a)')&
                   'ERROR: Resonance integration covers entire subluminal cone.'
              write(unit_error,'(a)')&
                   '       Adjustment of positions_principal, npar, or a non-relativistic run may resolve this problem.'
    	  case(9) !seen by all processors
              write(*,'(a)')&
                   'ERROR: All roots diverged. Adjustment of initial guesses or step width may resolve this problem.'
              write(unit_error,'(a)')&
                   'ERROR: All roots diverged. Adjustment of initial guesses or step width may resolve this problem.'
           case(10) !seen by proc0
              write (*,'(a)') "ERROR: Unspecified Orthogonal Representation."
              write(unit_error,'(a)') "ERROR: Unspecified Orthogonal Representation."
           case default
              write(*,'(a)')'ERROR: Unspecified...'
              write(unit_error,'(a)')'ERROR: Unspecified...'
           end select
           write(*,'(a)') 'Finishing ALPS=================================='
           write(*,'(a)') "Time:"
           call output_time
           write(*,'(a)')'================================================'
    
        close(unit_error)
        call mpi_abort(MPI_COMM_WORLD,error_id, ierror)
      stop
    
      end subroutine alps_error
    
    
    
    
    
      logical function isnancheck(input)
        !!Checks if double precision number input is NaN.
        implicit none
    
        double precision :: input
        !! Variable to be checked.
    
        isnancheck=.FALSE.
        if (abs(input).GE.huge(1.d0)) isnancheck=.TRUE.
        if (input.NE.input) isnancheck=.TRUE.
    
      end function isnancheck
    
    
    
    
      subroutine output_time
        !!Outputs the date and time in a given format using intrinsic
        !!FORTRAN function.
        implicit none
    
        character(8)  :: date
        !!Date.
    
        character(10) :: time
        !!Time.
    
        character(5)  :: zone
        !!Time Zone.
    
        integer,dimension(8) :: value
        !!Output Time Values.
    
        call date_and_time(date,time,zone,value)
        write (*,'(i4,a,i2.2,a,i2.2,a,i2.2,a,i2.2,a,i2.2)') value(1),"-",value(2),"-",value(3)," -- ",value(5),":",value(6),":",value(7)
    
      end subroutine output_time
    
    
    
      subroutine display_credits
        !!Writes the opening credits.
        implicit none
    
        write (*,*) "==========================================================="
        write (*,*) "I                                                         I"
        write (*,*) "I                       A  L  P  S                        I"
        write (*,*) "I              Arbitrary Linear Plasma Solver             I"
        write (*,*) "I                                                         I"
        write (*,*) "I                       Version 1.0                       I"
        write (*,*) "I                                                         I"
        write (*,*) "I  Kristopher Klein   (kgklein@arizona.edu)               I"
        write (*,*) "I  Daniel Verscharen  (d.verscharen@ucl.ac.uk)            I"
        write (*,*) "I                                                         I"
        write (*,*) "==========================================================="
    
    
      end subroutine display_credits
    
    end module alps_io
    

    back to top

    Software Heritage — Copyright (C) 2015–2026, The Software Heritage developers. License: GNU AGPLv3+.
    The source code of Software Heritage itself is available on our development forge.
    The source code files archived by Software Heritage are available under their own copyright and licenses.
    Terms of use: Archive access, API— Content policy— Contact— JavaScript license information— Web API