
No exemplo dos modelos físicos mais típicos, consolidaremos as habilidades de trabalhar com funções e nos familiarizaremos com o visualizador rápido, conveniente e bonito do PyPlot, que fornece todo o poder do Matplotlib Python. Haverá muitas fotos (escondidas sob os spoilers)
Garantimos que tudo esteja limpo e fresco sob o capô:
Sob o capô]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+
Caso contrário, teremos tudo o que precisamos hoje 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
Agora para as tarefas!
Carregar equação
Na física, o termo transferência é entendido como processos irreversíveis, como resultado do qual ocorre um movimento espacial (transferência) de massa, momento, energia, carga ou alguma outra quantidade física no sistema físico.
A equação linear unidimensional de transporte (ou a equação de advecção) - a equação diferencial parcial mais simples - é escrita como
Para a solução numérica da equação de transporte, você pode usar o esquema de diferenças explícitas:
onde - o valor da função de grade na camada de tempo superior. Este circuito é estável com o número de Courant.
Transferência não linear
Fonte da linha (transferência de absorção): . Usamos o esquema de diferença explícita:
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) ) #
Vamos aumentar a absorção:
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])
Quase derrubado
heatmap(t, X, Ans0)

Equação do calor
A equação diferencial de calor (ou a equação de difusão de calor) é escrita da seguinte forma:
Esta é uma equação parabólica que contém a primeira derivada em relação ao tempo te a segunda em relação à coordenada espacial x. Ele descreve a dinâmica da temperatura, por exemplo, de uma haste de metal de resfriamento ou aquecimento (a função T descreve o perfil de temperatura ao longo da coordenada x ao longo da haste). O coeficiente D é chamado coeficiente de condutividade térmica (difusão). Pode ser constante ou depender, explicitamente das coordenadas e da função desejada D (t, x, T).
Considere a equação linear (o coeficiente de difusão e as fontes de calor são independentes da temperatura). A aproximação da diferença de uma equação diferencial usando os esquemas de Euler explícitos e implícitos, respectivamente:
δ(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) )
Usamos o esquema implícito e o método sweep 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")
Equação de calor não linear
Soluções muito mais interessantes podem ser obtidas para a equação de calor não linear, por exemplo, com uma fonte de calor não linear . Se você o definir desta forma, obterá uma solução na forma de frentes térmicas, propagando-se nos dois lados da zona de aquecimento primário
Φ(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")
Soluções ainda mais inesperadas são possíveis com a não linearidade do coeficiente de difusão. Por exemplo, se você tomar , um , pode-se observar o efeito da combustão do meio, localizado na região de seu aquecimento primário (modo S de combustão “com exacerbação”).
Ao mesmo tempo, verificaremos como nosso esquema implícito funciona com a não linearidade das fontes e do coeficiente de difusão
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")
Equação de onda
Equação da Onda Hiperbólica
descreve ondas lineares unidimensionais sem dispersão. Por exemplo, vibrações de uma corda, som em um líquido (gás) ou ondas eletromagnéticas no vácuo (neste último caso, a equação deve ser escrita em forma vetorial).
O esquema de diferenças mais simples que se aproxima dessa equação é um esquema explícito de cinco pontos
Esse esquema, chamado de "cruz", tem uma segunda ordem de precisão no tempo e nas coordenadas espaciais e possui três camadas no tempo.
# ψ = 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])
Para construir uma superfície, usaremos o PyPlot como um ambiente de plotagens, mas diretamente:
Gráfico de superfície using PyPlot surf(t, X, U)

E para a sobremesa, a onda se propaga a uma velocidade, dependendo da coordenada:
ψ = 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) )
Resultado
U2 = [ U[i,j] for i = 1:60, j = 1:size(U,2) ]

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

O suficiente por hoje. Para uma revisão mais detalhada:
O PyPlot está vinculado ao github , outros exemplos de plotagens sendo usados como ambiente e um bom memorando em russo da Julia .