From: Bo =?iso-8859-1?Q?Thid=E9?= <bt@lufsen.plasma.uu.se>
Organization: Dept of Space and Plasma Physics, Uppsala University
Subject: Re: Plasma dispersion function, C or Fortran
References: <87k0jl$6f0$1@jupiter.cs.uml.edu> <87pvai$63g$1@jupiter.cs.uml.edu>
Newsgroups: sci.physics.plasma


Paul Probert wrote:
>
> Hey Mirko,
>   I've got one that I wrote in IDL, which is mostly a rewrite of a
> fortran error function W(z) that I found on the web. Let me know and
> I'll e-mail it to you.
>
> Mirko Vukovic wrote:
> >
> > Can anyone send me a C or Fortran routine for computing
> > the plasma dispersion function, for real and complex
> > arguments. Or point me to a reference that explains
> > how to do it.
> >
> > I developed one based on the expansion given in Swanson's book
> > on plasma waves,
> > but I'm not sure whether it is valid for complex arguments.
> >
> > Thanks,
> >
> > Mirko
> >
> > Sent via Deja.com http://www.deja.com/
> > Before you buy.
>
> --
> _______________________________
> Paul Probert
> Associate Scientist
> The University of Wisconsin-Madison
> 608 263 3752
> fax 608 262 1267
> pprobert@facstaff.wisc.edu

Below, please find my Fortran77 code for the PDF.  It's written
for HP-UX f77 but should be fairly portable.

Bo

--

  ^   Bo Thidé (Professor)               http://www.wavegroup.irfu.se/~bt
 |I|  Wave Group, Institute of Space Physics,  SE-755 91 Uppsala,  Sweden
 |R|  Office: Villavägen 3.  Phone: +46 018-4717269.  Fax: +46 018-554917
/|F|\ Mobile Phone: 0705-613670  Home Phone: 018-554184  Ham Call: SM5DFW
~~U~~ E-Mail: mailto:bt@plasma.uu.se  Mobile mail: mailto:call-bt@irfu.se

==========================================================================



      COMPLEX*16 FUNCTION Pdf(x,y)
*-----------------------------------------------------------------------
*
*  Computes the plasma dispersion function in the whole z-plane
*  by using the Voigt function
*
*    w(z) = exp(-z**2)erfc(-iz)
*
*  related to the plasma dispersion function  Pdf(z) = Z(z),
*  usually defined as
*
*    Z(z) = 1/SQRT(Pi) * Integral(-Inf,+Inf) exp(-t**2)/(t-z) dt ,
* 
*  in the following way:
*
*    Z(z) = i*SQRT(Pi) * w(z)
*  
*  The algorithm used is based on algorithm 363 for calculating  w(z)
*  in the whole complex plane with an accuracy of at least 10 digits
*  after the decimal point given by:
*
*  W. Gautschi, "Complex Error Function",
*  Comm. ACM 12, 635 (1969)
*
*  See also:
*
*  W. Gautschi, "Efficient computation of the complex error function",
*  SIAM J. Math. Anal. 7, 187 (1970)
*
* (c) Copyright 1992 - bt@irfu.se (Bo Thide' Swedish Inst of Space Phys)
*-----------------------------------------------------------------------


      IMPLICIT REAL*8(A-Y)
      IMPLICIT COMPLEX*16(Z)
      INTEGER Capn,Nu,N,Np1
      LOGICAL B
      COMPLEX*16 Ci,CiTwoSqrtPi

      PARAMETER  ( SqrtPi = 1.7724 53850 90551 60272 98167D0)
      PARAMETER  ( CiTwoSqrtPi = (0.D0,3.544907701811032054596334) )
      PARAMETER  ( Ci = (0.D0,1.D0) )

      DATA Lambda /0.D0/

C     IF ((x.EQ.0.D0).AND.(y.EQ.0.D0)) THEN          !Trivial case
C       Pdf = DCMPLX(0.D0,SqrtPi)
C       RETURN
C     END IF
      z = DCMPLX(x,y)


      IF (y.GE.0.) THEN                              !Upper half z-plane
        IF (x.LT.0.D0) THEN                          !Second quadrant
C         WRITE(7,*) 'Second quadrant'
          Pdf=-DCONJG(Pdf(-x,y))                     !NB. Recursive call
C         WRITE(7,*) 'Recursion upper half plane'
          RETURN                                     !Ready
        END IF                                       !Now in 1st quadrant
      ELSE                                           !Lower half z-plane
        IF (x.LT.0.D0) THEN                          !Third quadrant
C         WRITE(7,*) 'Third quadrant'
          Pdf=CiTwoSqrtPi*ZEXP(-z*z) - Pdf(-x,y)     !NB. Recursive call
        ELSE                                         !Fourth quadrant
C         WRITE(7,*) 'Fourth quadrant'
          Pdf=CiTwoSqrtPi*ZEXP(-z*z) +
     &        DCONJG(Pdf(x,-y))                      !NB. Recursive call
        END IF                                       !Now in 3rd quadrant
C         WRITE(7,*) 'Recursion lower half plane'
        RETURN                                       !Ready
      END IF

C...Compute plasma dispersion function Z(z) in first quadrant in the z-plane

C     WRITE(7,*) 'First quadrant'

      IF ((y.LT.4.29D0).AND.(x.LT.5.33D0)) THEN   !Taylor series
C       WRITE(*,*) 'Taylor series',x,y
        s = (1.D0-y/4.29D0)*DSQRT(1.D0-x*x/28.41D0)
        h = 1.6D0*s
        h2 = h+h
        OneOverh2 = 1.D0/h2
        Capn = 6 + IDINT(23*s)
        Nu = 9 + IDINT(21*s)
      ELSE                                        !Gauss-Hermite quadrature
C       WRITE(*,*) 'Gauss-Hermite quadrature',x,y
        h = 0.D0
        Capn = 0
        Nu = 8
      END IF

      IF (h.GT.0.D0) Lambda = H2**Capn
      B = (h.EQ.0.D0).OR.(Lambda.EQ.0.D0)
      R1 = 0.D0
      R2 = 0.D0
      S1 = 0.D0
      S2 = 0.D0


      DO n = Nu, 0, -1
        Np1 = n + 1
        T1 = y + h + Np1*R1
        T2 = x - Np1*R2
        c = .5D0/(T1*T1 + T2*T2)
        R1 = c*T1
        R2 = c*T2
        IF ((n.LE.Capn).AND.(h.GT.0.D0)) THEN
          T1 = Lambda + S1
          S1 = R1*T1 - R2*S2
          S2 = R2*T1 + R1*S2
          Lambda = Lambda*OneOverh2
        END IF
C       WRITE(7,*) 't1,t2,s1,s2,lambda',t1,t2,s1,s2,lambda
      END DO

      IF (B) THEN
        Z_real = -2*R2
      ELSE
        Z_real = -2*S2
      END IF

      IF (y.EQ.0.D0) THEN
        Z_imag = SqrtPi*DEXP(-x*x)
      ELSE
        IF (B) THEN
          Z_imag = 2*R1
        ELSE
          Z_imag = 2*S1
        END IF
      END IF

      Pdf = DCMPLX(Z_real,Z_imag)
      RETURN
      END