跳轉到內容

並行譜數值方法/非線性常微分方程和迭代

來自華夏公益教科書

非線性常微分方程和迭代

[編輯 | 編輯原始碼]

隱式顯式方法避免了直接求解非線性問題。這對某些問題可能是有利的,但在其他問題中可能導致嚴重的步長限制。此外,由此產生的數值方案有時可能具有不良的定性特性。出於這個原因,我們需要描述允許我們求解完全隱式數值方案中產生的非線性方程的方法。

我們考慮一個常微分方程 ,其中 ,其中 不一定是關於 的線性函式。我們希望使用隱式數值方法來獲得該問題的近似解 - 例如向後尤拉方法。如果我們想要證明數值方案的收斂性,我們需要證明我們用來在使用向後尤拉方法時找到非線性方程項的解的函式迭代的收斂性。

以下結果主要來自 Iserles[1],雖然這些材料也經常出現在微積分教材中,例如 Lax, Burstein 和 Lax[2],以及 Hughes 等人[3]。我們將令 表示時間步長 時的時刻, 表示時間步長 時的近似解, 表示時間步長。我們將假設 是 Lipschitz 連續的,這是一個比可微更弱但比連續更強的條件,我們將在後面給出它的精確定義。有兩種經典的迭代方法

  • 不動點迭代
  • 牛頓 (牛頓-拉夫森) 法。

我們將證明這兩種方法的收斂性(修正牛頓-拉夫森方法的收斂性證明見 Iserles[4])。我們將分析特定問題 ,其中初始資料為 .

非線性常微分方程示例的精確解

[編輯 | 編輯原始碼]

我們考慮 以及初始條件 。只要解 存在,它始終為正,因為初始值為正,且 為正。

為了顯式地積分這個方程,我們使用變數分離法,發現 ,這意味著 ,其中 是積分常數。使用我們的初始條件,我們得到 ,所以 是這個問題的精確解。我們將使用這個精確解來比較不同迭代方法獲得的數值解。請注意,當 時,這個精確解變為無窮大。

證明收斂所需的定義

[編輯 | 編輯原始碼]

定義函式 被稱為利普希茨函式,如果對於所有 在定義域 內滿足

利普希茨條件有兩個具體的定義。

定義 函式 被稱為區域性利普希茨函式,如果對於每個 ,都存在一個 ,使得 在以 為中心、半徑為 的開球上是利普希茨函式。

定義 如果 在整個空間 上是利普希茨函式(即上面的定義中開球是 ),那麼 被稱為全域性利普希茨函式。

請注意區域性利普希茨條件和全域性利普希茨條件之間的根本區別。在區域性版本中,利普希茨“常數”()和開球都取決於每個點 ,而在全域性版本中,“常數”()是固定的,開球是 。特別是,全域性利普希茨函式是區域性利普希茨連續的,但反之則不成立。

常微分方程解的存在性和唯一性

[編輯 | 編輯原始碼]

Peano 定理指出,如果 是連續的,那麼常微分方程 至少在時間 的某個鄰域記憶體在解,但該解不一定是唯一的。Picard 定理指出,如果 是區域性 Lipschitz 連續的,那麼常微分方程 的解在存在時是唯一的,初始條件為 。這些定理的詳細陳述可以在 Iserles[5] 中找到,許多關於常微分方程的書籍中都有這些定理的證明(例如 Birkhoff 和 Rota[6])。

後向尤拉方法

[edit | edit source]

我們回憶一下後向尤拉方法由 給出。注意,如果 是非線性的,我們需要在每一步推進解的過程中求解一個非線性方程(數值)。使用解析方法精確地求解非線性方程通常很困難,因此我們也使用數值方法。對於我們的示例方程,我們得到 。這個例子有一個優點,我們可以用代數方法找到它的解,所以我們可以檢查數值方案的行為。

函式迭代的收斂性

[edit | edit source]

我們經常使用函式迭代來求解非線性方程。我們回憶一下,有兩種常用的方法:不動點迭代和牛頓法。

不動點法的收斂性

[edit | edit source]

我們想要找到一個方程 的根。我們嘗試使用不動點法,構建一個序列 ,其中 .

定理 有一個不動點 ,對於 是 Lipschitz 連續的,其 Lipschitz 常數為 ,並且 上是連續的。那麼不動點法 會收斂到 ,它是在 的唯一不動點。

證明 由於 是 Lipschitz 連續的,我們發現, 對於 。因此,透過歸納法,我們得出結論 由於 ,因此我們得到一個解 ,其中 是不動點。我們可以透過假設存在兩個不同的極限並得出矛盾來證明該極限是唯一的。

有關在該定理中使用的假設下不動點存在的證明,請參閱數值分析方面的書籍,例如 Bradie[7] 或 Iserles[8]

關於我們的問題,我們應用不動點迭代,我們想要找到以下形式方程的根

 

 

 

 

( 1)

當時間步長 足夠小時,則 。因此,只要時間步長足夠小,不動點迭代就是收斂的。我們注意到方程式 1 具有兩個根,因此初始迭代的域在確定選擇哪個根方面起著重要作用。

牛頓法收斂性

[edit | edit source]

現在我們考慮牛頓法。我們想要找到一個根, 使得 牛頓法是一種不動點法,其中迭代由以下公式構造:

 

 

 

 

( 2)

其中 . 如果函式 行為良好,則牛頓法具有二次收斂速度。

定理 假設 是二次連續可微的,並且它的二階導數是有界的。還假設存在 使得 . 假設 在區間 中, 在同一區間內是有限的,並且 很小。那麼,牛頓法具有二次收斂速度。

Proof by Taylor expansion with Lagrange form remainder. In the above . Since , we have so Plug in the formula for , from eq. 2 we have Let We have and by our assumption, we know there is a constant such that Hence we have for some finite constant . So Newton's method is convergent provided is sufficiently small.

關於我們的問題,我們考慮 . 因此 並且 是有限的,所以如果我們適當地選擇初始資料和初始迭代,我們的問題滿足所有假設。因此,牛頓迭代將收斂並給出後向尤拉法的非線性項的近似值。

Theta 法的收斂性

[編輯 | 編輯原始碼]

向後尤拉法、向前尤拉法和克朗尼克森法是 Theta 方法的特殊情況,因此我們將首先證明 Theta 方法的收斂性以包含這三種方法。Theta 方法是以下演算法: 其中 。需要注意的是,當 時,我們得到克朗尼克森法或梯形法則。

首先,代入精確解 並使用泰勒展開,我們有

從以下表達式中減去最後一個表示式:

足夠小時,我們有

其中

其中

其中 。使用三角不等式和 的 Lipschitz 連續性,存在常數 使得

如果

如果

時,theta 方法簡化為梯形法則。可以證明 Crank-Nicolson 方法具有二階收斂性,例如,參見 Iserles[9]。現在讓我們考慮

我們斷言 。我們用數學歸納法來證明這個結論。當 時,,因為初始條件是精確計算的。現在假設這個結論對 成立,其中 且為整數。我們需要證明這個結論對 也成立。考慮

然後代入

我們有

所以我們的斷言對所有 成立。注意

根據指數函式的泰勒展開,我們有

根據我們的條件, 因此 因此,我們有 。 因此當 時,theta 方法是一階收斂的。

需要注意的是,當 時,theta 方法的特殊情況是後向尤拉法,所以後向尤拉法是一階收斂的。我們得到了定理結論。

定理 後向尤拉法是一階收斂的。

備註 如果 是全域性利普希茨的,那麼我們可以對任何時間區間應用上述論證。如果 僅僅是區域性利普希茨的,那麼我們需要更仔細地分析情況。首先,根據皮卡定理,這個常微分方程在很短的時間記憶體在唯一的解。實際上,我們只需要知道利普希茨常數是有限的,而不需要知道它的確切值。

備註 如果不知道皮卡定理,可以透過時間離散化推匯出常微分方程解的存在性和唯一性。

現在我們考慮 。該問題的精確解為 。因此 。在我們這個問題中, 顯然是解析的,並且在區域性上是 Lipschitz 連續的。很容易證明 不是全域性 Lipschitz 連續的。如果一個函式 滿足全域性 Lipschitz 條件,那麼存在一個有限常數 使得對於所有 都有 。在我們這個問題中,令 ,很容易驗證

現在我們討論如何找到區域性 Lipschitz 常數 。當 可微時,我們通常只需對 求導,並在感興趣的域中找到其導數的最大值。在我們的例子中, 很簡單,我們只需要知道 Lipschitz 常數是有限的。因此,我們使用一種更粗略的方法來證明 Lipschitz 常數是有限的。

因此,找到 在這個問題中的最大值就足夠了。在我們這個問題中, 是連續的。此外, 將始終為正,因為初始值為正,而 為正。連續函式在閉合有界集合中具有有限最大值。請注意,我們問題的精確解是 ,因此 。因此,我們知道我們問題中的 Lipschitz 常數是有限的。

最後,我們得到了函式迭代和我們問題的後向尤拉方法的收斂性。因此,我們針對 以及初始資料 的數值方案是收斂的。

推論 根據常微分方程解的存在性和唯一性定理以及本頁中的定理,我們得出最終目標,即後向尤拉方法與函式迭代生成的數值解在時間步長 趨於零時存在且唯一。

備註 這需要在進行函式迭代時仔細選擇初始迭代值。

備註 通常,ODE 的精確解是未知的,儘管可以推斷出區域性 Lipschitz 連續性。如果解變為無窮大,數值方法將無法收斂,或者如果近似解接近精確解,則會顯示非常大的值。在這些情況下解釋此類數值模擬時,需要謹慎。

使用迭代求解非線性常微分方程的示例程式

[編輯 | 編輯原始碼]

以下兩個 Matlab 和 Python 程式演示了示例方程的後向尤拉法。第一個程式使用不動點迭代來求解非線性項,第二個程式使用牛頓法來求解非線性項。

 

 

 

 

( A)
一個演示不動點迭代的 Matlab 程式 程式碼下載
% A program to solve y'=y^2 using the backward Euler
% method and fixed point iteration
% This is not optimized and is very simple

clear all; format compact; format short;
set(0,'defaultaxesfontsize',25,'defaultaxeslinewidth',.7,...
'defaultlinelinewidth',6,'defaultpatchlinewidth',3.7,...
'defaultaxesfontweight','bold')

n=10000; % Number of timesteps
Tmax=0.99; % Maximum time
y0=1; % Initial value
tol=0.1^10; % Tolerance for fixed point iterations
dt=Tmax/n; % Time step
y=zeros(1,n); % vector for discrete solution
t=zeros(1,n); % vector for times of discrete solution
y(1)=y0;
t(1)=0;
tic, % start timing
for i=1:n
    yold=y(i); ynew=y(i); err=1;
    while err>tol
        ynew=dt*yold^2+y(i);
        err=abs(ynew-yold);
        yold=ynew;
    end
    y(i+1)=ynew;
    t(i+1)=t(i)+dt;
end
toc, % stop timing
yexact=1./(1-t); max(abs(y-yexact)), % print the maximum error
figure(1); clf; plot(t,y,'r+',t,yexact,'b-.');
xlabel Time; ylabel Solution; legend('Backward Euler','Exact solution');
title('Numerical solution of dy/dt=y^2');

 

 

 

 

( Ap)
一個演示不動點迭代的 Python 程式 程式碼下載
#!/usr/bin/env python
"""
A program to solve y'=y^2 using the backward Euler
method and fixed point iteration
This is not optimized and is very simple
"""

import time
import matplotlib.pyplot as plt

N = 1000	# Number of timesteps
tmax = 0.99	# Maximum time
y0 = 1
t0 = 0	# Initial value
tol = pow(0.1,10)	# Tolerance for fixed point iterations
h = tmax/N	# Time step

y = [y0]	# Variables holding the values of iterations
t = [t0]	# Times of discrete solutions



T0 = time.clock()
for i in xrange(N):
yold = y[i]
ynew = y[i]
err = 1
while err > tol:
ynew = h*pow(yold,2)+y[i]
err = abs(ynew-yold)
yold = ynew
y.append(ynew)
t.append(t[i]+h)

T = time.clock() - T0	
yexact = [1.0/(1.0-x) for x in t]

print
print "Exact value: y(%d)=%f" % (tmax, 1/(1-tmax))
print "Value given by aproximation: y(%d)=%f" % (tmax, y[-1])
maxerr=(max([abs(y[i] - yexact[i]) for i in xrange(len(y))]))
print "Maximum error: %f" % maxerr
print "Elapsed time is %f" % (T)

plt.figure()
plt.plot(t,y,'r+',t,yexact,'b-.')
plt.xlabel('Time')
plt.ylabel('Solution')
plt.legend(('Backward Euler', 'Exact solution'))
plt.title('Numerical solution of dy/dt=y^2')
plt.show()


 

 

 

 

( B)
一個演示牛頓迭代的 Matlab 程式 程式碼下載
% A program to solve y'=y^2 using the backward Euler
% method and Newton iteration
% This is not optimized and is very simple

set(0,'defaultaxesfontsize',25,'defaultaxeslinewidth',.7,...
'defaultlinelinewidth',6,'defaultpatchlinewidth',3.7,...
    'defaultaxesfontweight','bold')

n=100000; % Number of timesteps
Tmax=0.99; % Maximum time
y0=1; % Initial value
tol=0.1^10; % Tolerance for fixed point iterations
dt=Tmax/n; % Time step
y=zeros(1,n); % vector for discrete solution
t=zeros(1,n); % vector for times of discrete solution
y(1)=y0;
t(1)=0;
tic, % start timing
for i=1:n
    yold=y(i); ynew=y(i); err=1;
    while err>tol
        ynew=yold-(yold-y(i)-dt*yold^2)/(1-2*dt*yold);
        err=abs(ynew-yold);
        yold=ynew;
    end
    y(i+1)=ynew;
    t(i+1)=t(i)+dt;
end
toc, % stop timing
yexact=1./(1-t); max(abs(y-yexact)), % print maximum error
figure(1); clf; plot(t,y,'r+',t,yexact,'b-.');
xlabel Time; ylabel Solution;
legend('Backward Euler','Exact solution');
title('Numerical solution of dy/dt=y^2');

 

 

 

 

( Bp)
一個演示牛頓迭代的 Python 程式。 程式碼下載
#!/usr/bin/env python
"""
A program to solve y'=y^2 using the backward Euler
method and Newton iteration
This is not optimized and is very simple
"""

import time
import matplotlib.pyplot as plt

N = 1000 # Number of timesteps
tmax = 0.99 # Maximum value
t0 = 0 # Initial t value
y0 = 1 # Initial value y(t0) = y0
tol = 0.1**10 # Tolerance for fixed point iterations
h = (tmax - t0)/N # Time step

y = [y0] # List for discrete solutions
t = [t0] # List with grid of discrete values of t

T0 = time.clock() #Start timing

for i in xrange(N):
    yold = y[i]
    ynew = y[i]
    err =1
    while err > tol:
        ynew = yold-(yold-y[i]-h*(yold**2))/(1-2*h*yold)
        err = abs(ynew-yold)
        yold = ynew
    y.append(ynew)
    t.append(t[-1]+h)

T = time.clock() - T0 # Stop timing


print "Exact value y(%f) = %f " % (t[N], 1/(1-t[N]))
print "Value given by approx y_n(%f) = %f" % (t[N], y[N])
print "The error = y-y_n = %f " % (abs(1/(1-t[N]) - y[N]))
print "Time taken = %f " % (T)

yexact = [1.0/(1.0-x) for x in t]

plt.figure();
plt.plot(t,y,'r+',t,yexact,'b-.');
plt.xlabel('Time')
plt.ylabel('Solution')
plt.legend(('Backward Euler', 'Exact Solution'))
plt.title('Numerical solution of dy/dt=y^2')
plt.show()
  1. 執行 Matlab 中的不動點迭代程式,並檢查結果是否合理。現在,研究將時間步數從 0 到 0.99 的變化以及不動點迭代的容差對最大誤差的影響。特別是,嘗試 1,000 到 1,000,000(以 10 的冪表示)的時間步數範圍,以及 (以 的冪表示)的容差範圍。您應該觀察到,細分數和容差的“理想”組合可以最小化誤差。這些組合是什麼?使用牛頓迭代重複整個過程。答案如何變化?
  2. 編寫一個 Matlab 程式,使用 Crank-Nicolson 方法和不動點迭代來求解 ,其中 。解釋為什麼不動點迭代可以收斂到兩個不動點。哪一個不動點給出了微分方程解的正確近似值?評論不動點迭代的初始迭代的選擇如何決定方法收斂到的不動點。
    1. 證明微分方程 ,其中 不是 Lipschitz 連續的。
    2. 找到該微分方程的至少兩個解析解。
    3. 使用前向尤拉法計算該微分方程的數值解。
    4. 使用後向尤拉法計算該微分方程的數值解。請務必嘗試不動點迭代的不同初始猜測,而不僅僅是前一步的值;您應該能夠計算出初始迭代的選擇對數值方法選擇的解的影響。對此發表評論。
    5. 使用隱式中點規則計算該微分方程的數值解。請務必嘗試不動點迭代的不同初始猜測,而不僅僅是前一步的值;您應該能夠計算出初始迭代的選擇對數值方法選擇的“解”的影響。對此發表評論。
    6. 使用牛頓迭代重複 (d) 和 (e)。
    7. 評論數值方法對求解沒有唯一解的微分方程的適用性。
  1. 修改一維 Allen-Cahn 方程的程式,使其使用 Crank-Nicolson 方法和非線性項的定點迭代。您需要在實空間中計算非線性項,以便您的最終方案為 其中 表示時間步長,而 表示迭代次數。當連續迭代之間的最大差異足夠小時,停止迭代。
  2. 修改二維 Allen-Cahn 方程的程式,使其使用 Crank-Nicolson 方法和非線性項的定點迭代。您需要在實空間中計算非線性項。
  1. Iserles (2009)
  2. Lax, Burstein 和 Lax (1979)
  3. Hughes 等人 (2008)
  4. Iserles (2009)
  5. Iserles (2009)
  6. Birkhoff 和 Rota (1989)
  7. Bradie (2006)
  8. Iserles (2009)
  9. Iserles (2009)

參考文獻

[編輯 | 編輯原始碼]

Birkhoff, G; Rota, G.C. (1989). 常微分方程 (第 4 版). 約翰·威立。

Bradie, B. (2006). 數值分析友好入門. 皮爾森。

Hughes-Hallett, D. (2008). 微積分,單變數和多變數 (第 5 版). 約翰·威立。 {{cite book}}: 未知引數 |coauthors= 被忽略 (|author= 建議) (幫助)

Iserles, A. (2009). 微分方程數值分析入門. 劍橋大學出版社。

Lax, A. (1976). 應用和計算微積分. 第 1 卷. 施普林格。

華夏公益教科書