Wolfram mathematica 数学中的复误差函数

Wolfram mathematica 数学中的复误差函数,wolfram-mathematica,Wolfram Mathematica,w(z)被定义为e^(-x^2)erfc(-ix)。如上所述,使用w(z)的问题是,erfc倾向于在更大的x上爆炸(由指数变为0补充,因此所有东西都保持较小),因此Mathematica恢复到任意精度的计算,这使得生命非常缓慢。该函数用于实现voigt轮廓-光谱和其他相关领域中常用的线型。现在我恢复到只计算一次线型,并使用插值来加快速度,但是这不允许我轻松地更改线型的参数(或适合它们) scipy有一个很好的快速实现w(z)为scipy.special.wofz,我想知道在Mathematica

w(z)被定义为
e^(-x^2)erfc(-ix)
。如上所述,使用w(z)的问题是,erfc倾向于在更大的x上爆炸(由指数变为0补充,因此所有东西都保持较小),因此Mathematica恢复到任意精度的计算,这使得生命非常缓慢。该函数用于实现voigt轮廓-光谱和其他相关领域中常用的线型。现在我恢复到只计算一次线型,并使用插值来加快速度,但是这不允许我轻松地更改线型的参数(或适合它们)


scipy有一个很好的快速实现w(z)为
scipy.special.wofz
,我想知道在Mathematica中是否有一个等价物。

复杂的误差函数可以用Hermite“多项式”
H_{-1}(x)

而且,评估不会遭受太多的下溢和溢出

In[68]:= 2 HermiteH[-1, I x] /. x -> 100000.
Out[68]= 6.12323*10^-22 - 0.00001 I

In[69]:= Sqrt[Pi] E^-x^2 Erfc[I x] /. x -> 100000.
During evaluation of In[69]:= General::unfl: Underflow occurred in computation. >>
During evaluation of In[69]:= General::ovfl: Overflow occurred in computation. >>
Out[69]= Indeterminate

也就是说,一些快速测试表明,埃尔米特函数的计算速度比指数函数和误差函数乘积的计算速度慢…

无穷远处的级数展开表明实部和虚部具有非常不同的尺度。我建议单独计算它们,不要添加它们。下面我使用级数展开的前几个项来得到虚部

In[186]:= 
w[x_?NumericQ] := {N[Exp[-SetPrecision[x, 25]^2], 20], 
  N[(3 /(4 Sqrt[\[Pi]] x^5) + 1/(2 Sqrt[\[Pi]] x^3) + 1/(
     Sqrt[\[Pi]] x))]}

In[187]:= w[11]

Out[187]= {2.8207700884601354011*10^-53, 0.05150453151309212}

In[188]:= w[1000]

Out[188]= {3.296831478088558579*10^-434295, 0.0005641898656429712}
我不知道你有多想要那个很小的真实角色。如果你能放弃它,这将使数字保持在一个合理的范围内。在某些范围内(或者如果需要高于机器精度),您可能需要使用该虚部展开式中的更多项

In[186]:= 
w[x_?NumericQ] := {N[Exp[-SetPrecision[x, 25]^2], 20], 
  N[(3 /(4 Sqrt[\[Pi]] x^5) + 1/(2 Sqrt[\[Pi]] x^3) + 1/(
     Sqrt[\[Pi]] x))]}

In[187]:= w[11]

Out[187]= {2.8207700884601354011*10^-53, 0.05150453151309212}

In[188]:= w[1000]

Out[188]= {3.296831478088558579*10^-434295, 0.0005641898656429712}
丹尼尔·利奇布劳
Wolfram Research

在Mathematica中,可以使用以下方法明确有效地计算实线上复误差函数的实部和虚部:

这比使用
HermiteH[-1,z]
快4倍左右

In[10]:= w1[x_] := E^-x^2 Sqrt[\[Pi]] - 2 I DawsonF[x]
w2[x_] := 2 HermiteH[-1, I x]

In[15]:= AbsoluteTiming[w1 /@ Range[-5.0, 5.0, 0.001];]

Out[15]= {2.3272327, Null}

In[16]:= AbsoluteTiming[w2 /@ Range[-5.0, 5.0, 0.001];]

Out[16]= {10.2400239, Null}

只需包装C库。

中还提供了可从Mathematica运行的复杂错误函数(又称Faddeeva函数)的C语言程序。更多信息,请阅读文章。

错误函数爆炸,x大(和实)的指数衰减,这难道不是另一种方式吗?我尝试使用
SetSystemOptions[“CatchMachineUnderflow”->False]
,但结果是
0+0I
用于大参数。然后我尝试将函数定义为
Exp[Log[-z^2+Log@Erfc[-I*z]]
,但这并不比自动切换快多少。因此,似乎很难加快速度,除了@Daniel Lichtblausuggests@Heike你是对的,我有点失误。因为实际部分实际上是零,足够远(voigt轮廓被定义为w(z)的真实部分),所以我只要把整个东西设置为0就足够了(比如在mathematica切换到任意精度之前-但我对该机制不是很熟悉)因为最后我做了一个数值拟合,10^-53远低于浮点的机器sigma。我运行了一些旧代码(从2007年开始)前几天,手册
erf
简化/替换规则因为那些
DawsonF
函数而被打破。它们在版本7中是新的。你知道它们出现在哪里以及为什么它们被添加到Mma中吗?@Simon如果“它们出现的地方”指的是应用程序,我在进行路径积分蒙特卡罗时遇到过它们(或者通常使用假想的时间动作)。我想主要的吸引力在于,这些函数存在近似值,序列确实非常迅速地收敛(同样,我只从数字公式中知道这一点,我自己也从未在愤怒中使用过这些函数)@Simon在等离子体研究中很活跃,我希望积分能出现在等离子体物理中,尽管我自己还没有看到它的用途。这不是Mathematica的答案,除非你展示如何从Mathematica调用该库(比OP提到的scipy库更简单).从Mathematica调用C是标准的,.是的,是我发布了libcerf,抱歉并感谢您通知我有关披露规则的信息。@JoachimWuttke您是否碰巧有一个如何使用Mathematica的libcerf的示例?查看wolfram文档,似乎我必须开始修改源代码,所以如果您ady有一个有效的实现,我更愿意使用它。@Jordan,没有,到目前为止我还没有示例。但是如果有人给我指出一个,那么我很乐意将它添加到libcerf发行版中。
In[10]:= w1[x_] := E^-x^2 Sqrt[\[Pi]] - 2 I DawsonF[x]
w2[x_] := 2 HermiteH[-1, I x]

In[15]:= AbsoluteTiming[w1 /@ Range[-5.0, 5.0, 0.001];]

Out[15]= {2.3272327, Null}

In[16]:= AbsoluteTiming[w2 /@ Range[-5.0, 5.0, 0.001];]

Out[16]= {10.2400239, Null}