Repository: PlasmaPy/PlasmaPy

Issue:
Use Dawson function for dispersion
`plasma_dispersion_func` under `mathematics.py` currently uses `erf()` along with some other terms. This can be simplified to Dawson function, [dawsn](https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.dawsn.html), and may even offer some minor speedups if scipy implements it in C code.


Discussion:
I hadn't remembered seeing the [Dawson function](https://en.wikipedia.org/wiki/Dawson_function) used in expressions for the plasma dispersion function before.  I was looking through _Waves in Plasmas_ by T. H. Stix (1992) and saw a formulation for it on page 202.  The Dawson function is:

S(ζ) = exp(-ζ²) ∫<sub>0</sub><sup>∞</sup> exp(z²) dz = -S(-ζ)

where the integral goes from 0 to ∞.  Then the panda dispersion function is:

Z(ζ) = i √π exp(ζ²) - 2 S(ζ)
Looking at this a little further, an expression that looks even simpler is:

Z(ζ) = i √π w(ζ)

where w(ζ) is the complex error function, also known as the [Faddeeva function](https://en.wikipedia.org/wiki/Faddeeva_function).  I think that's [`wofz`](https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.wofz.html) in SciPy.

The name `wofz` is not helpful at all, so if we do it this way then maybe we should do something like
```Python
from scipy.math.special import wofz as Faddeeva_function
```
so that the code is more readable.
I like your Faddeeva idea, and looking at wikipedia wofz is implemented in C, so there may be some speedups.
Hello. I would like to work on this. Looks like a good first contribution.

Resolving patch:
diff --git a/plasmapy/mathematics/mathematics.py b/plasmapy/mathematics/mathematics.py
--- a/plasmapy/mathematics/mathematics.py
+++ b/plasmapy/mathematics/mathematics.py
@@ -3,6 +3,7 @@
 import numpy as np
 from scipy import special
 from astropy import units as u
+from scipy.special import wofz as Faddeeva_function
 
 
 def plasma_dispersion_func(zeta):
@@ -57,9 +58,9 @@ def plasma_dispersion_func(zeta):
     >>> plasma_dispersion_func(0)
     1.7724538509055159j
     >>> plasma_dispersion_func(1j)
-    0.7578721561413119j
+    0.757872156141312j
     >>> plasma_dispersion_func(-1.52+0.47j)
-    (0.6088888957234255+0.3349458388287403j)
+    (0.6088888957234254+0.33494583882874024j)
 
     """
 
@@ -79,7 +80,7 @@ def plasma_dispersion_func(zeta):
         raise ValueError("The argument to plasma_dispersion_function is "
                          "not finite.")
 
-    Z = 1j * np.sqrt(np.pi) * np.exp(-zeta**2) * (1.0 + special.erf(1j * zeta))
+    Z = 1j * np.sqrt(np.pi) * Faddeeva_function(zeta)
 
     return Z
 
@@ -124,9 +125,9 @@ def plasma_dispersion_func_deriv(zeta):
     >>> plasma_dispersion_func_deriv(0)
     (-2+0j)
     >>> plasma_dispersion_func_deriv(1j)
-    (-0.48425568771737626+0j)
+    (-0.48425568771737604+0j)
     >>> plasma_dispersion_func_deriv(-1.52+0.47j)
-    (0.1658713314982294+0.4458797880593507j)
+    (0.16587133149822897+0.44587978805935047j)
 
     """
 


Test patch:
diff --git a/plasmapy/mathematics/tests/test_dispersion.py b/plasmapy/mathematics/tests/test_dispersion.py
--- a/plasmapy/mathematics/tests/test_dispersion.py
+++ b/plasmapy/mathematics/tests/test_dispersion.py
@@ -15,7 +15,7 @@
     (0, 1j * np.sqrt(π)),
     (1, -1.076_159_013_825_536_8 + 0.652_049_332_173_292_2j),
     (1j, 0.757_872_156_141_311_87j),
-    (1.2 + 4.4j, -0.054_246_146_372_377_471 + 0.207_960_589_336_958_13j),
+    (1.2 + 4.4j, -0.054_246_157_069_223_27+0.207_960_584_359_855_62j),
     (9.2j, plasma_dispersion_func(9.2j * units.dimensionless_unscaled)),
     (5.4 - 3.1j, -0.139_224_873_051_713_11 - 0.082_067_822_640_155_802j),
     (9.9 - 10j, 2.013_835_257_947_027_6 - 25.901_274_737_989_727j),