Pengantar Matematika Numerik
Ini adalah "Halo, Dunia!" PDE (Persamaan Diferensial Parsial). Persamaan Laplace atau Difusi sering muncul dalam Fisika, misalnya Persamaan Panas, Deforming, Fluid Dynamics, dll ... Karena kehidupan nyata adalah 3D tetapi kami ingin mengatakan "Halo, Dunia!" dan tidak menyanyikan "99 botol bir, ..." tugas ini diberikan dalam 1D. Anda dapat menafsirkan ini sebagai jubah karet yang diikat ke dinding di kedua ujungnya dengan beberapa kekuatan yang diterapkan padanya.
Pada [0,1]
domain, temukan fungsi u
untuk fungsi sumber f
dan nilai batas yang diberikan u_L
dan u_R
sedemikian rupa sehingga:
-u'' = f
u(0) = u_L
u(1) = u_R
u''
menunjukkan turunan kedua dari u
Ini dapat dipecahkan sepenuhnya teoretis tetapi tugas Anda adalah menyelesaikannya secara numerik pada domain yang didiskritisasi x untuk N
poin:
- x =
{i/(N-1) | i=0..N-1}
atau berbasis 1:{(i-1)/(N-1) | i=1..N}
h = 1/(N-1)
adalah spasi
Memasukkan
f
sebagai fungsi atau ekspresi atau stringu_L
,u_R
sebagai nilai floating pointN
sebagai integer> = 2
Keluaran
- Array, List, semacam string terpisah
u
sehinggau_i == u(x_i)
Contohnya
Contoh 1
Input: f = -2
, u_L = u_R = 0
, N = 10
(Do tidak mengambil f=-2
salah, itu bukan nilai tapi fungsi konstan yang kembali -2
untuk semua x
Hal ini seperti gaya gravitasi konstan pada tali kami..)
Keluaran: [-0.0, -0.09876543209876543, -0.1728395061728395, -0.22222222222222224, -0.24691358024691357, -0.24691358024691357, -0.22222222222222224, -0.1728395061728395, -0.09876543209876547, -0.0]
Ada solusi tepat yang mudah: u = -x*(1-x)
Contoh 2
Input: f = 10*x
, u_L = 0
u_R = 1
, N = 15
(Di sini ada banyak melawan angin di sisi kanan)
Keluaran: [ 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.]
Solusi tepat untuk kondisi ini: u = 1/3*(8*x-5*x^3)
Contoh 3
Input: f = sin(2*pi*x)
, u_L = u_R = 1
, N = 20
(Seseorang masuk gravitasi atau ada semacam atas dan melawan arah angin)
Keluaran: [ 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.]
Di sini solusinya adalah u = (sin(2*π*x))/(4*π^2)+1
Contoh 4
Input: f = exp(x^2)
, u_L = u_R = 0
,N=30
Keluaran:
[ 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. ]
Perhatikan sedikit ketidaksimetrisan
FDM
Salah satu metode yang mungkin untuk menyelesaikan ini adalah Metode Perbedaan Hingga :
- tulis ulang
-u_i'' = f_i
sebagai (-u_{i-1} + 2u_i - u{i+1})/h² = f_i
yang sama dengan-u_{i-1} + 2u_i - u{i+1} = h²f_i
- Siapkan persamaan:
- Yang sama dengan persamaan matriks-vektor:
- Selesaikan persamaan ini dan hasilkan
u_i
Salah satu implementasi ini untuk demonstrasi di 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)
Implementasi alternatif tanpa Matriks Aljabar (menggunakan metode 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
Namun Anda dapat menggunakan metode lain untuk menyelesaikan persamaan Laplace. Jika Anda menggunakan metode berulang, Anda harus mengulanginya sampai residual|b-Au|<1e-6
, dengan b
menjadi vektor sisi kananu_L,f_1h²,f_2h²,...
Catatan
Bergantung pada metode solusi Anda, Anda mungkin tidak dapat menyelesaikan contoh dengan tepat untuk solusi yang diberikan. Setidaknya untukN->infinity
kesalahan harus mendekati nol.
Celah standar tidak diijinkan , built-in untuk PDE diizinkan.
Bonus
Bonus -30% untuk menampilkan solusi, baik grafis atau ASCII-art.
Kemenangan
Ini codegolf, jadi kode terpendek dalam byte menang!
f(x) = exp(x^2)
.log(log(x))
atausqrt(1-x^4)
yang memiliki integral, yang bagaimanapun tidak dapat diekspresikan dalam fungsi dasar.u(x) = 1/2 (-sqrt(π) x erfi(x)+sqrt(π) erfi(1) x+e^(x^2)-e x+x-1)
tidak dapat dihitung secara tepat.Jawaban:
Mathematica, 52,5 byte (= 75 * (1 - 30%))
+0,7 byte per komentar @ flawr.
Ini memplot output.
misalnya
Penjelasan
Selesaikan untuk fungsinya
u
.Subdivide
interval [0,1] menjadi bagian N (input 4).Peta
u
ke output dariSubdivide
.Plot hasil akhirnya.
Solusi non-grafik: 58 byte
sumber
f(x) = exp(x^2)
NDSolve
untuk solusi umum non elementer.Matlab,
84, 81.279.1 byte = 113 - 30%Perhatikan bahwa dalam contoh ini saya menggunakan vektor baris, ini berarti bahwa matriks
A
ditransposisikan.f
diambil sebagai pegangan fungsi,a,b
adalah sisi Dirichlet kiri / kanan yang dikelantang.Sebagai contoh
f = 10*x, u_L = 0 u_R = 1, N = 15
ini menghasilkan:sumber
R,
123,2 102,998,7 byte (141-30%)Sunting: Menyimpan beberapa byte berkat @Angs!
Jika seseorang ingin mengedit gambar, jangan ragu untuk melakukannya. Ini pada dasarnya merupakan adaptasi R dari versi matlab dan python yang diposting.
Tidak digabungkan & dijelaskan:
Contoh & uji kasus:
Fungsi yang dinamai dan tidak diubah dapat disebut menggunakan:
Perhatikan bahwa
f
argumennya adalah fungsi-R.Untuk menjalankan versi golf cukup gunakan
(function(...){...})(args)
sumber
is.numeric(f)
cek jika Anda mendeklarasikanf
sebagai fungsi, tidak ada persyaratan untuk meneruskannya secara langsung dalam panggilan fungsi ke pemecah.f
sebagai fungsi sehingga Anda tidak perlu memeriksa kasus itu adalah konstanta (fungsi).f
menjadi numerik.f = (function(x)-2)
bekerja untuk contoh pertama, jadi tidak perlurep
.x<-0:10/10;f<-function(x){-2};10^-2*sapply(x,f)
jika f (x) tidak dikarantina untuk di-vektor-kan atau hanya10^-2*f(x)
jika dif
-vektor-kan (laplace(Vectorize(function(x)2),0,0,10
)f
sebagai fungsi yang tepat.Haskell,
195168 bytesKeterbacaannya cukup terpukul. Tidak Disatukan:
TODO: Mencetak dalam
8371 byte.Biar kulihat:
Doh!
sumber
Aksioma,
579460 byteungolf itu dan uji
fungsi untuk pertanyaannya adalah m (,,,) kode di atas dimasukkan ke dalam file "file.input" dan memuat dalam Aksioma. Hasilnya tergantung dari fungsi digit ().
jika seseorang berpikir itu bukan golf => dia dapat menunjukkan bagaimana melakukannya ... terima kasih
PS
tampaknya 6 angka di samping itu. untuk e ^ (x ^ 2) tidak ok di sini atau dalam contoh tetapi di sini saya meningkatkan angka tetapi angka tidak berubah ... bagi saya itu berarti angka dalam contoh salah. Mengapa yang lainnya belum menunjukkan jumlahnya?
untuk dosa (2 *% pi * x) ada masalah juga
"Di sini solusi yang tepat adalah u = (sin (2 * π * x)) / (4 * π ^ 2) +1" "saya menyalin solusi yang tepat untuk x = 1/19:
di WolframAlpha https://www.wolframalpha.com/input/?i=(sin(2% CF% 80% 2F19))% 2F (4 % CF% 80% 5E2)% 2B1 hasilnya
1,0083001 diusulkan karena hasilnya berbeda dalam digit ke-4 dari hasil nyata, 1,00822473 ... (dan bukan ke-6)
sumber
f=-2
contoh yang memiliki solusi analitis dan numerik yang cocok.