SUPG advection-diffusion-reaction of a rotating pulse in a rectangle

SUPG advection-diffusion-reaction of a rotating pulse in a rectangle#

Donea, J. & Huerta, A. (2003). Finite Element Methods for Flow Problems. \(\S 5.6.2\)

\[\begin{split} \mathbb{S}_u \begin{cases} \Omega = [0, 1] \times [0, 1] \\ u_0(x) = 0 \\ u_{\text{D}}=0 \\ \textbf{a} = (L_y/2-y)\textbf{e}_x + (x-L_x/2)\textbf{e}_y \\ \mathsf{D}=D\mathsf{I} \\ R = 0 \\ J(x,y,t) = e^{-t^{10}}\cos(\pi/2\sqrt{x^2+y^2})\text{H}(1-\sqrt{x^2+y^2})\\ \end{cases} \end{split}\]
import numpy as np
from ufl import SpatialCoordinate, as_vector
from lucifex.mesh import rectangle_mesh
from lucifex.fem import Constant, Function
from lucifex.fdm import (
    BE, CN, advective_timestep, 
    FiniteDifference, FunctionSeries, ConstantSeries, finite_difference_order,
)
from lucifex.solver import ibvp , BoundaryConditions, evaluation, extrema
from lucifex.sim import Simulation, run
from lucifex.plt import (
    plot_streamlines, plot_line, save_figure, 
    plot_colormap, plot_colormap_multifigure,
)
from lucifex.pde.advection_diffusion import advection_diffusion_reaction

def source_amplitude(t) -> float:
    return np.exp(-float(t)**10)

def create_simulation(
    tau: str | None,
    Lx: float, 
    Ly: float,
    Nx: int,
    Ny: int,
    dt: float,
    d: float,
    D_adv: FiniteDifference,
    D_diff: FiniteDifference,
    D_src: FiniteDifference,
) -> Simulation:
    order = finite_difference_order(D_adv, D_diff, D_src)
    mesh = rectangle_mesh(Lx, Ly, Nx, Ny)
    radius = lambda x: np.sqrt(x[0]**2 + x[1]**2)
    t = ConstantSeries(mesh, name='t', ics=0.0)
    dt = Constant(mesh, dt, name='dt')
    x = SpatialCoordinate(mesh)
    a = as_vector((0.5 * Ly -x[1], x[0] - 0.5 * Lx))
    d = Constant(mesh, d, name='d')
    u = FunctionSeries(
        (mesh, 'P', 1), 
        name='u', 
        order=order, 
        store=1, 
        ics=0.0,
    )
    uMinMax = ConstantSeries(
        mesh, 
        name='uMinMax', 
        order=order,
        shape=(2,),
        store=1,
    )
    jt = ConstantSeries(
        mesh, 
        name='jt', 
        order=order,
        store=1,
        ics=source_amplitude(0.0),
    )
    jxy = Function(
        (mesh, 'P', 1),
        lambda x: 0.0 + np.cos(0.5 * np.pi * radius(x)) * (radius(x) <= 1.0), 
        name='jxy',   
    )
    jt_solver = evaluation(jt, source_amplitude, future=True)(t[1])
    bcs = BoundaryConditions(
        ('dirichlet', lambda x: x[0], 0.0),
        ('dirichlet', lambda x: x[0] - Lx, 0.0),
        ('dirichlet', lambda x: x[1], 0.0),
        ('dirichlet', lambda x: x[1] - Ly, 0.0),
    )
    u_solver = ibvp(advection_diffusion_reaction, bcs=bcs)(
        u, dt, a, d, j=D_src(jt) * jxy, D_adv=D_adv, D_diff=D_diff, tau=tau,
    )
    uMinMax_solver = evaluation(uMinMax, extrema)(u[0])
    solvers = (jt_solver, u_solver, uMinMax_solver)
    auxiliary = (('a', a), d, jxy)
    return Simulation(solvers, t, dt, auxiliary)


Lx = 1.0
Ly = 1.0
Nx = 40
Ny = 40
hx = Lx / Nx
hy = Ly / Ny
hMin = min(hx, hx)

d = 1e-5
aMax = np.sqrt(Lx**2 + Ly**2)
courant = 1.0
dt = advective_timestep(aMax, hMin, courant)

D_adv = CN
D_diff = CN
D_src = BE

tau_opts = ('coth', 'shakib', 'codina', 'transient', None) 
simulations: dict[None | str, Simulation] = {}

for tau in tau_opts:
    simulations[tau] = create_simulation(
        tau, Lx, Ly, Nx, Ny, dt, d, D_adv, D_diff, D_src,
    )

n_stop = 300
for tau in tau_opts:
    run(simulations[tau], n_stop)
time_indices = (1, 20, 30, 50, 200, -1)

for tau in tau_opts:
    sim = simulations[tau]
    u, uMinMax = sim['u', 'uMinMax']
    if tau is None:
        tau_title = 'unstabilized'
    elif tau in ('shakib', 'codina'):
        tau_title = tau.capitalize()
    else:
        tau_title = str(tau)
    mfig, *_ = plot_colormap_multifigure(
        n_rows=2, 
        cbars=True, 
        suptitle=tau_title,
    )(
        [u.series[i] for i in time_indices],
        title=[f'$u(t={u.time_series[i]:.3f})$' for i in time_indices],
    )
    save_figure(f'u(x,y,t)_{tau}')(fig)
    fig, ax = plot_line(
        (uMinMax.time_series, uMinMax.value_series), 
        cyc='black',
        x_label='$t$',
        legend_labels=['$\min_{\\mathbf{x}}u$', '$\max_{\\mathbf{x}}u$'],
        title=tau_title,
    )
    save_figure(f'uMinMax(t)_{tau}', thumbnail=(tau == tau_opts[0]))(fig)
    if tau is None:
        a, jxy, jt = sim['a', 'jxy', 'jt']
        fig, ax = plot_colormap(jxy, title=f'$J(t=0)$')
        plot_streamlines(fig, ax, a, mesh=u.function_space.mesh, density=0.75, color='cyan')
        fig, ax = plot_line(
            (jt.time_series, jt.value_series),
            x_label='$t$',
            y_label='$\max_{\\mathbf{x}}J$',
        )
../../_images/5588c3829df904fd4c16698159828803ee9b93b3a58890f9f454c62b7c36ea24.png ../../_images/a2a31e3e8149551e4e31d23700c70846b8d2074b5123f820017fb31e0c04e4fa.png ../../_images/cf86b73a80e28e0034996b0d0376a5408201c36c2c38a417b57971295f4a0868.png ../../_images/caf7e405b634afa1af9d3b62b9edeeca6fa0debe70eb9ec9c60a9838a909d8e6.png ../../_images/14c260b03fc9620ee5cc591752eecae7566599ebcae8347737adbe0475403e50.png ../../_images/708e282dd07509460bd6715cbfbda5162d3e087cf4407cde1aa15565c0d2c7d5.png ../../_images/d1fc1e2f71bbfa4027c3d055b5e83f1ca9980cfe38246986791af92c0b310563.png ../../_images/13557bbb455d5782e0ff82f7d604c7c9e326a64951d8a0abb1d65855dbb760d1.png ../../_images/f73684e1f0bd860e4b2a82e205db547a6e897cb39eff04792953556251479e38.png ../../_images/6b83bd09a5a9c42302f9771c166809ecec31a92a6076235f5d6b5ad5adc5056e.png ../../_images/7b9d86e19e3ec784db9fafd80f1b18f5a625ff59765751f79228fda7c23a74fb.png ../../_images/378cbd694e8cdda1896c7b473606542084a11b94aae107eabc16c030a9816d15.png
The Kernel crashed while executing code in the current cell or a previous cell. 

Please review the code in the cell(s) to identify a possible cause of the failure. 

Click <a href='https://aka.ms/vscodeJupyterKernelCrash'>here</a> for more info. 

View Jupyter <a href='command:jupyter.viewOutput'>log</a> for further details.