13: Parabolic terms

Experimental support for parabolic diffusion terms is available in Trixi.jl. This demo illustrates parabolic terms for the advection-diffusion equation.

using OrdinaryDiffEqLowStorageRKusing Trixi

Splitting a system into hyperbolic and parabolic parts

For a mixed hyperbolic-parabolic system, we represent the hyperbolic and parabolic parts of the system separately. We first define the hyperbolic (advection) part of the advection-diffusion equation.

advection_velocity = (1.5, 1.0)equations_hyperbolic = LinearScalarAdvectionEquation2D(advection_velocity);

Next, we define the parabolic diffusion term. The constructor requires knowledge of equations_hyperbolic to be passed in because the LaplaceDiffusion2D applies diffusion to every variable of the hyperbolic system.

diffusivity = 5.0e-2equations_parabolic = LaplaceDiffusion2D(diffusivity, equations_hyperbolic);

Boundary conditions

As with the equations, we define boundary conditions separately for the hyperbolic and parabolic part of the system. For this example, we impose inflow BCs for the hyperbolic system (no condition is imposed on the outflow), and we impose Dirichlet boundary conditions for the parabolic equations. Both BoundaryConditionDirichlet and BoundaryConditionNeumann are defined for LaplaceDiffusion2D.

The hyperbolic and parabolic boundary conditions are assumed to be consistent with each other.

boundary_condition_zero_dirichlet = BoundaryConditionDirichlet((x, t, equations) -> SVector(0.0))boundary_conditions_hyperbolic = (;                                  x_neg = BoundaryConditionDirichlet((x, t, equations) -> SVector(1 +                                                                                                  0.5 *                                                                                                  x[2])),                                  y_neg = boundary_condition_zero_dirichlet,                                  y_pos = boundary_condition_do_nothing,                                  x_pos = boundary_condition_do_nothing)boundary_conditions_parabolic = (;                                 x_neg = BoundaryConditionDirichlet((x, t, equations) -> SVector(1 +                                                                                                 0.5 *                                                                                                 x[2])),                                 y_neg = boundary_condition_zero_dirichlet,                                 y_pos = boundary_condition_zero_dirichlet,                                 x_pos = boundary_condition_zero_dirichlet);

Defining the solver and mesh

The process of creating the DG solver and mesh is the same as for a purely hyperbolic system of equations.

solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs)coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y))coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y))mesh = TreeMesh(coordinates_min, coordinates_max,                initial_refinement_level = 4,                periodicity = false)initial_condition = (x, t, equations) -> SVector(0.0);

Semidiscretizing and solving

To semidiscretize a hyperbolic-parabolic system, we create a SemidiscretizationHyperbolicParabolic. This differs from a SemidiscretizationHyperbolic in that we pass in a Tuple containing both the hyperbolic and parabolic equation, as well as a Tuple containing the hyperbolic and parabolic boundary conditions.

semi = SemidiscretizationHyperbolicParabolic(mesh,                                             (equations_hyperbolic, equations_parabolic),                                             initial_condition, solver;                                             boundary_conditions = (boundary_conditions_hyperbolic,                                                                    boundary_conditions_parabolic))
┌──────────────────────────────────────────────────────────────────────────────────────────────────┐
│ SemidiscretizationHyperbolicParabolic                                                            │
│ ═════════════════════════════════════                                                            │
│ #spatial dimensions: ……………………………………… 2                                                           │
│ mesh: ……………………………………………………………………………… TreeMesh{2, Trixi.SerialTree{2, Float64}} with length 341   │
│ hyperbolic equations: …………………………………… LinearScalarAdvectionEquation2D                             │
│ parabolic equations: ……………………………………… LaplaceDiffusion2D                                          │
│ initial condition: …………………………………………… #7                                                          │
│ source terms: ………………………………………………………… nothing                                                     │
│ source terms parabolic: ……………………………… nothing                                                     │
│ solver: ………………………………………………………………………… DG                                                          │
│ parabolic solver: ……………………………………………… ParabolicFormulationBassiRebay1                             │
│ total #DOFs per field: ………………………………… 4096                                                        │
└──────────────────────────────────────────────────────────────────────────────────────────────────┘

The rest of the code is identical to the hyperbolic case. We create a system of ODEs through semidiscretize, defining callbacks, and then passing the system to OrdinaryDiffEq.jl.

tspan = (0.0, 1.5)ode = semidiscretize(semi, tspan)callbacks = CallbackSet(SummaryCallback())time_int_tol = 1.0e-6sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol,            ode_default_options()..., callback = callbacks);

████████╗██████╗ ██╗██╗  ██╗██╗
╚══██╔══╝██╔══██╗██║╚██╗██╔╝██║
   ██║   ██████╔╝██║ ╚███╔╝ ██║
   ██║   ██╔══██╗██║ ██╔██╗ ██║
   ██║   ██║  ██║██║██╔╝ ██╗██║
   ╚═╝   ╚═╝  ╚═╝╚═╝╚═╝  ╚═╝╚═╝

┌──────────────────────────────────────────────────────────────────────────────────────────────────┐
│ SemidiscretizationHyperbolicParabolic                                                            │
│ ═════════════════════════════════════                                                            │
│ #spatial dimensions: ……………………………………… 2                                                           │
│ mesh: ……………………………………………………………………………… TreeMesh{2, Trixi.SerialTree{2, Float64}} with length 341   │
│ hyperbolic equations: …………………………………… LinearScalarAdvectionEquation2D                             │
│ parabolic equations: ……………………………………… LaplaceDiffusion2D                                          │
│ initial condition: …………………………………………… #7                                                          │
│ source terms: ………………………………………………………… nothing                                                     │
│ source terms parabolic: ……………………………… nothing                                                     │
│ solver: ………………………………………………………………………… DG                                                          │
│ parabolic solver: ……………………………………………… ParabolicFormulationBassiRebay1                             │
│ total #DOFs per field: ………………………………… 4096                                                        │
└──────────────────────────────────────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────────────────────────────────────────┐
│ TreeMesh{2, Trixi.SerialTree{2, Float64}}                                                        │
│ ═════════════════════════════════════════                                                        │
│ center: ………………………………………………………………………… [0.0, 0.0]                                                  │
│ length: ………………………………………………………………………… 2.0                                                         │
│ periodicity: …………………………………………………………… (false, false)                                              │
│ current #cells: …………………………………………………… 341                                                         │
│ #leaf-cells: …………………………………………………………… 256                                                         │
│ current capacity: ……………………………………………… 341                                                         │
└──────────────────────────────────────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────────────────────────────────────────┐
│ LinearScalarAdvectionEquation2D                                                                  │
│ ═══════════════════════════════                                                                  │
│ #variables: ……………………………………………………………… 1                                                           │
│ │ variable 1: ………………………………………………………… scalar                                                      │
└──────────────────────────────────────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────────────────────────────────────────┐
│ DG{Float64}                                                                                      │
│ ═══════════                                                                                      │
│ basis: …………………………………………………………………………… LobattoLegendreBasis{Float64}(polydeg=3)                    │
│ mortar: ………………………………………………………………………… LobattoLegendreMortarL2{Float64}(polydeg=3)                 │
│ surface integral: ……………………………………………… SurfaceIntegralWeakForm                                     │
│ │ surface flux: …………………………………………………… FluxLaxFriedrichs(max_abs_speed)                            │
│ volume integral: ………………………………………………… VolumeIntegralWeakForm                                      │
└──────────────────────────────────────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Time integration                                                                                 │
│ ════════════════                                                                                 │
│ Start time: ……………………………………………………………… 0.0                                                         │
│ Final time: ……………………………………………………………… 1.5                                                         │
│ time integrator: ………………………………………………… RDPK3SpFSAL49                                               │
│ adaptive: …………………………………………………………………… true                                                        │
│ abstol: ………………………………………………………………………… 1.0e-6                                                      │
│ reltol: ………………………………………………………………………… 1.0e-6                                                      │
│ controller: ……………………………………………………………… PIDController(beta=(0.38, -0.…er=default_dt_factor_limiter) │
└──────────────────────────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Environment information                                                                          │
│ ═══════════════════════                                                                          │
│ #threads: …………………………………………………………………… 1                                                           │
│ threading backend: …………………………………………… polyester                                                   │
└──────────────────────────────────────────────────────────────────────────────────────────────────┘
                                         Trixi.jl
───────────────────────────────────────────────────────────────────────────────────────────
                                                 Time                   Allocations        
                                        ──────────────────────    ────────────────────────
           Tot / % measured:                73.6ms / 96.8%             115KiB / 9.8%
 ─────────────────────────────────────  ──────────────────────    ────────────────────────
 Section                        ncalls    time    %tot     avg      alloc    %tot      avg
───────────────────────────────────────────────────────────────────────────────────────────
 parabolic rhs!                  1.20k  50.4ms   70.7%  42.0μs    7.19KiB   64.0%    6.13B
 ├─ calculate gradient           1.20k  26.9ms   37.7%  22.4μs    2.62KiB   23.4%    2.24B
 │  ├─ volume integral           1.20k  14.7ms   20.6%  12.2μs          ∅       ∅        ∅
 │  ├─ Jacobian                  1.20k  4.72ms    6.6%  3.93μs          ∅       ∅        ∅
 │  ├─ surface integral          1.20k  3.35ms    4.7%  2.79μs          ∅       ∅        ∅
 │  ├─ prolong2interfaces        1.20k  1.21ms    1.7%  1.01μs          ∅       ∅        ∅
 │  ├─ interface flux            1.20k  1.06ms    1.5%   884ns          ∅       ∅        ∅
 │  ├─ reset gradients           1.20k   816μs    1.1%   680ns          ∅       ∅        ∅
 │  ├─ ~calculate gradient~      1.20k   687μs    1.0%   572ns    2.62KiB   23.4%    2.24B
 │  ├─ prolong2boundaries        1.20k   177μs    0.2%   147ns          ∅       ∅        ∅
 │  ├─ boundary flux             1.20k   111μs    0.2%  92.5ns          ∅       ∅        ∅
 │  ├─ prolong2mortars           1.20k  38.1μs    0.1%  31.8ns          ∅       ∅        ∅
 │  └─ mortar flux               1.20k  36.1μs    0.1%  30.1ns          ∅       ∅        ∅
 ├─ volume integral              1.20k  15.7ms   22.0%  13.1μs          ∅       ∅        ∅
 ├─ calculate parabolic fluxes   1.20k  1.71ms    2.4%  1.42μs          ∅       ∅        ∅
 ├─ prolong2interfaces           1.20k  1.31ms    1.8%  1.09μs          ∅       ∅        ∅
 ├─ surface integral             1.20k  1.18ms    1.7%   983ns          ∅       ∅        ∅
 ├─ interface flux               1.20k  1.03ms    1.4%   861ns          ∅       ∅        ∅
 ├─ ~parabolic rhs!~             1.20k   937μs    1.3%   781ns    4.56KiB   40.6%    3.89B
 ├─ transform variables          1.20k   749μs    1.1%   624ns          ∅       ∅        ∅
 ├─ boundary flux                1.20k   242μs    0.3%   201ns          ∅       ∅        ∅
 ├─ Jacobian                     1.20k   215μs    0.3%   179ns          ∅       ∅        ∅
 ├─ reset ∂u/∂t                  1.20k   187μs    0.3%   156ns          ∅       ∅        ∅
 ├─ prolong2boundaries           1.20k   153μs    0.2%   128ns          ∅       ∅        ∅
 ├─ prolong2mortars              1.20k  38.4μs    0.1%  32.0ns          ∅       ∅        ∅
 ├─ mortar flux                  1.20k  36.4μs    0.1%  30.4ns          ∅       ∅        ∅
 └─ source terms parabolic       1.20k  27.3μs    0.0%  22.7ns          ∅       ∅        ∅
 rhs_hyperbolic!                 1.20k  20.9ms   29.3%  17.4μs    4.05KiB   36.0%    3.45B
 ├─ volume integral              1.20k  15.2ms   21.4%  12.7μs          ∅       ∅        ∅
 ├─ interface flux               1.20k  1.76ms    2.5%  1.47μs          ∅       ∅        ∅
 ├─ surface integral             1.20k  1.18ms    1.6%   980ns          ∅       ∅        ∅
 ├─ prolong2interfaces           1.20k   988μs    1.4%   823ns          ∅       ∅        ∅
 ├─ ~rhs_hyperbolic!~            1.20k   732μs    1.0%   610ns    4.05KiB   36.0%    3.45B
 ├─ boundary flux                1.20k   360μs    0.5%   300ns          ∅       ∅        ∅
 ├─ Jacobian                     1.20k   217μs    0.3%   181ns          ∅       ∅        ∅
 ├─ reset ∂u/∂t                  1.20k   191μs    0.3%   159ns          ∅       ∅        ∅
 ├─ prolong2boundaries           1.20k   136μs    0.2%   113ns          ∅       ∅        ∅
 ├─ mortar flux                  1.20k  38.5μs    0.1%  32.1ns          ∅       ∅        ∅
 ├─ prolong2mortars              1.20k  37.1μs    0.1%  30.9ns          ∅       ∅        ∅
 └─ source terms                 1.20k  26.7μs    0.0%  22.2ns          ∅       ∅        ∅
───────────────────────────────────────────────────────────────────────────────────────────

We can now visualize the solution, which develops a boundary layer at the outflow boundaries.

using Plotsplot(sol)
Example block output

Package versions

These results were obtained using the following versions.

using InteractiveUtilsversioninfo()using PkgPkg.status(["Trixi", "OrdinaryDiffEqLowStorageRK", "Plots"],           mode = PKGMODE_MANIFEST)
Julia Version 1.10.12
Commit d93beab124c (2026-08-15 10:29 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 4 × AMD EPYC 9V45 96-Core Processor
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-15.0.7 (ORCJIT, generic)
Threads: 1 default, 0 interactive, 1 GC (on 4 virtual cores)
Environment:
  JULIA_PKG_SERVER_REGISTRY_PREFERENCE = eager
Status `~/work/Trixi.jl/Trixi.jl/docs/Manifest.toml`
  [b0944070] OrdinaryDiffEqLowStorageRK v3.4.0
  [91a5bcdd] Plots v1.41.7
  [a7f1ee26] Trixi v0.17.12 `~/work/Trixi.jl/Trixi.jl`

This page was generated using Literate.jl.