Einführung in die Numerische Mathematik
Dies ist das "Hallo, Welt!" von PDEs (Partielle Differentialgleichungen). Die Laplace- oder Diffusionsgleichung wird in der Physik häufig verwendet, z. B. Wärmegleichung, Verformung, Fluiddynamik usw. Da das reale Leben 3D ist, möchten wir jedoch "Hallo, Welt!" und nicht singen "99 flaschen bier, ..." diese aufgabe ist in 1D gegeben. Sie können dies als eine Gummimantel interpretieren, die an beiden Enden mit etwas Kraft an einer Wand befestigt ist.
[0,1]
Suchen Sie in einer Domain eine Funktion u
für bestimmte Quellfunktionen f
und Grenzwerte, u_L
und zwar u_R
so, dass:
-u'' = f
u(0) = u_L
u(1) = u_R
u''
bezeichnet die zweite Ableitung von u
Dies kann rein theoretisch gelöst werden, aber Ihre Aufgabe ist es, es numerisch in einer diskretisierten Domäne x nach N
Punkten zu lösen :
- x =
{i/(N-1) | i=0..N-1}
oder 1-basiert:{(i-1)/(N-1) | i=1..N}
h = 1/(N-1)
ist der Abstand
Eingang
f
als Funktion oder Ausdruck oder Zeichenfolgeu_L
,u_R
Als GleitkommawerteN
als ganze Zahl> = 2
Ausgabe
- Array, List, eine Art separater String
u
davonu_i == u(x_i)
Beispiele
Beispiel 1
Input: f = -2
, u_L = u_R = 0
, N = 10
(nehmen Sie nicht f=-2
falsch, es ist kein Wert , sondern eine konstante Funktion , dass die Renditen -2
für alle x
Es ist wie eine konstante Schwerkraft auf unserem Seil..)
Ausgabe: [-0.0, -0.09876543209876543, -0.1728395061728395, -0.22222222222222224, -0.24691358024691357, -0.24691358024691357, -0.22222222222222224, -0.1728395061728395, -0.09876543209876547, -0.0]
Es gibt eine einfache exakte Lösung: u = -x*(1-x)
Beispiel 2
Input: f = 10*x
, u_L = 0
u_R = 1
, N = 15
(Hier gibt es eine Menge gegen den Wind auf der rechten Seite)
Ausgabe: [ 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.]
Die genaue Lösung hierfür lautet: u = 1/3*(8*x-5*x^3)
Beispiel 3
Input: f = sin(2*pi*x)
, u_L = u_R = 1
, N = 20
(jemand brach die Schwerkraft , oder es ist eine Art von Up- und Abwind)
Ausgabe: [ 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.]
Hier ist die genaue Lösung u = (sin(2*π*x))/(4*π^2)+1
Beispiel 4
Input: f = exp(x^2)
, u_L = u_R = 0
,N=30
Ausgabe:
[ 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. ]
Beachten Sie die leichte Unsymmetrie
FDM
Eine mögliche Methode, um dies zu lösen, ist die Finite-Differenz-Methode :
- umschreiben
-u_i'' = f_i
als (-u_{i-1} + 2u_i - u{i+1})/h² = f_i
was gleich ist-u_{i-1} + 2u_i - u{i+1} = h²f_i
- Stellen Sie die Gleichungen auf:
- Welche sind gleich einer Matrix-Vektor-Gleichung:
- Lösen Sie diese Gleichung und geben Sie die aus
u_i
Eine Implementierung davon zur Demonstration in Python:
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)
Alternative Implementierung ohne Matrixalgebra (unter Verwendung der Jacobi-Methode )
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
Sie können jedoch eine andere Methode verwenden, um die Laplace-Gleichung zu lösen. Wenn Sie eine iterative Methode verwenden, sollten Sie bis zum Residuum iterieren |b-Au|<1e-6
, wobei b
dies der Vektor auf der rechten Seite istu_L,f_1h²,f_2h²,...
Anmerkungen
Abhängig von Ihrer Lösungsmethode lösen Sie die Beispiele möglicherweise nicht genau mit den angegebenen Lösungen. Zumindest für N->infinity
den Fehler sollte sich Null nähern.
Standard-Schlupflöcher sind nicht zulässig, eingebaute PDEs sind zulässig.
Bonus
Ein Bonus von -30% für die Anzeige der Lösung, entweder grafisch oder ASCII-artig.
Gewinnen
Das ist Codegolf, also gewinnt der kürzeste Code in Bytes!
log(log(x))
odersqrt(1-x^4)
die ein Integral haben, das sich aber in Elementarfunktionen nicht ausdrücken lässt.
u(x) = 1/2 (-sqrt(π) x erfi(x)+sqrt(π) erfi(1) x+e^(x^2)-e x+x-1)
nicht genau berechenbar ist.
f(x) = exp(x^2)
.