Thermosolutal convection of a Navier-Stokes fluid in a rectangle

Thermosolutal convection of a Navier-Stokes fluid in a rectangle#

\[\begin{split} \mathbb{S} \begin{cases} \Omega = [0, \mathcal{A}X] \times [0, X] & \text{aspect ratio } \mathcal{A}=\mathcal{O}(1)\\ \textbf{e}_g=-\textbf{e}_y & \text{vertically downward gravity} \\ \rho(c, \theta) = c - \beta\theta & \text{constitutive relation} \\ c_0(x,y)=y+\mathcal{N}(x,y) & \text{perturbed diffusive base state} \\ \theta_0(x,y)=1-y+\mathcal{N}(x,y) \\ \textbf{u}_0 = \textbf{0} \\ p_0 = 0 \\ c_{\text{D}}(x,y=0)=0 & \text{prescribed concentration on upper and lower boundaries} \\ c_{\text{D}}(x,y=1)=1 \\ \theta_{\text{D}}(x,y=0)=1 & \text{prescribed temperature on upper and lower boundaries} \\ \theta_{\text{D}}(x,y=1)=0 \\ c_{\text{N}}(x=0,y)=0 & \text{no-flux on left and right boundaries}\\ c_{\text{N}}(x=L_x,y)=0 \\ \theta_{\text{N}}(x=0,y)=0 & \\ \theta_{\text{N}}(x=L_x,y)=0 \\ \textbf{u}_{\text{E}}\vert_{\partial\Omega}=\textbf{0} & \text{no-flow on entire boundary} \end{cases} \end{split}\]
from lucifex.sim import run
from lucifex.utils import as_indices
from lucifex.viz import (
    plot_line, create_animation, plot_colormap,
    save_figure, display_animation, plot_colormap_multifigure,
)
from lucifex.solver import maximum
from py.C03_navier_stokes_thermosolutal import navier_stokes_thermosolutal_rectangle

simulation = navier_stokes_thermosolutal_rectangle(
    aspect=2.0,
    Nx=64,
    Ny=64,
    Ra=5e4,
    beta=2.0,
    Le=10.0,
    dt_max=0.01, 
)

n_stop = 400
dt_init = 1e-6 
n_init = 10
run(simulation, n_stop=n_stop, dt_init=dt_init, n_init=n_init)

c, theta, rho, u = simulation['c', 'theta', 'rho', 'u']
mesh = c.mesh
title_triplet = lambda time_triplet, tex_triplet: (
    tuple(f'${n}(t={t:.6f})$' for t, n in zip(time_triplet, tex_triplet))
)
series_triplet = (c, theta, rho)
tex_triplet = ('c', '\\theta', '\\rho')
time_slice = slice(0, None, 2)
time_triplet_series = [ti for ti in zip(*[s.time_series[time_slice] for s in series_triplet])]

anim = create_animation(
    plot_colormap_multifigure(n_cols=3, colorbar=False),
    cmaps=('hot', 'magma', 'plasma'),
)(
    [ui for ui in zip(*[s.series[time_slice] for s in series_triplet])],
    titles=[title_triplet(i, tex_triplet) for i in time_triplet_series],
)
anim_path = save_figure('c(x,y,t)_theta(x,y,t)_rho(x,y,t)', get_path=True)(anim)

display_animation(anim_path)
time_index = -1
time_triplet = tuple(u.time_series[time_index] for u in series_triplet)

fig, *axes = plot_colormap_multifigure(n_cols=3, colorbar=True)(
    [u.series[time_index] for u in series_triplet],
    ('hot', 'magma', 'plasma'),
    titles=title_triplet(time_triplet, tex_triplet),
)
save_figure(f'c(x,y,t={time_triplet[0]})_theta(x,y,t={time_triplet[1]})_rho(x,y,t={time_triplet[2]})')(fig)
../../_images/ae8dd6987c0026f3e7b223566f2c0565b7eea4ad90cef725e6d21eb1cf2b3325.png
time_indices = as_indices(rho.time_series, (0, 0.5, -1), fraction=True)
for i in time_indices:
    fig, ax = plot_colormap(rho.series[i], 'plasma', title=f'$c(t={rho.time_series[i]:.3f})$')
    save_figure(f'c(x,y,t={rho.time_series[i]:.3f})', thumbnail=(i == -1))(fig)
../../_images/1a2da186a34dd6530110fb450ec4daf74fcdea3a5375cc237300edc53573d108.png ../../_images/bb3f3265cea031826d601f7dfcb5bd184c2eefa6b5611917d4915102673daa2d.png ../../_images/94cab4971c9e06f53278aaae400036f4fb104a1cef1c0405d7702b51c1f73984.png
uMax = [maximum(i) for i in u.series]
fig, ax = plot_line(
    (u.time_series, uMax), 
    x_label='$t$', 
    y_label='$\max_{\\textbf{x}}|\\textbf{u}|$',
)
save_figure('uMax(t)')(fig)
../../_images/a845a43ba1668a7e2fec56a36bd030c993b56ab185152206a11d493794a864a3.png