
باستخدام النماذج المادية النموذجية كمثال ، سنقوم بدمج مهارات العمل مع الوظائف والتعرف على متخيل PyPlot السريع والمريح والجميل ، والذي يوفر كل قوة Python Matplotlib. سيكون هناك الكثير من الصور (مخبأة تحت المفسدين)
نتأكد من أن كل شيء نظيف وجديد تحت غطاء المحرك:
تحت غطاء المحرك]status Status `C:\Users\\.julia\environments\v1.0\Project.toml` [537997a7] AbstractPlotting v0.9.0 [ad839575] Blink v0.8.1 [159f3aea] Cairo v0.5.6 [5ae59095] Colors v0.9.5 [8f4d0f93] Conda v1.1.1 [0c46a032] DifferentialEquations v5.3.1 [a1bb12fb] Electron v0.3.0 [5789e2e9] FileIO v1.0.2 [5752ebe1] GMT v0.5.0 [28b8d3ca] GR v0.35.0 [c91e804a] Gadfly v1.0.0+
خلاف ذلك ، سنحصل على كل ما نحتاجه اليوم julia>] pkg> add PyCall pkg> add LaTeXStrings pkg> add PyPlot pkg> build PyPlot # build # - , pkg> add Conda # Jupyter - pkg> add IJulia # pkg> build IJulia # build
الآن إلى المهام!
حمل معادلة
في الفيزياء ، يُفهم مصطلح النقل على أنه يعني عمليات لا رجعة فيها ، ونتيجة لذلك تحدث حركة مكانية (نقل) للكتلة أو الزخم أو الطاقة أو الشحن أو بعض الكمية المادية الأخرى في النظام المادي.
معادلة النقل الخطية أحادية البعد (أو معادلة التأفق) - أبسط معادلة تفاضلية جزئية - مكتوبة بصيغة
frac جزئيU(x،t) جزئيt+c frac جزئيU(x،t) جزئيx= Phi(U،x،t)
للحل العددي لمعادلة النقل ، يمكنك استخدام مخطط الفرق الصريح:
frac hatUi−Ui tau+c fracUi−Ui−1 Delta= frac Phii−1+ Phii2
أين hatU - قيمة دالة الشبكة في الطبقة الزمنية العليا. هذه الدائرة مستقرة مع رقم Courant. K=c tau/ Delta<1
تحويل غير خطي
frac جزئيU(x،t) جزئيt+(C0+UC1) frac جزئيU(x،t) جزئيx= Phi(U،x،t)
مصدر الخط (نقل الامتصاص): Phi(U،x،t)=−BU . نستخدم مخطط الاختلاف الواضح:
Uj+1i= left(1− frachtB2− frachtC0hx− frachtC1hxUji right)Uji+Uji−1 left( frachtC0hx− frachtB2+ frachtC1hxUji right)
using Plots pyplot() a = 0.2 b = 0.01 ust = x -> x^2 * exp( -(xa)^2/b ) # bord = t -> 0. # # - function transferequi(;C0 = 1., C1 = 0., B = 0., Nx = 50, Nt = 50, tlmt = 0.01) dx = 1/Nx dt = tlmt/Nt b0 = 0.5B*dt c0 = C0*dt/dx c1 = C1*dt/dx print("Kurant: $c0 $c1") x = [i for i in range(0, length = Nx, step = dx)]# t = [i for i in range(0, length = Nt, step = dt)] # - U = zeros(Nx, Nt) U[:,1] = ust.(x) U[1,:] = bord.(t) for j = 1:Nt-1, i = 2:Nx U[i, j+1] = ( 1-b0-c0-c1*U[i,j] )*U[i,j] + ( c0-b0+c1*U[i,j] )*U[i-1,j] end t, x, U end t, X, Ans0 = transferequi( C0 = 4., C1 = 1., B = 1.5, tlmt = 0.2 ) plot(X, Ans0[:,1], lab = "t1") plot!(X, Ans0[:,10], lab = "t10") p = plot!(X, Ans0[:,40], lab = "t40") plot( p, heatmap(t, X, Ans0) ) #
دعونا زيادة الامتصاص:
t, X, Ans0 = transferequi( C0 = 2., C1 = 1., B = 3.5, tlmt = 0.2 ) plot(X, Ans0[:,1]) plot!(X, Ans0[:,10]) p = plot!(X, Ans0[:,40]) plot( p, heatmap(t, X, Ans0) )
t, X, Ans0 = transferequi( C0 = 1., C1 = 15., B = 0.1, Nx = 100, Nt = 100, tlmt = 0.4 ) plot(X, Ans0[:,1]) plot!(X, Ans0[:,20]) plot!(X, Ans0[:,90])
طرقت تقريبا
heatmap(t, X, Ans0)

معادلة الحرارة
يتم كتابة معادلة الحرارة التفاضلية (أو معادلة انتشار الحرارة) على النحو التالي:
frac جزئيT(x،t) جزئيt+D frac جزئي2U(x،t) جزئيx2= phi(T،x،t)
هذه معادلة مكافئة تحتوي على المشتق الأول بالنسبة للوقت t والثاني فيما يتعلق بالإحداثيات المكانية x. يصف ديناميكا درجة الحرارة ، على سبيل المثال ، لقضيب معدني للتبريد أو التسخين (الوظيفة T تصف ملف درجة الحرارة على طول إحداثيات x على طول القضيب). يسمى المعامل D معامل التوصيل الحراري (الانتشار). يمكن أن يكون ثابتًا أو يعتمد ، بشكل صريح على الإحداثيات ، وعلى الوظيفة المطلوبة D (t ، x ، T) نفسها.
النظر في المعادلة الخطية (معامل الانتشار ومصادر الحرارة مستقلة عن درجة الحرارة). تقريب الفرق لمعادلة تفاضلية باستخدام مخططات أويلر الصريحة والضمنية ، على التوالي:
fracTi،n+1−Ti،n tau=D fracTi−1،n−2Ti،n+Ti+1،n Delta2+ phii،n fracTi،n+1−Ti،n tau=D fracTi−1،n+1−2Ti،n+1+Ti+1،n+1 Delta2+ phii،n
δ(x) = x==0 ? 0.5 : x>0 ? 1 : 0 # - startcond = x-> δ(x-0.45) - δ(x-0.55) # bordrcond = x-> 0. # D(u) = 1 # Φ(u) = 0 # # LaTex Tab # \delta press Tab -> δ function linexplicit(Nx = 50, Nt = 40; tlmt = 0.01) dx = 1/Nx dt = tlmt/Nt k = dt/(dx*dx) print("Kurant: $k dx = $dx dt = $dt k<0.5? $(k<0.5)") x = [i for i in range(0, length = Nx, step = dx)] # t = [i for i in range(0, length = Nt, step = dt)] # - U = zeros(Nx, Nt) U[: ,1] = startcond.(x) U[1 ,:] = U[Nt,:] = bordrcond.(t) for j = 1:Nt-1, i = 2:Nx-1 U[i, j+1] = U[i,j]*(1-2k*D( U[i,j] )) + k*U[i-1,j]*D( U[i-1,j] ) + k*U[i+1,j]*D( U[i+1,j] ) + dt*Φ(U[i,j]) end t, x, U end t, X, Ans2 = linexplicit( tlmt = 0.005 ) plot(X, Ans2[:,1], lab = "t1") plot!(X, Ans2[:,10], lab = "t10") p = plot!(X, Ans2[:,40], lab = "t40", title = "Explicit scheme") plot( p, heatmap(t, X, Ans2) )
نستخدم المخطط الضمني وطريقة الاجتياح function nonexplicit(Nx = 50, Nt = 40; tlmt = 0.01) dx = 1/Nx dt = tlmt/Nt k = dt/(dx*dx) print("Kurant: $k dx = $dx dt = $dt k<0.5? $(k<0.5)\n") x = [i for i in range(0, length = Nx, step = dx)] t = [i for i in range(0, length = Nt, step = dt)] U = zeros(Nx, Nt) η = zeros(Nx+1) ξ = zeros(Nx) U[: ,1] = startcond.(x) U[1 ,:] = bordrcond.(t) U[Nt,:] = bordrcond.(t) for j = 1:Nt-1 b = -1 - 2k*D( U[1,j] ) c = -k*D( U[2,j] ) d = U[1,j] + dt*Φ(U[1,j]) ξ[2] = c/b η[2] = -d/b for i = 2:Nx-1 a = -k*D( U[i-1,j] ) b = -2k*D( U[i,j] ) - 1 c = -k*D( U[i+1,j] ) d = U[i,j] + dt*Φ(U[i,j]) ξ[i+1] = c / (ba*ξ[i]) η[i+1] = (a*η[i]-d) / (ba*ξ[i]) end U[Nx,j+1] = η[Nx] for i = Nx:-1:2 U[i-1,j+1] = ξ[i]*U[i,j+1] + η[i] end end t, x, U end plot(X, Ans2[:,1], lab = "ex_t1") plot!(X, Ans2[:,10], lab = "ex_t10") plot!(X, Ans2[:,40], lab = "ex_t40") plot!(X, Ans3[:,1], lab = "non_t1") plot!(X, Ans3[:,10], lab = "non_t10") plot!(X, Ans3[:,40], lab = "non_t40", title = "Comparison schemes")
معادلة الحرارة غير الخطية
يمكن الحصول على حلول أكثر إثارة للاهتمام لمعادلة الحرارة غير الخطية ، على سبيل المثال ، مع مصدر حرارة غير خطي phi(x،T)=103(T−T3) . إذا قمت بتعيينه في هذا النموذج ، فستحصل على حل في شكل جبهات حرارية ، تنتشر على جانبي منطقة التسخين الأساسية
Φ(u) = 1e3*(uu^3) t, X, Ans4 = linexplicit( tlmt = 0.005 ) plot(X, Ans4[:,1], lab = "ex_t1") plot!(X, Ans4[:,10], lab = "ex_t10") plot!(X, Ans4[:,40], lab = "ex_t40", title = "Thermal front")
حتى الحلول غير المتوقعة ممكنة مع عدم انتشار معامل الانتشار أيضًا. على سبيل المثال ، إذا أخذت D(x،T)=T2 ، أ phi(x،T)=103T3.5 ، ثم يمكن للمرء أن يلاحظ تأثير احتراق الوسط ، موضعي في منطقة تسخينه الأساسي (وضع الاحتراق "مع تفاقم").
في الوقت نفسه ، سوف نتحقق من كيفية عمل مخططنا الضمني مع عدم الخطية لكل من المصادر ومعامل الانتشار
D(u) = u*u Φ(u) = 1e3*abs(u)^(3.5) t, X, Ans5 = linexplicit( tlmt = 0.0005 ) t, X, Ans6 = nonexplicit( tlmt = 0.0005 ) plot(X, Ans5[:,1], lab = "ex_t1") plot!(X, Ans5[:,10], lab = "ex_t10") p1 = plot!(X, Ans5[:,40], lab = "ex_t40", title = "Burning with aggravation") p2 = heatmap(abs.(Ans6-Ans5), title = "Difference")
معادلة الموجة
معادلة الموجة الزائدية
frac جزئي2U(x،t) جزئيt2=c2 frac جزئي2U(x،t) جزئيx2
يصف الموجات الخطية أحادية البعد دون تشتت. على سبيل المثال ، اهتزازات سلسلة أو صوت في سائل (غاز) أو موجات كهرومغناطيسية في فراغ (في الحالة الأخيرة ، يجب كتابة المعادلة في شكل ناقل).
أبسط مخطط اختلاف تقريبًا لهذه المعادلة هو مخطط صريح من خمس نقاط
fracUn+1i−2Uni+Un−1i tau2=c2 fracUni+1−2Uni+Uni−1h2xi=ih،\،tn= tau
هذا المخطط ، المسمى "الصليب" ، له ترتيب ثانٍ من حيث الدقة والإحداثيات المكانية ويتكون من ثلاث طبقات في الوقت المناسب.
# ψ = x -> x^2 * exp( -(x-0.5)^2/0.01 ) # ϕ(x) = 0 c = x -> 1 # function pdesolver(N = 100, K = 100, L = 2pi, T = 10, a = 0.1 ) dx = L/N; dt = T/K; gam(x) = c(x)*c(x)*a*a*dt*dt/dx/dx; print("Kurant-Fridrihs-Levi: $(dt*a/dx) dx = $dx dt = $dt") u = zeros(N,K); x = [i for i in range(0, length = N, step = dx)] # u[:,1] = ψ.(x); u[:,2] = u[:,1] + dt*ψ.(x); # fill!( u[1,:], 0); fill!( u[N,:], ϕ(L) ); for t = 2:K-1, i = 2:N-1 u[i,t+1] = -u[i,t-1] + gam( x[i] )* (u[i-1,t] + u[i+1,t]) + (2-2*gam( x[i] ) )*u[i,t]; end x, u end N = 50; # K = 40; # a = 0.1; # L = 1; # T = 1; # t = [i for i in range(0, length = K, stop = T)] X, U = pdesolver(N, K, L, T, a) # plot(X, U[:,1]) plot!(X, U[:,40])
لبناء سطح ، سنستخدم PyPlot كبيئة مؤامرات ، ولكن بشكل مباشر:
رسم بياني سطحي using PyPlot surf(t, X, U)

وللحلوى ، تنتشر الموجة بسرعة اعتمادًا على الإحداثيات:
ψ = x -> x>1/3 ? 0 : sin(3pi*x)^2 c = x -> x>0.5 ? 0.5 : 1 X, U = pdesolver(400, 400, 8, 1.5, 1) plot(X, U[:,1]) plot!(X, U[:,40]) plot!(X, U[:,90]) plot!(X, U[:,200], xaxis=(" ", (0, 1.5), 0:0.5:2) )
النتيجة
U2 = [ U[i,j] for i = 1:60, j = 1:size(U,2) ]

heatmap(U, yaxis=(" ", (0, 50), 0:10:50))

يكفي اليوم. لمراجعة أكثر تفصيلاً:
رابط PyPlot إلى github ، وأمثلة أخرى على استخدام المؤامرات كبيئة ، ومذكرة جيدة باللغة الروسية من قبل جوليا .