Operators
All discrete operators are built using KernelAbstractions.jl and Cartesian indices, similar to WaterLily.jl. This allows for dimension- and backend-agnostic code. See this blog post for how to write kernels. IncompressibleNavierStokes previously relied on assembling sparse operators to perform the same operations. While being very efficient and also compatible with CUDA (CUSPARSE), storing these matrices in memory is expensive for large 3D problems.
IncompressibleNavierStokes.Offset
— Typee = Offset{D}()
Cartesian index unit vector in D = 2
or D = 3
dimensions. Calling e(α)
returns a Cartesian index with 1
in the dimension α
and zeros elsewhere.
See https://b-fg.github.io/2023/05/07/waterlily-on-gpu.html for writing kernel loops using Cartesian indices.
IncompressibleNavierStokes.avg
— FunctionAverage scalar field ϕ
in the α
-direction.
IncompressibleNavierStokes.divergence!
— Functiondivergence!(div, u, setup)
Compute divergence of velocity field (in-place version).
IncompressibleNavierStokes.divergence
— Functiondivergence(u, setup)
Compute divergence of velocity field.
IncompressibleNavierStokes.vorticity
— Functionvorticity(u, setup)
Compute vorticity field.
IncompressibleNavierStokes.vorticity!
— Functionvorticity!(ω, u, setup)
Compute vorticity field.
IncompressibleNavierStokes.convection!
— Functionconvection!(F, u, setup)
Compute convective term.
IncompressibleNavierStokes.diffusion!
— Functiondiffusion!(F, u, setup)
Compute diffusive term.
IncompressibleNavierStokes.bodyforce!
— Functionbodyforce!(F, u, t, setup)
Compute body force.
IncompressibleNavierStokes.momentum!
— Functionmomentum!(F, u, temp, t, setup)
Right hand side of momentum equations, excluding pressure gradient. Put the result in $F$.
IncompressibleNavierStokes.momentum
— Functionmomentum(u, temp, t, setup)
Right hand side of momentum equations, excluding pressure gradient.
IncompressibleNavierStokes.laplacian!
— Functionlaplacian!(L, p, setup)
Compute Laplacian of pressure field (in-place version).
IncompressibleNavierStokes.laplacian
— Functionlaplacian(p, setup)
Compute Laplacian of pressure field.
IncompressibleNavierStokes.pressuregradient!
— Functionpressuregradient!(G, p, setup)
Compute pressure gradient (in-place).
IncompressibleNavierStokes.pressuregradient
— Functionpressuregradient(p, setup)
Compute pressure gradient.
IncompressibleNavierStokes.interpolate_u_p
— Functioninterpolate_u_p(u, setup)
Interpolate velocity to pressure points.
IncompressibleNavierStokes.interpolate_u_p!
— Functioninterpolate_u_p!(up, u, setup)
Interpolate velocity to pressure points.
IncompressibleNavierStokes.interpolate_ω_p
— Functioninterpolate_ω_p(ω, setup)
Interpolate vorticity to pressure points.
IncompressibleNavierStokes.interpolate_ω_p!
— Functioninterpolate_ω_p!(ωp, ω, setup)
Interpolate vorticity to pressure points.
IncompressibleNavierStokes.Dfield!
— FunctionDfield!(d, G, p, setup; ϵ = eps(eltype(p)))
Compute the $D$-field [9] given by
\[D = \frac{2 | \nabla p |}{\nabla^2 p}.\]
IncompressibleNavierStokes.Dfield
— FunctionDfield(p, setup; kwargs...)
Compute the $D$-field.
IncompressibleNavierStokes.Qfield!
— FunctionQfield!(Q, u, setup)
Compute $Q$-field [10] given by
\[Q = - \frac{1}{2} \sum_{α, β} \frac{\partial u^α}{\partial x^β} \frac{\partial u^β}{\partial x^α}.\]
IncompressibleNavierStokes.Qfield
— FunctionQfield(u, setup)
Compute the $Q$-field.
IncompressibleNavierStokes.eig2field!
— Functioneig2field!(λ, u, setup; ϵ = eps(eltype(λ)))
Compute the second eigenvalue of $S^2 + \Omega^2$, as proposed by Jeong and Hussain [10].
IncompressibleNavierStokes.eig2field
— Functioneig2field(u, setup)
Compute the second eigenvalue of $S^2 + \Omega^2$, as proposed by Jeong and Hussain [10].
IncompressibleNavierStokes.kinetic_energy
— Functionkinetic_energy(u, setup; kwargs...)
Compute kinetic energy field $e$ (out-of-place version).
IncompressibleNavierStokes.kinetic_energy!
— Functionkinetic_energy!(k, u, setup; interpolate_first = false)
Compute kinetic energy field $k$ (in-place version). If interpolate_first
is true, it is given by
\[e_I = \frac{1}{8} \sum_\alpha (u^\alpha_{I + \delta(\alpha) / 2} + u^\alpha_{I - \delta(\alpha) / 2})^2.\]
Otherwise, it is given by
\[e_I = \frac{1}{4} \sum_\alpha (u^\alpha_{I + \delta(\alpha) / 2}^2 + u^\alpha_{I - \delta(\alpha) / 2}^2),\]
as in [11].
IncompressibleNavierStokes.total_kinetic_energy
— Functiontotal_kinetic_energy(setup, u; kwargs...)
Compute total kinetic energy. The velocity components are interpolated to the volume centers and squared.
IncompressibleNavierStokes.tensorbasis
— Functiontensorbasis(u, setup)
Compute symmetry tensor basis T[1]
-T[11]
and invariants V[1]
-V[5]
.
IncompressibleNavierStokes.divoftensor!
— Functiondivoftensor!(s, σ, setup)
Compute divergence of a tensor with all components in the pressure points. The stress tensors should be precomputed and stored in σ
.
IncompressibleNavierStokes.tensorbasis!
— Functiontensorbasis!(B, V, u, setup)
Compute symmetry tensor basis B[1]
-B[11]
and invariants V[1]
-V[5]
, as specified in [12] in equations (9) and (11). Note that B[1]
corresponds to $T_0$ in the paper, and V
to $I$.