伪谱方法在Julia中生成复杂的PDE(Ginzburg Landau)

时间:2019-07-03 16:11:08

标签: julia ode differential-equations pde differentialequations.jl

我想教自己关于如何使用Julia求解PDE的知识,现在我正在尝试使用Julia中的伪光谱方法求解复杂的Ginzburg Landau方程(CGLE)。但是,我为此苦苦挣扎,并且我对尝试什么有一些想法。

CGLE读取: cgle

使用傅立叶变换F及其逆F-1,我可以将其变换为频谱形式:

cgle-spectral

例如,这也是我在旧脚本中找到的(https://www.uni-muenster.de/Physik.TP/archive/fileadmin/lehre/NumMethoden/SoSe2009/Skript/script.pdf),根据我知道的同一来源,应得出alpha = 1,beta = 2和初始条件,且初始噪声水平约为0的0.01级在平面波中作为解决方案。那就是我要首先测试的。

在Chris Rackauckas(https://youtu.be/okGybBmihOE)的非常不错的教程之后,我尝试通过以下方式使用ApproxFun和DifferentialEquations解决此问题:

编辑:我更正了原始帖子中的两个错误,一个点和一个负号,但代码仍未给出正确的结果

EDIT2:发现我计算的波数CHECK CONSTRAINT完全错误

k

(已编辑)我尝试了不同的求解器,如视频中所建议,有些显然不适用于复数,有些则可行,但是当我运行此代码时,它没有给出预期成绩。该解决方案的价值仍然很小,并且不会导致实际上应该是平面波的结果。我还测试了其他可能导致混乱的初始条件,但这些条件也导致了同样很小的解决方案。我还交替使用了带有ApproxFun的显式Laplace运算符,但结果是相同的。我在这里的问题是,我既不是PDE数学模型的专家,也不是其数值处理的专家,到目前为止,我主要从事ODE的研究。

EDIT2 现在似乎或多或少地起作用了。我仍然想知道一些事情

  • 我如何在x\in[-L/2;L/2]这样的指定域上计算此值,我对它与ApproxFun的工作方式感到非常困惑,据我所知波数using ApproxFun using DifferentialEquations F = Fourier() n = 512 L = 100 T = ApproxFun.plan_transform(F, n) Ti = ApproxFun.plan_itransform(F, n) x = collect(range(-L/2,stop=L/2, length=n)) k = points(F, n) alpha = 1im beta = 2im u0 = 0.01*(rand(ComplexF64, n) .- 0.5) Fu0 = T*u0 function cgle!(du, u, p, t) a, b, k, T, Ti = p invu = Ti*u du .= (1.0 .- k.^2*(1.0 .+a)).*u .- T*( (1.0 .+b) .* (abs.(invu)).^2 .* invu) end pars = alpha, beta, k, T, Ti prob = ODEProblem(cgle!, Fu0, (0.,50.), pars) u = solve(prob, Rodas5(autodiff=false)) # plotting on a equidistant time stepping t = collect(range(0, stop=50, length=1000)) sol = zeros(eltype(u),(n, length(t))) for it in eachindex(t) sol[:,it] = Ti*u(t[it]) end IM = PyPlot.imshow(real.(sol)) cb = PyPlot.colorbar(IM, orientation="horizontal") gcf() 应该为k ,但我不确定如何使用ApproxFun
  • https://codeinthehole.com/tutorial/coherent.html显示了方程的不同动态范围/相图。虽然我可以重现其中的一些,但有些似乎不起作用,例如时空间歇性

编辑3:我通过直接使用FFTW代替ApproxFun解决了这些问题。如果有人知道如何使用ApproxFun做到这一点,尽管我仍然会对此感兴趣。下面是FFTW的代码(它在性能上也进行了一些优化)

(2pi/L)*[-N/2+1 ; N/2 -1]

编辑4 :对于这种情况,Rodas确实是一个极慢的求解器,只是使用默认值对我来说效果很好。

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

du = (1. .- k.^2*(1. .+(im*a))).*u + T*( (1. .+(im*b)) .* abs.(invu).^2 .* invu)

注意,它正在替换指向du的指针,而不是对其进行更新。使用类似.=的东西:

du .= (1. .- k.^2*(1. .+(im*a))).*u + T*( (1. .+(im*b)) .* abs.(invu).^2 .* invu)

否则,您的导数仅为0。