用python求复杂函数的导数
我想推导一个相当复杂的扩散关系。 以下是色散关系的代码:用python求复杂函数的导数,python,math,numpy,Python,Math,Numpy,我想推导一个相当复杂的扩散关系。 以下是色散关系的代码: import numpy as np import pylab as pl #function definitions. compare following paper eqs. (60) and (61) #"Hamiltionian formalism for two magnon scattering microwave relaxation: #Theory and applications" #Krivosik, Kalari
import numpy as np
import pylab as pl
#function definitions. compare following paper eqs. (60) and (61)
#"Hamiltionian formalism for two magnon scattering microwave relaxation:
#Theory and applications"
#Krivosik, Kalarickal, Patton
#JAP 101, 083901 (2007)
def omega(gamma,Bx,By): #resonance frequency
return gamma*sqrt(Bx*By)
def Bx(B,A,k,mu_0,Ms,Nk): #magnetic field in x-direction
return B+(2*A/Ms)*k**2+mu_0*Ms*Nk
def By(B,A,k,mu_0,Ms,phi,Nk): #magnetic field in y-direction
return B+(2*A/Ms)*k**2+mu_0*Ms*(sin(phi)**2)*(1-Nk)
def k(kx,n,w): #k-vektor of spin wave
return sqrt(kx**2+(n*pi/w)**2)
def Nk(k,d): #Dipole field function
return (1-exp(-k*d))/(k*d)
def phi(kx,n,w): #angle between k vector and magnetization which points along x-axis
return arctan(n*pi/(w*kx))
#constants and parameters
gamma=28 #GHz/T
mu_0=4*pi*1e-7 #As/Vm
#range of k-vectors
kx=linspace(0,25000000,1000)
#sample parameters
A=3.5e-12 #J/m
Ms=140000 #A/m
B=0.05 #mT
w=2e-6 #m
d=100e-9 #m
fig=pl.figure(num=None, figsize=(10, 6.25), dpi=80, facecolor='w', edgecolor='k')
font = {'weight' : 'normal', 'size' : 13}
matplotlib.rc('font', **font)
n=1
plot(kx/1e6, omega(gamma,Bx(B,A,k(kx,n,w),mu_0,Ms,Nk(k(kx,n,w),d)),By(B,A,k(kx,n,w),mu_0,Ms,phi(kx,n,w),Nk(k(kx,n,w),d))), 'k-')
现在我想推导这个函数,因为函数的斜率对我来说至关重要
您可以使用函数梯度,它是在numpy中实现的 使用内部的中心差和边界处的第一个差计算渐变。因此,返回的梯度与输入数组具有相同的形状 这就是如何使用它来绘制导数,只需复制您的示例
plot(kx/1e6, gradient(omega(gamma,Bx(B,A,k(kx,n,w),mu_0,Ms,Nk(k(kx,n,w),d)),By(B,A,k(kx,n,w),mu_0,Ms,phi(kx,n,w),Nk(k(kx,n,w),d)))), 'k-')
希望有帮助。您可以依赖scipy实用程序函数,该函数允许同时使用离散化dx
的大小和有限差分格式的顺序(默认设置为3
)。这是一个例子:
from scipy.misc import derivative
f=lambda kx : omega(gamma,Bx(B,A,k(kx,n,w),mu_0,Ms,Nk(k(kx,n,w),d)),By(B,A,k(kx,n,w),mu_0,Ms,phi(kx,n,w),Nk(k(kx,n,w),d)))
df = derivative(f,kx,dx=kx[1]-kx[0])
fig,ax=plt.subplots()
ax.plot(kx/1e6,f(kx),'b')
bx=ax.twinx()
bx.plot(kx/1e6,df,'r')
bx.grid()
我找到了解决问题的办法
#Definitions from above
dispersion =lambda n : omega(gamma,Bx(B,A,k(kx,n,w),mu_0,Ms,Nk(k(kx,n,w),d)),By(B,A,k(kx,n,w),mu_0,Ms,phi(kx,n,w),Nk(k(kx,n,w),d)))
derivative=diff(dispersion(n))/diff(kx)
有多种方法:
- ,(刚刚更新到版本0.5)这使用有限差分方法,但跟踪数值误差估计,从而给出可靠的结果,即自动考虑网格大小
- ,(刚刚更新到0.5版)
- ,非常优雅的代码,感谢Theano和decorators
- 有一个python包装器
- ,经典的python符号派生模块
- ,一个类似iPython的环境,用于替代Mathematica,它构建在python上
2和3都比数值导数更精确,因为为了保持精度,需要在非常精细的网格上对方程进行采样。如果使用numpy 1.9(当前的开发版本)梯度函数在边界上也使用二阶精度差分,因此在整个导数上保持精度:)这是一个很好的改进!;)这个函数似乎没有提供正确的值。可能是因为梯度函数不知道我的kx值。gradient()强烈地依赖于点的数量。这是正确的,但您也可以将差异作为参数包含到gradient函数中。梯度(func[1:],diff(func))。在这种情况下,结果与您在下面的帖子中实现的结果类似,但边缘的值可能是错误的。如果您使用具有多个维度的数组,这将非常方便。这似乎不起作用。函数对kx=0的导数为0,noch为3.1?来自的渐变工具提供了正确的结果。您可能不需要导数的符号表达式,但数值微分容易出错,因此我的建议是构造一个符号表达式(例如,通过Sympy)并对其进行计算。numdifftools是数值近似,而不是自动微分。