数値数学入門
これが「Hello、World!」です のPDE(偏微分方程式)。ラプラス方程式または拡散方程式は、物理学によく登場します。たとえば、熱方程式、変形、流体力学などです。実生活は3Dですが、「こんにちは、世界!」と言いたいのです。「99本のビール...」を歌わないでください。このタスクは1Dで行われます。これは、両端の壁に何らかの力が加えられたゴム製のローブと解釈できます。
上の[0,1]
ドメイン機能を見つけるu
与えられたソース関数のf
境界値u_L
とu_R
、そのようなことを:
-u'' = f
u(0) = u_L
u(1) = u_R
u''
の二次導関数を示します u
これは純粋に理論的に解くことができますが、あなたの仕事は点の離散化された領域xで数値的に解くことですN
:
- x =
{i/(N-1) | i=0..N-1}
または1ベース:{(i-1)/(N-1) | i=1..N}
h = 1/(N-1)
間隔です
入力
f
関数または式または文字列としてu_L
、u_R
浮動小数点値としてN
整数> = 2として
出力
- 配列、リストの区切り文字列のいくつかの並べ替え
u
、その結果u_i == u(x_i)
例
例1
入力:f = -2
、u_L = u_R = 0
、N = 10
(DOは服用しないでf=-2
間違って、それが値ではなく、一定の機能を返すものではありません-2
すべてのためにx
それは私たちのロープに一定の重力のようなものです。)
出力: [-0.0, -0.09876543209876543, -0.1728395061728395, -0.22222222222222224, -0.24691358024691357, -0.24691358024691357, -0.22222222222222224, -0.1728395061728395, -0.09876543209876547, -0.0]
簡単で正確な解決策があります: u = -x*(1-x)
例2
入力:f = 10*x
、u_L = 0
u_R = 1
、N = 15
(ここでは右側に風上がたくさんあります)
出力: [ 0., 0.1898688, 0.37609329, 0.55502915, 0.72303207, 0.87645773, 1.01166181, 1.125, 1.21282799, 1.27150146, 1.29737609, 1.28680758, 1.2361516, 1.14176385, 1.]
この状態の正確な解決策: u = 1/3*(8*x-5*x^3)
例3
入力:f = sin(2*pi*x)
、u_L = u_R = 1
、N = 20
(誰かが重力を壊したりアップと風下の並べ替えがあります)
出力: [ 1., 1.0083001, 1.01570075, 1.02139999, 1.0247802, 1.0254751, 1.02340937, 1.01880687, 1.01216636, 1.00420743, 0.99579257, 0.98783364, 0.98119313, 0.97659063, 0.9745249, 0.9752198, 0.97860001, 0.98429925, 0.9916999, 1.]
ここで正確な解決策は u = (sin(2*π*x))/(4*π^2)+1
例4
入力:f = exp(x^2)
、u_L = u_R = 0
、N=30
出力:
[ 0. 0.02021032 0.03923016 0.05705528 0.07367854 0.0890899
0.10327633 0.11622169 0.12790665 0.13830853 0.14740113 0.15515453
0.16153488 0.1665041 0.17001962 0.172034 0.17249459 0.17134303
0.16851482 0.1639387 0.15753606 0.1492202 0.13889553 0.12645668
0.11178744 0.09475961 0.07523169 0.05304738 0.02803389 0. ]
わずかな非対称性に注意してください
FDM
これを解決する1つの可能な方法は、有限差分法です。
-u_i'' = f_i
として書き換える(-u_{i-1} + 2u_i - u{i+1})/h² = f_i
等しい-u_{i-1} + 2u_i - u{i+1} = h²f_i
- 方程式を設定します。
- 行列ベクトル方程式に等しい:
- この方程式を解いて、
u_i
Pythonでのデモンストレーション用のこれの1つの実装:
import matplotlib.pyplot as plt
import numpy as np
def laplace(f, uL, uR, N):
h = 1./(N-1)
x = [i*h for i in range(N)]
A = np.zeros((N,N))
b = np.zeros((N,))
A[0,0] = 1
b[0] = uL
for i in range(1,N-1):
A[i,i-1] = -1
A[i,i] = 2
A[i,i+1] = -1
b[i] = h**2*f(x[i])
A[N-1,N-1] = 1
b[N-1] = uR
u = np.linalg.solve(A,b)
plt.plot(x,u,'*-')
plt.show()
return u
print laplace(lambda x:-2, 0, 0, 10)
print laplace(lambda x:10*x, 0, 1, 15)
print laplace(lambda x:np.sin(2*np.pi*x), 1, 1, 20)
マトリックス代数を使用しない代替実装(Jacobiメソッドを使用)
def laplace(f, uL, uR, N):
h=1./(N-1)
b=[f(i*h)*h*h for i in range(N)]
b[0],b[-1]=uL,uR
u = [0]*N
def residual():
return np.sqrt(sum(r*r for r in[b[i] + u[i-1] - 2*u[i] + u[i+1] for i in range(1,N-1)]))
def jacobi():
return [uL] + [0.5*(b[i] + u[i-1] + u[i+1]) for i in range(1,N-1)] + [uR]
while residual() > 1e-6:
u = jacobi()
return u
ただし、他の方法を使用してラプラス方程式を解くことができます。あなたは反復法を使用する場合は、残留するまで繰り返す必要がある|b-Au|<1e-6
と、b
右辺ベクトルであることu_L,f_1h²,f_2h²,...
ノート
解法によっては、与えられた解に対して正確に例を解けない場合があります。少なくともN->infinity
エラーについてはゼロに近づく必要があります。
ボーナス
グラフィカルまたはASCIIアートのいずれかで、ソリューションを表示するための-30%のボーナス。
勝ち
これはcodegolfなので、バイト単位の最短コードが勝ちです!
log(log(x))
やsqrt(1-x^4)
しかし、初等関数では表現できません整数を、持っています。
u(x) = 1/2 (-sqrt(π) x erfi(x)+sqrt(π) erfi(1) x+e^(x^2)-e x+x-1)
はありません。解を分析的に表現する方法がありますが、正確に計算することはできません。
f(x) = exp(x^2)
ます。