2013-12-16 122 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