Skip to content

Rayleigh-Bénard convection (2D)

A hot and a cold plate generate a convection cell in a box.

julia
using CairoMakie
using IncompressibleNavierStokes

Output directory for saving results

julia
outdir = joinpath(@__DIR__, "output", "RayleighBenard2D")
"/home/runner/work/IncompressibleNavierStokes.jl/IncompressibleNavierStokes.jl/docs/build/examples/generated/output/RayleighBenard2D"

Hardware

julia
backend = CPU()

# using CUDA, CUDSS
# backend = CUDABackend()
CPU(false)

Define observer function to track Nusselt numbers on top and bottom plates.

julia
function nusseltplot(state; setup)
    state isa Observable || (state = Observable(state))
    (; Δ, Δu) = setup.grid
    Δy1 = Δu[2][1:1] |> sum
    Δy2 = Δu[2][end-1:end-1] |> sum

    # Observe Nusselt numbers
    Nu1 = Observable(Point2f[])
    Nu2 = Observable(Point2f[])
    on(state) do (; temp, t)
        dTdy = @. (temp[:, 2] - temp[:, 1]) / Δy1
        Nu = sum((.-dTdy.*Δ[1])[2:end-1])
        push!(Nu1[], Point2f(t, Nu))
        dTdy = @. (temp[:, end-1] - temp[:, end-2]) / Δy2
        Nu = sum((.-dTdy.*Δ[1])[2:end-1])
        push!(Nu2[], Point2f(t, Nu))
        (Nu1, Nu2) .|> notify ## Update plot
    end

    # Plot Nu history
    fig = Figure()
    ax = Axis(fig[1, 1]; title = "Nusselt number", xlabel = "t", ylabel = "Nu")
    lines!(ax, Nu1; label = "Lower plate")
    lines!(ax, Nu2; label = "Upper plate")
    axislegend(ax)
    on(_ -> autolimits!(ax), Nu2)
    fig
end
nusseltplot (generic function with 1 method)

Define observer function to track average temperature.

julia
function averagetemp(state; setup)
    state isa Observable || (state = Observable(state))
    (; xp, Δ, Ip) = setup.grid
    ix = Ip.indices[1]
    Ty = lift(state) do (; temp)
        Ty = sum(temp[ix, :] .* Δ[1][ix]; dims = 1) ./ sum(Δ[1][ix])
        Array(Ty)[:]
    end
    Ty0 = copy(Ty[])
    yy = Array(xp[2])
    fig = Figure()
    ax = Axis(fig[1, 1]; title = "Average temperature", xlabel = "T", ylabel = "y")
    lines!(ax, Ty0, yy; label = "t = 0")
    lines!(ax, Ty, yy; label = "t = t")
    axislegend(ax)
    on(_ -> autolimits!(ax), Ty)
    fig
end
averagetemp (generic function with 1 method)

Instabilities should depend on the floating point precision. Try both Float32 and Float64.

julia
T = Float32
Float32

Temperature equation setup.

julia
temperature = temperature_equation(;
    Pr = T(0.71),
    Ra = T(1e7),
    Ge = T(1.0),
    dodissipation = true,
    boundary_conditions = (
        (SymmetricBC(), SymmetricBC()),
        (DirichletBC(T(1)), DirichletBC(T(0))),
    ),
    gdir = 2,
    nondim_type = 1,
)
(α1 = 0.00026645826f0, α2 = 1.0f0, α3 = 0.00026645826f0, α4 = 0.0003752933f0, γ = 1.0f0, dodissipation = true, boundary_conditions = ((SymmetricBC(), SymmetricBC()), (DirichletBC{Float32}(1.0f0), DirichletBC{Float32}(0.0f0))), gdir = 2)

Grid

julia
n = 100
x = tanh_grid(T(0), T(2), 2n, T(1.2)), tanh_grid(T(0), T(1), n, T(1.2))
plotgrid(x...)

Setup

julia
setup = Setup(;
    x,
    boundary_conditions = ((DirichletBC(), DirichletBC()), (DirichletBC(), DirichletBC())),
    Re = 1 / temperature.α1,
    temperature,
    backend,
);

Initial conditions

julia
ustart = velocityfield(setup, (dim, x, y) -> zero(x));
tempstart = temperaturefield(setup, (x, y) -> one(y) / 2 + max(sinpi(20 * x) / 100, 0));

Processors

julia
processors = (;
    rtp = realtimeplotter(;
        setup,
        fieldname = :temperature,
        colorrange = (T(0), T(1)),
        size = (600, 350),
        colormap = :seaborn_icefire_gradient,
        nupdate = 20,
    ),
    nusselt = realtimeplotter(;
        setup,
        plot = nusseltplot,
        nupdate = 20,
    ),
    avg = realtimeplotter(;
        setup,
        plot = averagetemp,
        nupdate = 50,
    ),
    log = timelogger(; nupdate = 1000),
)
(rtp = (initialize = IncompressibleNavierStokes.var"#312#314"{@NamedTuple{grid::@NamedTuple{xlims::Tuple{Tuple{Float32, Float32}, Tuple{Float32, Float32}}, dimension::IncompressibleNavierStokes.Dimension{2}, N::Tuple{Int64, Int64}, Nu::Tuple{Tuple{Int64, Int64}, Tuple{Int64, Int64}}, Np::Tuple{Int64, Int64}, Iu::Tuple{CartesianIndices{2, Tuple{UnitRange{Int64}, UnitRange{Int64}}}, CartesianIndices{2, Tuple{UnitRange{Int64}, UnitRange{Int64}}}}, Ip::CartesianIndices{2, Tuple{UnitRange{Int64}, UnitRange{Int64}}}, x::Tuple{Vector{Float32}, Vector{Float32}}, xu::Tuple{Tuple{Vector{Float32}, Vector{Float32}}, Tuple{Vector{Float32}, Vector{Float32}}}, xp::Tuple{Vector{Float32}, Vector{Float32}}, Δ::Tuple{Vector{Float32}, Vector{Float32}}, Δu::Tuple{Vector{Float32}, Vector{Float32}}, A::Tuple{Tuple{Tuple{Vector{Float32}, Vector{Float32}}, Tuple{Vector{Float32}, Vector{Float32}}}, Tuple{Tuple{Vector{Float32}, Vector{Float32}}, Tuple{Vector{Float32}, Vector{Float32}}}}}, boundary_conditions::Tuple{Tuple{DirichletBC{Nothing}, DirichletBC{Nothing}}, Tuple{DirichletBC{Nothing}, DirichletBC{Nothing}}}, Re::Float32, bodyforce::Nothing, issteadybodyforce::Bool, closure_model::Nothing, backend::CPU, workgroupsize::Int64, temperature::@NamedTuple{α1::Float32, α2::Float32, α3::Float32, α4::Float32, γ::Float32, dodissipation::Bool, boundary_conditions::Tuple{Tuple{SymmetricBC, SymmetricBC}, Tuple{DirichletBC{Float32}, DirichletBC{Float32}}}, gdir::Int64}}, typeof(fieldplot), Int64, Bool, Nothing, Bool, Nothing, Base.Pairs{Symbol, Any, NTuple{4, Symbol}, @NamedTuple{fieldname::Symbol, colorrange::Tuple{Float32, Float32}, size::Tuple{Int64, Int64}, colormap::Symbol}}}((grid = (xlims = ((0.0f0, 2.0f0), (0.0f0, 1.0f0)), dimension = IncompressibleNavierStokes.Dimension{2}(), N = (202, 102), Nu = ((199, 100), (200, 99)), Np = (200, 100), Iu = (CartesianIndices((2:200, 2:101)), CartesianIndices((2:201, 2:100))), Ip = CartesianIndices((2:201, 2:101)), x = (Float32[0.0, 0.0, 0.0044347644, 0.008958757, 0.0135733485, 0.01827985, 0.023079693, 0.027974367, 0.032965183, 0.038053393  …  1.9619466, 1.9670348, 1.9720256, 1.9769204, 1.9817202, 1.9864266, 1.9910412, 1.9955652, 2.0, 2.0], Float32[0.0, 0.0, 0.0044793785, 0.009139925, 0.013987184, 0.019026697, 0.024263948, 0.029704452, 0.03535363, 0.04121679  …  0.9587832, 0.96464634, 0.97029555, 0.975736, 0.9809733, 0.9860128, 0.9908601, 0.9955206, 1.0, 1.0]), xu = ((Float32[0.0, 0.0044347644, 0.008958757, 0.0135733485, 0.01827985, 0.023079693, 0.027974367, 0.032965183, 0.038053393, 0.043240547  …  1.9619466, 1.9670348, 1.9720256, 1.9769204, 1.9817202, 1.9864266, 1.9910412, 1.9955652, 2.0, 2.0], Float32[0.0, 0.0022396892, 0.006809652, 0.011563554, 0.01650694, 0.021645322, 0.0269842, 0.03252904, 0.03828521, 0.044257984  …  0.955742, 0.96171474, 0.96747094, 0.9730158, 0.9783547, 0.9834931, 0.98843646, 0.99319035, 0.9977603, 1.0]), (Float32[0.0, 0.0022173822, 0.0066967607, 0.011266053, 0.0159266, 0.020679772, 0.02552703, 0.030469775, 0.03550929, 0.04064697  …  1.959353, 1.9644907, 1.9695302, 1.974473, 1.9793203, 1.9840734, 1.9887339, 1.9933032, 1.9977826, 2.0], Float32[0.0, 0.0044793785, 0.009139925, 0.013987184, 0.019026697, 0.024263948, 0.029704452, 0.03535363, 0.04121679, 0.047299176  …  0.9587832, 0.96464634, 0.97029555, 0.975736, 0.9809733, 0.9860128, 0.9908601, 0.9955206, 1.0, 1.0])), xp = (Float32[0.0, 0.0022173822, 0.0066967607, 0.011266053, 0.0159266, 0.020679772, 0.02552703, 0.030469775, 0.03550929, 0.04064697  …  1.959353, 1.9644907, 1.9695302, 1.974473, 1.9793203, 1.9840734, 1.9887339, 1.9933032, 1.9977826, 2.0], Float32[0.0, 0.0022396892, 0.006809652, 0.011563554, 0.01650694, 0.021645322, 0.0269842, 0.03252904, 0.03828521, 0.044257984  …  0.955742, 0.96171474, 0.96747094, 0.9730158, 0.9783547, 0.9834931, 0.98843646, 0.99319035, 0.9977603, 1.0]), Δ = (Float32[1.1920929f-7, 0.0044347644, 0.0045239925, 0.0046145916, 0.004706502, 0.004799843, 0.004894674, 0.004990816, 0.00508821, 0.005187154  …  0.005187154, 0.00508821, 0.004990816, 0.0048947334, 0.004799843, 0.0047063828, 0.0046145916, 0.0045239925, 0.004434824, 1.1920929f-7], Float32[1.1920929f-7, 0.0044793785, 0.004660547, 0.0048472583, 0.005039513, 0.0052372515, 0.0054405034, 0.005649179, 0.00586316, 0.006082386  …  0.006082356, 0.00586313, 0.005649209, 0.0054404736, 0.0052372813, 0.005039513, 0.004847288, 0.004660487, 0.0044794083, 1.1920929f-7]), Δu = (Float32[0.0022173822, 0.0044793785, 0.004569292, 0.004660547, 0.0047531724, 0.0048472583, 0.004942745, 0.005039513, 0.005137682, 0.0052372515  …  0.005137682, 0.0050395727, 0.004942775, 0.004847288, 0.004753113, 0.004660487, 0.004569292, 0.0044794083, 0.002217412, 1.1920929f-7], Float32[0.0022396892, 0.0045699626, 0.0047539026, 0.0049433857, 0.0051383823, 0.0053388774, 0.0055448413, 0.0057561696, 0.005972773, 0.0061945915  …  0.005972743, 0.0057561994, 0.0055448413, 0.0053389072, 0.005138397, 0.004943371, 0.0047538877, 0.0045699477, 0.0022397041, 1.1920929f-7]), A = (((Float32[1.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5  …  0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5], Float32[0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5  …  0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1.0]), (Float32[1.0, 1.0, 0.5099108, 0.50981885, 0.5097228, 0.50962067, 0.50951755, 0.5094086, 0.50929356, 0.509176  …  0.49093604, 0.49081892, 0.4907065, 0.49058872, 0.4904881, 0.49038374, 0.49028164, 0.49017644, 0.49009407, 0.0], Float32[0.0, 0.49008918, 0.49018115, 0.49027717, 0.49037933, 0.49048245, 0.49059144, 0.49070647, 0.49082395, 0.49094325  …  0.5091811, 0.5092935, 0.5094113, 0.5095119, 0.50961626, 0.50971836, 0.50982356, 0.50990593, 1.0, 1.0])), ((Float32[1.0, 1.0, 0.50497997, 0.50495696, 0.50493026, 0.5049094, 0.5048909, 0.5048628, 0.50483155, 0.5048146  …  0.49520862, 0.4951738, 0.4951626, 0.49514025, 0.49510598, 0.4950843, 0.49507612, 0.49504304, 0.49502343, 0.0], Float32[0.0, 0.49502006, 0.49504304, 0.49506977, 0.4950906, 0.49510905, 0.4951372, 0.49516848, 0.4951854, 0.49521717  …  0.5048262, 0.5048374, 0.50485975, 0.504894, 0.5049157, 0.5049239, 0.50495696, 0.5049766, 1.0, 1.0]), (Float32[1.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5  …  0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5], Float32[0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5  …  0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1.0])))), boundary_conditions = ((DirichletBC{Nothing}(nothing), DirichletBC{Nothing}(nothing)), (DirichletBC{Nothing}(nothing), DirichletBC{Nothing}(nothing))), Re = 3752.933f0, bodyforce = nothing, issteadybodyforce = false, closure_model = nothing, backend = CPU(false), workgroupsize = 64, temperature = (α1 = 0.00026645826f0, α2 = 1.0f0, α3 = 0.00026645826f0, α4 = 0.0003752933f0, γ = 1.0f0, dodissipation = true, boundary_conditions = ((SymmetricBC(), SymmetricBC()), (DirichletBC{Float32}(1.0f0), DirichletBC{Float32}(0.0f0))), gdir = 2)), IncompressibleNavierStokes.fieldplot, 20, true, nothing, false, nothing, Base.Pairs{Symbol, Any, NTuple{4, Symbol}, @NamedTuple{fieldname::Symbol, colorrange::Tuple{Float32, Float32}, size::Tuple{Int64, Int64}, colormap::Symbol}}(:fieldname => :temperature, :colorrange => (0.0f0, 1.0f0), :size => (600, 350), :colormap => :seaborn_icefire_gradient)), finalize = IncompressibleNavierStokes.var"#265#266"()), nusselt = (initialize = IncompressibleNavierStokes.var"#312#314"{@NamedTuple{grid::@NamedTuple{xlims::Tuple{Tuple{Float32, Float32}, Tuple{Float32, Float32}}, dimension::IncompressibleNavierStokes.Dimension{2}, N::Tuple{Int64, Int64}, Nu::Tuple{Tuple{Int64, Int64}, Tuple{Int64, Int64}}, Np::Tuple{Int64, Int64}, Iu::Tuple{CartesianIndices{2, Tuple{UnitRange{Int64}, UnitRange{Int64}}}, CartesianIndices{2, Tuple{UnitRange{Int64}, UnitRange{Int64}}}}, Ip::CartesianIndices{2, Tuple{UnitRange{Int64}, UnitRange{Int64}}}, x::Tuple{Vector{Float32}, Vector{Float32}}, xu::Tuple{Tuple{Vector{Float32}, Vector{Float32}}, Tuple{Vector{Float32}, Vector{Float32}}}, xp::Tuple{Vector{Float32}, Vector{Float32}}, Δ::Tuple{Vector{Float32}, Vector{Float32}}, Δu::Tuple{Vector{Float32}, Vector{Float32}}, A::Tuple{Tuple{Tuple{Vector{Float32}, Vector{Float32}}, Tuple{Vector{Float32}, Vector{Float32}}}, Tuple{Tuple{Vector{Float32}, Vector{Float32}}, Tuple{Vector{Float32}, Vector{Float32}}}}}, boundary_conditions::Tuple{Tuple{DirichletBC{Nothing}, DirichletBC{Nothing}}, Tuple{DirichletBC{Nothing}, DirichletBC{Nothing}}}, Re::Float32, bodyforce::Nothing, issteadybodyforce::Bool, closure_model::Nothing, backend::CPU, workgroupsize::Int64, temperature::@NamedTuple{α1::Float32, α2::Float32, α3::Float32, α4::Float32, γ::Float32, dodissipation::Bool, boundary_conditions::Tuple{Tuple{SymmetricBC, SymmetricBC}, Tuple{DirichletBC{Float32}, DirichletBC{Float32}}}, gdir::Int64}}, typeof(Main.nusseltplot), Int64, Bool, Nothing, Bool, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}}((grid = (xlims = ((0.0f0, 2.0f0), (0.0f0, 1.0f0)), dimension = IncompressibleNavierStokes.Dimension{2}(), N = (202, 102), Nu = ((199, 100), (200, 99)), Np = (200, 100), Iu = (CartesianIndices((2:200, 2:101)), CartesianIndices((2:201, 2:100))), Ip = CartesianIndices((2:201, 2:101)), x = (Float32[0.0, 0.0, 0.0044347644, 0.008958757, 0.0135733485, 0.01827985, 0.023079693, 0.027974367, 0.032965183, 0.038053393  …  1.9619466, 1.9670348, 1.9720256, 1.9769204, 1.9817202, 1.9864266, 1.9910412, 1.9955652, 2.0, 2.0], Float32[0.0, 0.0, 0.0044793785, 0.009139925, 0.013987184, 0.019026697, 0.024263948, 0.029704452, 0.03535363, 0.04121679  …  0.9587832, 0.96464634, 0.97029555, 0.975736, 0.9809733, 0.9860128, 0.9908601, 0.9955206, 1.0, 1.0]), xu = ((Float32[0.0, 0.0044347644, 0.008958757, 0.0135733485, 0.01827985, 0.023079693, 0.027974367, 0.032965183, 0.038053393, 0.043240547  …  1.9619466, 1.9670348, 1.9720256, 1.9769204, 1.9817202, 1.9864266, 1.9910412, 1.9955652, 2.0, 2.0], Float32[0.0, 0.0022396892, 0.006809652, 0.011563554, 0.01650694, 0.021645322, 0.0269842, 0.03252904, 0.03828521, 0.044257984  …  0.955742, 0.96171474, 0.96747094, 0.9730158, 0.9783547, 0.9834931, 0.98843646, 0.99319035, 0.9977603, 1.0]), (Float32[0.0, 0.0022173822, 0.0066967607, 0.011266053, 0.0159266, 0.020679772, 0.02552703, 0.030469775, 0.03550929, 0.04064697  …  1.959353, 1.9644907, 1.9695302, 1.974473, 1.9793203, 1.9840734, 1.9887339, 1.9933032, 1.9977826, 2.0], Float32[0.0, 0.0044793785, 0.009139925, 0.013987184, 0.019026697, 0.024263948, 0.029704452, 0.03535363, 0.04121679, 0.047299176  …  0.9587832, 0.96464634, 0.97029555, 0.975736, 0.9809733, 0.9860128, 0.9908601, 0.9955206, 1.0, 1.0])), xp = (Float32[0.0, 0.0022173822, 0.0066967607, 0.011266053, 0.0159266, 0.020679772, 0.02552703, 0.030469775, 0.03550929, 0.04064697  …  1.959353, 1.9644907, 1.9695302, 1.974473, 1.9793203, 1.9840734, 1.9887339, 1.9933032, 1.9977826, 2.0], Float32[0.0, 0.0022396892, 0.006809652, 0.011563554, 0.01650694, 0.021645322, 0.0269842, 0.03252904, 0.03828521, 0.044257984  …  0.955742, 0.96171474, 0.96747094, 0.9730158, 0.9783547, 0.9834931, 0.98843646, 0.99319035, 0.9977603, 1.0]), Δ = (Float32[1.1920929f-7, 0.0044347644, 0.0045239925, 0.0046145916, 0.004706502, 0.004799843, 0.004894674, 0.004990816, 0.00508821, 0.005187154  …  0.005187154, 0.00508821, 0.004990816, 0.0048947334, 0.004799843, 0.0047063828, 0.0046145916, 0.0045239925, 0.004434824, 1.1920929f-7], Float32[1.1920929f-7, 0.0044793785, 0.004660547, 0.0048472583, 0.005039513, 0.0052372515, 0.0054405034, 0.005649179, 0.00586316, 0.006082386  …  0.006082356, 0.00586313, 0.005649209, 0.0054404736, 0.0052372813, 0.005039513, 0.004847288, 0.004660487, 0.0044794083, 1.1920929f-7]), Δu = (Float32[0.0022173822, 0.0044793785, 0.004569292, 0.004660547, 0.0047531724, 0.0048472583, 0.004942745, 0.005039513, 0.005137682, 0.0052372515  …  0.005137682, 0.0050395727, 0.004942775, 0.004847288, 0.004753113, 0.004660487, 0.004569292, 0.0044794083, 0.002217412, 1.1920929f-7], Float32[0.0022396892, 0.0045699626, 0.0047539026, 0.0049433857, 0.0051383823, 0.0053388774, 0.0055448413, 0.0057561696, 0.005972773, 0.0061945915  …  0.005972743, 0.0057561994, 0.0055448413, 0.0053389072, 0.005138397, 0.004943371, 0.0047538877, 0.0045699477, 0.0022397041, 1.1920929f-7]), A = (((Float32[1.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5  …  0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5], Float32[0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5  …  0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1.0]), (Float32[1.0, 1.0, 0.5099108, 0.50981885, 0.5097228, 0.50962067, 0.50951755, 0.5094086, 0.50929356, 0.509176  …  0.49093604, 0.49081892, 0.4907065, 0.49058872, 0.4904881, 0.49038374, 0.49028164, 0.49017644, 0.49009407, 0.0], Float32[0.0, 0.49008918, 0.49018115, 0.49027717, 0.49037933, 0.49048245, 0.49059144, 0.49070647, 0.49082395, 0.49094325  …  0.5091811, 0.5092935, 0.5094113, 0.5095119, 0.50961626, 0.50971836, 0.50982356, 0.50990593, 1.0, 1.0])), ((Float32[1.0, 1.0, 0.50497997, 0.50495696, 0.50493026, 0.5049094, 0.5048909, 0.5048628, 0.50483155, 0.5048146  …  0.49520862, 0.4951738, 0.4951626, 0.49514025, 0.49510598, 0.4950843, 0.49507612, 0.49504304, 0.49502343, 0.0], Float32[0.0, 0.49502006, 0.49504304, 0.49506977, 0.4950906, 0.49510905, 0.4951372, 0.49516848, 0.4951854, 0.49521717  …  0.5048262, 0.5048374, 0.50485975, 0.504894, 0.5049157, 0.5049239, 0.50495696, 0.5049766, 1.0, 1.0]), (Float32[1.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5  …  0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5], Float32[0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5  …  0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1.0])))), boundary_conditions = ((DirichletBC{Nothing}(nothing), DirichletBC{Nothing}(nothing)), (DirichletBC{Nothing}(nothing), DirichletBC{Nothing}(nothing))), Re = 3752.933f0, bodyforce = nothing, issteadybodyforce = false, closure_model = nothing, backend = CPU(false), workgroupsize = 64, temperature = (α1 = 0.00026645826f0, α2 = 1.0f0, α3 = 0.00026645826f0, α4 = 0.0003752933f0, γ = 1.0f0, dodissipation = true, boundary_conditions = ((SymmetricBC(), SymmetricBC()), (DirichletBC{Float32}(1.0f0), DirichletBC{Float32}(0.0f0))), gdir = 2)), Main.nusseltplot, 20, true, nothing, false, nothing, Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}()), finalize = IncompressibleNavierStokes.var"#265#266"()), avg = (initialize = IncompressibleNavierStokes.var"#312#314"{@NamedTuple{grid::@NamedTuple{xlims::Tuple{Tuple{Float32, Float32}, Tuple{Float32, Float32}}, dimension::IncompressibleNavierStokes.Dimension{2}, N::Tuple{Int64, Int64}, Nu::Tuple{Tuple{Int64, Int64}, Tuple{Int64, Int64}}, Np::Tuple{Int64, Int64}, Iu::Tuple{CartesianIndices{2, Tuple{UnitRange{Int64}, UnitRange{Int64}}}, CartesianIndices{2, Tuple{UnitRange{Int64}, UnitRange{Int64}}}}, Ip::CartesianIndices{2, Tuple{UnitRange{Int64}, UnitRange{Int64}}}, x::Tuple{Vector{Float32}, Vector{Float32}}, xu::Tuple{Tuple{Vector{Float32}, Vector{Float32}}, Tuple{Vector{Float32}, Vector{Float32}}}, xp::Tuple{Vector{Float32}, Vector{Float32}}, Δ::Tuple{Vector{Float32}, Vector{Float32}}, Δu::Tuple{Vector{Float32}, Vector{Float32}}, A::Tuple{Tuple{Tuple{Vector{Float32}, Vector{Float32}}, Tuple{Vector{Float32}, Vector{Float32}}}, Tuple{Tuple{Vector{Float32}, Vector{Float32}}, Tuple{Vector{Float32}, Vector{Float32}}}}}, boundary_conditions::Tuple{Tuple{DirichletBC{Nothing}, DirichletBC{Nothing}}, Tuple{DirichletBC{Nothing}, DirichletBC{Nothing}}}, Re::Float32, bodyforce::Nothing, issteadybodyforce::Bool, closure_model::Nothing, backend::CPU, workgroupsize::Int64, temperature::@NamedTuple{α1::Float32, α2::Float32, α3::Float32, α4::Float32, γ::Float32, dodissipation::Bool, boundary_conditions::Tuple{Tuple{SymmetricBC, SymmetricBC}, Tuple{DirichletBC{Float32}, DirichletBC{Float32}}}, gdir::Int64}}, typeof(Main.averagetemp), Int64, Bool, Nothing, Bool, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}}((grid = (xlims = ((0.0f0, 2.0f0), (0.0f0, 1.0f0)), dimension = IncompressibleNavierStokes.Dimension{2}(), N = (202, 102), Nu = ((199, 100), (200, 99)), Np = (200, 100), Iu = (CartesianIndices((2:200, 2:101)), CartesianIndices((2:201, 2:100))), Ip = CartesianIndices((2:201, 2:101)), x = (Float32[0.0, 0.0, 0.0044347644, 0.008958757, 0.0135733485, 0.01827985, 0.023079693, 0.027974367, 0.032965183, 0.038053393  …  1.9619466, 1.9670348, 1.9720256, 1.9769204, 1.9817202, 1.9864266, 1.9910412, 1.9955652, 2.0, 2.0], Float32[0.0, 0.0, 0.0044793785, 0.009139925, 0.013987184, 0.019026697, 0.024263948, 0.029704452, 0.03535363, 0.04121679  …  0.9587832, 0.96464634, 0.97029555, 0.975736, 0.9809733, 0.9860128, 0.9908601, 0.9955206, 1.0, 1.0]), xu = ((Float32[0.0, 0.0044347644, 0.008958757, 0.0135733485, 0.01827985, 0.023079693, 0.027974367, 0.032965183, 0.038053393, 0.043240547  …  1.9619466, 1.9670348, 1.9720256, 1.9769204, 1.9817202, 1.9864266, 1.9910412, 1.9955652, 2.0, 2.0], Float32[0.0, 0.0022396892, 0.006809652, 0.011563554, 0.01650694, 0.021645322, 0.0269842, 0.03252904, 0.03828521, 0.044257984  …  0.955742, 0.96171474, 0.96747094, 0.9730158, 0.9783547, 0.9834931, 0.98843646, 0.99319035, 0.9977603, 1.0]), (Float32[0.0, 0.0022173822, 0.0066967607, 0.011266053, 0.0159266, 0.020679772, 0.02552703, 0.030469775, 0.03550929, 0.04064697  …  1.959353, 1.9644907, 1.9695302, 1.974473, 1.9793203, 1.9840734, 1.9887339, 1.9933032, 1.9977826, 2.0], Float32[0.0, 0.0044793785, 0.009139925, 0.013987184, 0.019026697, 0.024263948, 0.029704452, 0.03535363, 0.04121679, 0.047299176  …  0.9587832, 0.96464634, 0.97029555, 0.975736, 0.9809733, 0.9860128, 0.9908601, 0.9955206, 1.0, 1.0])), xp = (Float32[0.0, 0.0022173822, 0.0066967607, 0.011266053, 0.0159266, 0.020679772, 0.02552703, 0.030469775, 0.03550929, 0.04064697  …  1.959353, 1.9644907, 1.9695302, 1.974473, 1.9793203, 1.9840734, 1.9887339, 1.9933032, 1.9977826, 2.0], Float32[0.0, 0.0022396892, 0.006809652, 0.011563554, 0.01650694, 0.021645322, 0.0269842, 0.03252904, 0.03828521, 0.044257984  …  0.955742, 0.96171474, 0.96747094, 0.9730158, 0.9783547, 0.9834931, 0.98843646, 0.99319035, 0.9977603, 1.0]), Δ = (Float32[1.1920929f-7, 0.0044347644, 0.0045239925, 0.0046145916, 0.004706502, 0.004799843, 0.004894674, 0.004990816, 0.00508821, 0.005187154  …  0.005187154, 0.00508821, 0.004990816, 0.0048947334, 0.004799843, 0.0047063828, 0.0046145916, 0.0045239925, 0.004434824, 1.1920929f-7], Float32[1.1920929f-7, 0.0044793785, 0.004660547, 0.0048472583, 0.005039513, 0.0052372515, 0.0054405034, 0.005649179, 0.00586316, 0.006082386  …  0.006082356, 0.00586313, 0.005649209, 0.0054404736, 0.0052372813, 0.005039513, 0.004847288, 0.004660487, 0.0044794083, 1.1920929f-7]), Δu = (Float32[0.0022173822, 0.0044793785, 0.004569292, 0.004660547, 0.0047531724, 0.0048472583, 0.004942745, 0.005039513, 0.005137682, 0.0052372515  …  0.005137682, 0.0050395727, 0.004942775, 0.004847288, 0.004753113, 0.004660487, 0.004569292, 0.0044794083, 0.002217412, 1.1920929f-7], Float32[0.0022396892, 0.0045699626, 0.0047539026, 0.0049433857, 0.0051383823, 0.0053388774, 0.0055448413, 0.0057561696, 0.005972773, 0.0061945915  …  0.005972743, 0.0057561994, 0.0055448413, 0.0053389072, 0.005138397, 0.004943371, 0.0047538877, 0.0045699477, 0.0022397041, 1.1920929f-7]), A = (((Float32[1.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5  …  0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5], Float32[0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5  …  0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1.0]), (Float32[1.0, 1.0, 0.5099108, 0.50981885, 0.5097228, 0.50962067, 0.50951755, 0.5094086, 0.50929356, 0.509176  …  0.49093604, 0.49081892, 0.4907065, 0.49058872, 0.4904881, 0.49038374, 0.49028164, 0.49017644, 0.49009407, 0.0], Float32[0.0, 0.49008918, 0.49018115, 0.49027717, 0.49037933, 0.49048245, 0.49059144, 0.49070647, 0.49082395, 0.49094325  …  0.5091811, 0.5092935, 0.5094113, 0.5095119, 0.50961626, 0.50971836, 0.50982356, 0.50990593, 1.0, 1.0])), ((Float32[1.0, 1.0, 0.50497997, 0.50495696, 0.50493026, 0.5049094, 0.5048909, 0.5048628, 0.50483155, 0.5048146  …  0.49520862, 0.4951738, 0.4951626, 0.49514025, 0.49510598, 0.4950843, 0.49507612, 0.49504304, 0.49502343, 0.0], Float32[0.0, 0.49502006, 0.49504304, 0.49506977, 0.4950906, 0.49510905, 0.4951372, 0.49516848, 0.4951854, 0.49521717  …  0.5048262, 0.5048374, 0.50485975, 0.504894, 0.5049157, 0.5049239, 0.50495696, 0.5049766, 1.0, 1.0]), (Float32[1.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5  …  0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5], Float32[0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5  …  0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1.0])))), boundary_conditions = ((DirichletBC{Nothing}(nothing), DirichletBC{Nothing}(nothing)), (DirichletBC{Nothing}(nothing), DirichletBC{Nothing}(nothing))), Re = 3752.933f0, bodyforce = nothing, issteadybodyforce = false, closure_model = nothing, backend = CPU(false), workgroupsize = 64, temperature = (α1 = 0.00026645826f0, α2 = 1.0f0, α3 = 0.00026645826f0, α4 = 0.0003752933f0, γ = 1.0f0, dodissipation = true, boundary_conditions = ((SymmetricBC(), SymmetricBC()), (DirichletBC{Float32}(1.0f0), DirichletBC{Float32}(0.0f0))), gdir = 2)), Main.averagetemp, 50, true, nothing, false, nothing, Base.Pairs{Symbol, Union{}, Tuple{}, @NamedTuple{}}()), finalize = IncompressibleNavierStokes.var"#265#266"()), log = (initialize = IncompressibleNavierStokes.var"#268#270"{Bool, Bool, Bool, Bool, Bool, Int64}(false, true, true, true, true, 1000), finalize = IncompressibleNavierStokes.var"#265#266"()))

Solve equation

julia
state, outputs = solve_unsteady(;
    setup,
    ustart,
    tempstart,
    tlims = (T(0), T(20)),
    Δt = T(1e-2),
    processors,
);
[ Info: t = 10.0001	Δt = 0.01	umax = 0.24	itertime = 0.014
[ Info: t = 20.0004	Δt = 0.01	umax = 0.52	itertime = 0.012

Nusselt numbers

julia
outputs.nusselt

Average temperature

julia
outputs.avg

Copy-pasteable code

Below is the full code for this example stripped of comments and output.

julia
using GLMakie
using IncompressibleNavierStokes

outdir = joinpath(@__DIR__, "output", "RayleighBenard2D")

backend = CPU()

# using CUDA, CUDSS
# backend = CUDABackend()

function nusseltplot(state; setup)
    state isa Observable || (state = Observable(state))
    (; Δ, Δu) = setup.grid
    Δy1 = Δu[2][1:1] |> sum
    Δy2 = Δu[2][end-1:end-1] |> sum

    # Observe Nusselt numbers
    Nu1 = Observable(Point2f[])
    Nu2 = Observable(Point2f[])
    on(state) do (; temp, t)
        dTdy = @. (temp[:, 2] - temp[:, 1]) / Δy1
        Nu = sum((.-dTdy.*Δ[1])[2:end-1])
        push!(Nu1[], Point2f(t, Nu))
        dTdy = @. (temp[:, end-1] - temp[:, end-2]) / Δy2
        Nu = sum((.-dTdy.*Δ[1])[2:end-1])
        push!(Nu2[], Point2f(t, Nu))
        (Nu1, Nu2) .|> notify ## Update plot
    end

    # Plot Nu history
    fig = Figure()
    ax = Axis(fig[1, 1]; title = "Nusselt number", xlabel = "t", ylabel = "Nu")
    lines!(ax, Nu1; label = "Lower plate")
    lines!(ax, Nu2; label = "Upper plate")
    axislegend(ax)
    on(_ -> autolimits!(ax), Nu2)
    fig
end

function averagetemp(state; setup)
    state isa Observable || (state = Observable(state))
    (; xp, Δ, Ip) = setup.grid
    ix = Ip.indices[1]
    Ty = lift(state) do (; temp)
        Ty = sum(temp[ix, :] .* Δ[1][ix]; dims = 1) ./ sum(Δ[1][ix])
        Array(Ty)[:]
    end
    Ty0 = copy(Ty[])
    yy = Array(xp[2])
    fig = Figure()
    ax = Axis(fig[1, 1]; title = "Average temperature", xlabel = "T", ylabel = "y")
    lines!(ax, Ty0, yy; label = "t = 0")
    lines!(ax, Ty, yy; label = "t = t")
    axislegend(ax)
    on(_ -> autolimits!(ax), Ty)
    fig
end

T = Float32

temperature = temperature_equation(;
    Pr = T(0.71),
    Ra = T(1e7),
    Ge = T(1.0),
    dodissipation = true,
    boundary_conditions = (
        (SymmetricBC(), SymmetricBC()),
        (DirichletBC(T(1)), DirichletBC(T(0))),
    ),
    gdir = 2,
    nondim_type = 1,
)

n = 100
x = tanh_grid(T(0), T(2), 2n, T(1.2)), tanh_grid(T(0), T(1), n, T(1.2))
plotgrid(x...)

setup = Setup(;
    x,
    boundary_conditions = ((DirichletBC(), DirichletBC()), (DirichletBC(), DirichletBC())),
    Re = 1 / temperature.α1,
    temperature,
    backend,
);

ustart = velocityfield(setup, (dim, x, y) -> zero(x));
tempstart = temperaturefield(setup, (x, y) -> one(y) / 2 + max(sinpi(20 * x) / 100, 0));

GLMakie.closeall()
processors = (;
    rtp = realtimeplotter(;
        screen = GLMakie.Screen(),
        setup,
        fieldname = :temperature,
        colorrange = (T(0), T(1)),
        size = (600, 350),
        colormap = :seaborn_icefire_gradient,
        nupdate = 20,
    ),
    nusselt = realtimeplotter(;
        screen = GLMakie.Screen(),
        setup,
        plot = nusseltplot,
        nupdate = 20,
    ),
    avg = realtimeplotter(;
        screen = GLMakie.Screen(),
        setup,
        plot = averagetemp,
        nupdate = 50,
    ),
    log = timelogger(; nupdate = 1000),
)

state, outputs = solve_unsteady(;
    setup,
    ustart,
    tempstart,
    tlims = (T(0), T(20)),
    Δt = T(1e-2),
    processors,
);

outputs.nusselt

outputs.avg

This page was generated using Literate.jl.