Quick Start: Scalar Transport

This notebook demonstrates a minimal transient scalar transport setup: a Gaussian pulse advected through a 2D channel using HDG with BDF2 time integration.

[1]:
import numpy as np
import ngsolve as ngs
from dream.mesh import get_rectangular_mesh
from dream.scalar_transport import ScalarTransportSolver, transportfields
from dream.scalar_transport.config import FarField, Initial

ngs.SetNumThreads(12)
[2]:
# Build a simple channel mesh
nx = np.linspace(0.0, 4.0, 41)
ny = np.linspace(-0.5, 0.5, 11)
mesh = get_rectangular_mesh(
    [("channel", (nx, ny))],
    [("inflow",  (np.array([0.0]), ny)),
     ("outflow", (np.array([4.0]), ny)),
     ("wall",    (nx, np.array([-0.5]))),
     ("wall",    (nx, np.array([ 0.5])))],
)
[3]:
solver = ScalarTransportSolver(mesh)

# Physical parameters
solver.convection_velocity   = ngs.CF((1.0, 0.0))
solver.diffusion_coefficient = 1e-3

# Discretisation
solver.fem            = 'hdg'
solver.fem.order      = 3
solver.riemann_solver = 'lax_friedrich'

# Time integration
solver.time                = 'transient'
solver.fem.scheme          = 'bdf2'
solver.time.timer.interval = (0.0, 2.0)
solver.time.timer.step     = 5e-3

# Boundary and initial conditions
Uinf = transportfields(u=0.0)
U0   = transportfields(u=ngs.exp(-50 * (ngs.y**2)))

solver.bcs['inflow']  = FarField(fields=U0)
solver.bcs['outflow'] = FarField(fields=Uinf)
solver.dcs['channel'] = Initial(fields=transportfields(u=0.0))

# with ngs.TaskManager():
#     # Sets up finite element spaces, assembles bilinear forms and applies boundary conditions
#     solver.initialize()
#     # Runs the time-stepping loop defined by solver.time
#     solver.solve()