2013-12-16 103 views
1

我有以下功能(维维安尼的曲线):计算矢量的导数

Phi  = @(t)[ cos(t)^2, cos(t)*sin(t), sin(t) ] 

只是检查,它是有效的:

s = linspace(0,T,1000); 
plot3(cos(s).^2, cos(s).*sin(s), sin(s)); 

如何衍生功能Phi(也许多次),其代表Viviani的曲线点t其中t0变为2*pi?我是否定义了Phi适合这样的衍生物?我试过diff,但它并没有保留我所需要的Phi

如果二阶导数是Phi_d2,我需要得到它的值(例如在t = 0)。

我该如何做到这一点?

+0

你想获得它的数值或分析(需要符号数学工具箱)?为什么不用手? – thewaywewalk

+0

要在没有任何附加工具箱的情况下进行数值计算,可以使用简单的有限差分(http://en.wikipedia.org/wiki/Finite_difference),例如'(Phi(1.1)-Phi(.9))/。2'来计算t = 1.0时的一阶导数 – tim

回答

4

这里有三种方法可以实现这一点。第一种使用subs,第二使用symfun,第三个使用complex step differentiation

% Using subs 
syms t 
Phi = [cos(t) cos(t).*sin(t) sin(t)]; 
Phi_d2 = diff(Phi,t) 
double(subs(Phi_d2,t,0)) 

% Using symfun 
syms t 
Phi(t) = [cos(t) cos(t).*sin(t) sin(t)]; 
Phi_d2 = diff(Phi,t) 
double(Phi_d2(0)) 

% Using complex step differentiation 
Phi = @(t)[cos(t) cos(t).*sin(t) sin(t)]; 
h = 2^-28; 
cdiff = @(f,x)imag(f(x(:)+1i*h))/h; 
Phi_d2 = cdiff(Phi,0) 

你可以找到执行第一级和第二级复杂的一步分化on my GitHub: cdiff功能。请注意,复阶分解对于高阶导数不适用。当只有一个非微分函数或需要快速数值一阶导数时最好。

+1

+1我不知道你可以做'Phi(t)= ...'来制作一个symfun。谢谢。 – ja72

+0

@ ja72:这是一个稍微更新的功能,所以旧版本不支持它 - 我认为它是与Matlab R2012a一起推出的。 – horchler

+0

必须与开沟枫木和mupad一致。我认为这是一个疏忽,你无法定义任意函数,但是现在你可以用'syms f(x)',这样你就可以象'diff(1/f(x),x)'这样象征性地评估'-diff F(X)中,x)/ F(X)^ 2'。 – ja72

3

为了完整起见,数值解,而无需使用任何额外的工具箱:

N = 999; 
t = linspace(0,2*pi,N+1); 
Phi = [cos(t); cos(t).*sin(t); sin(t)]; 
dPhi = gradient(Phi,2*pi/N) 

对于非均匀间隔的参数矢量,的gradient第二个参数是由间隔矢量,而不是标量限定。 (时间或角度矢量是合适的) - 在这种情况下显然需要分割尺寸。 (虽然我不知道为什么。)

所以另外,虽然没有必要:

dX = gradient(Phi(1,:),t); 
dY = gradient(Phi(2,:),t); 
dZ = gradient(Phi(3,:),t); 
dPhi = [dX; dY; dZ]; 
+0

此处需要't(2)-t(1)'的间距参数,否则您将得到错误缩放的答案。默认情况下,“gradient”的间距为1。而且我没有办法处理非统一的时间向量,只是指出了问题 - 除了解决问题,可能会有问题。 – horchler

+0

此外,对于一阶导数,您会发现复杂的阶梯差异(不需要任何工具箱)比使用'gradient'具有更少的误差。 – horchler

+0

如果您使用'linspace'并且要求准确性,'2 * pi/N'不是正确的间距。应该使用't(2)-t(1)',因为所有的点都有很大的距离,除了最后一个点之外。 – horchler