Thermosolutal convection of a Navier-Stokes fluid in a rectangle

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

\[\begin{split} \mathbb{S}_{\mathbf{u},p,c,\theta} \begin{cases} \Omega = [0, \mathcal{A}X] \times [0, X] & \text{aspect ratio } \mathcal{A}=\mathcal{O}(1)\\ c_0(x,y)=y+\mathcal{N}(x,y) & \text{perturbed initial linear concentration} \\ \theta_0(x,y)=1-y+\mathcal{N}(x,y) & \text{perturbed initial linear temperature} \\ \textbf{u}_0=\textbf{0} & \text{static initial velocity} \\ p_0=0 & \text{static initial pressure} \\ c_{\text{D}}(x,y=0)=0 & \text{light lower boundary} \\ c_{\text{D}}(x,y=X)=1 & \text{heavy upper boundary} \\ \theta_{\text{D}}(x,y=0)=1 & \text{hot lower boundary} \\ \theta_{\text{D}}(x,y=X)=0 & \text{cold upper boundary} \\ c_{\text{N}}(x=0,y)=0 & \text{no-solutal-flux on left boundary}\\ c_{\text{N}}(x=\mathcal{A}X,y)=0 & \text{no-solutal-flux on right boundary}\\ \theta_{\text{N}}(x=0,y)=0 & \text{no-thermal-flux on left boundary}\\ \theta_{\text{N}}(x=\mathcal{A}X,y)=0 & \text{no-thermal-flux on right boundary}\\ \textbf{u}_{\text{E}}\vert_{\partial\Omega}=\textbf{0} & \text{no-flow on entire boundary} \\ \rho(c, \theta) = c - \gamma\theta & \text{linear density} \\ \textbf{e}_g=-\textbf{e}_y & \text{vertically downward gravity} \\ \end{cases} \end{split}\]
from lucifex.sim import run
from lucifex.utils.npy_utils import as_index
from lucifex.plt import (
    plot_line, create_animation, plot_colormap,
    save_figure, display_animation, plot_colormap_multifigure,
)
from lucifex.solver import maximum
from py.C31_navier_stokes_thermosolutal import navier_stokes_thermosolutal_rectangle

simulation = navier_stokes_thermosolutal_rectangle(
    aspect=2.0,
    Nx=64,
    Ny=64,
    Ra=5e4,
    gamma=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, cbars=False),
    cmap=('magma', 'plasma', 'hot'),
)(
    [ui for ui in zip(*[s.series[time_slice] for s in series_triplet])],
    title=[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)', return_path=True)(anim)

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

mfig, *_ = plot_colormap_multifigure(n_cols=3, cbars=True)(
    [u.series[time_index] for u in series_triplet],
    ('hot', 'magma', 'plasma'),
    title=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/eda738eaa307d1d481e0971a981926fb2d5af9124dc46d200bd6fe68cef91742.png
time_indices = as_index(rho.time_series, (0, 0.5, -1), fraction=True)
for i in time_indices:
    fig, ax = plot_colormap(rho.series[i], title=f'$\\rho(t={rho.time_series[i]:.3f})$')
    save_figure(f'rho(x,y,t={rho.time_series[i]:.3f})', thumbnail=(i == -1))(fig)
../../_images/cea6e31c527fcdd26635e3f8eaf95d8baab748878f79ee1eb367c0eb954c275e.png ../../_images/90a700e46dd746d48f1b24c5a0cb558a248f93b86ce25654e219371da3686cfd.png ../../_images/c21df86b59ee5ec3ce3cd6d46d56e2ae2d3b5e711b1f1b54b8758d5b30f4cc31.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/cbc86526d5ca834816b986e487672d41f58844af571e95ec15bcb829752252c4.png