LES Models API

Types

Abstract Types

abstract type SGSModel end
abstract type EddyViscosityModel <: SGSModel end

SmagorinskyModel

Tarang.SmagorinskyModelType
SmagorinskyModel{T, N, A, Arch}

Classic Smagorinsky (1963) subgrid-scale model.

Mathematical Formulation

The eddy viscosity is:

νₑ = (Cₛ Δ)² |S̄|

where:

  • Cₛ is the Smagorinsky constant (typically 0.1-0.2)
  • Δ is the filter width (grid spacing)
  • |S̄| = √(2 S̄ᵢⱼ S̄ᵢⱼ) is the strain rate magnitude

Fields

  • C_s::T: Smagorinsky constant
  • filter_width::NTuple{N, T}: Filter width in each direction (Δx, Δy, ...)
  • eddy_viscosity::A: Cached eddy viscosity field (Array or CuArray)
  • strain_magnitude::A: Cached |S̄| field
  • architecture::Arch: CPU() or GPU() architecture

Example

# Create model for 256³ domain with Δ = 2π/256
model = SmagorinskyModel(
    C_s = 0.17,
    filter_width = (2π/256, 2π/256, 2π/256),
    field_size = (256, 256, 256)
)

# Create GPU model
model_gpu = SmagorinskyModel(
    C_s = 0.17,
    filter_width = (2π/256, 2π/256, 2π/256),
    field_size = (256, 256, 256),
    architecture = GPU()
)

# Compute eddy viscosity from velocity gradients
compute_eddy_viscosity!(model, ∂u∂x, ∂u∂y, ∂u∂z, ∂v∂x, ∂v∂y, ∂v∂z, ∂w∂x, ∂w∂y, ∂w∂z)

# Access the result
νₑ = get_eddy_viscosity(model)
source

Classic Smagorinsky (1963) subgrid-scale model.

Type signature:

mutable struct SmagorinskyModel{T<:AbstractFloat, N} <: EddyViscosityModel

Fields:

FieldTypeDescription
C_sTSmagorinsky constant
filter_widthNTuple{N, T}Filter width (Δx, Δy, Δz)
effective_deltaTEffective Δ = (Δx Δy Δz)^(1/N)
eddy_viscosityArray{T, N}νₑ field
strain_magnitudeArray{T, N}|S̄| field
field_sizeNTuple{N, Int}Grid dimensions

Constructor:

SmagorinskyModel(;
    C_s = 0.17,
    filter_width::NTuple{N, Real},
    field_size::NTuple{N, Int},
    dtype = Float64
)

AMDModel

Tarang.AMDModelType
AMDModel{T, N, A, Arch}

Anisotropic Minimum Dissipation model (Rozema et al., 2015).

Mathematical Formulation

The eddy viscosity is:

νₑ = max(0, νₑ†)

where the predictor is:

νₑ† = -C (Δₖ² ∂uᵢ/∂xₖ ∂uⱼ/∂xₖ Sᵢⱼ) / (∂uₘ/∂xₙ ∂uₘ/∂xₙ)

Key features:

  • Uses anisotropic filter widths Δₖ in each direction
  • Automatically switches off in laminar/transitional regions
  • Provides minimum dissipation required for subgrid energy transfer
  • No explicit filtering or test-filtering required

Fields

  • C::T: Poincaré constant (model constant)
  • filter_width::NTuple{N, T}: Anisotropic filter widths (Δx, Δy, Δz)
  • eddy_viscosity::A: Cached eddy viscosity field (Array or CuArray)
  • eddy_diffusivity::A: Cached eddy diffusivity (for scalars)
  • architecture::Arch: CPU() or GPU() architecture

Model Constant Recommendations

DiscretizationC
Spectral methods1/12 ≈ 0.0833
4th-order finite difference0.212
2nd-order finite difference0.3

Example

# Create AMD model for anisotropic grid
model = AMDModel(
    C = 1/12,  # Spectral method
    filter_width = (2π/256, 2π/256, 2π/64),  # Anisotropic
    field_size = (256, 256, 64)
)

# Create GPU AMD model
model_gpu = AMDModel(
    C = 1/12,
    filter_width = (2π/256, 2π/256, 2π/64),
    field_size = (256, 256, 64),
    architecture = GPU()
)

# Compute eddy viscosity
compute_eddy_viscosity!(model, ∂u∂x, ∂u∂y, ∂u∂z, ∂v∂x, ∂v∂y, ∂v∂z, ∂w∂x, ∂w∂y, ∂w∂z)

References

Rozema, W., Bae, H.J., Moin, P., Verstappen, R. (2015). "Minimum-dissipation models for large-eddy simulation", Physics of Fluids 27, 085107.

source

Anisotropic Minimum Dissipation model (Rozema et al., 2015).

Type signature:

mutable struct AMDModel{T<:AbstractFloat, N} <: EddyViscosityModel

Fields:

FieldTypeDescription
CTPoincaré constant
filter_widthNTuple{N, T}Anisotropic filter widths
filter_width_sqNTuple{N, T}Δₖ² for each direction
eddy_viscosityArray{T, N}νₑ field
eddy_diffusivityArray{T, N}κₑ field (for scalars)
field_sizeNTuple{N, Int}Grid dimensions
clip_negativeBoolWhether to clip νₑ < 0

Constructor:

AMDModel(;
    C = 1/12,
    filter_width::NTuple{N, Real},
    field_size::NTuple{N, Int},
    clip_negative = true,
    dtype = Float64
)

Eddy Viscosity Computation

computeeddyviscosity!

Tarang.compute_eddy_viscosity!Function
compute_eddy_viscosity!(model::SmagorinskyModel, velocity_gradients...)

Compute eddy viscosity from velocity gradient components.

GPU-aware: Uses broadcasting for GPU arrays, optimized SIMD loops for CPU.

2D Case

compute_eddy_viscosity!(model, ∂u∂x, ∂u∂y, ∂v∂x, ∂v∂y)

3D Case

compute_eddy_viscosity!(model, ∂u∂x, ∂u∂y, ∂u∂z, ∂v∂x, ∂v∂y, ∂v∂z, ∂w∂x, ∂w∂y, ∂w∂z)
source
compute_eddy_viscosity!(model::AMDModel, velocity_gradients...)

Compute AMD eddy viscosity from velocity gradient components.

GPU-aware: Uses broadcasting for GPU arrays, optimized SIMD loops for CPU.

2D Case

compute_eddy_viscosity!(model, ∂u∂x, ∂u∂y, ∂v∂x, ∂v∂y)

3D Case

compute_eddy_viscosity!(model, ∂u∂x, ∂u∂y, ∂u∂z, ∂v∂x, ∂v∂y, ∂v∂z, ∂w∂x, ∂w∂y, ∂w∂z)

The AMD formula uses anisotropic scaling: νₑ† = -C (Δₖ² ∂uᵢ/∂xₖ ∂uⱼ/∂xₖ Sᵢⱼ) / (∂uₘ/∂xₙ ∂uₘ/∂xₙ)

source

Compute eddy viscosity from velocity gradient components.

2D Signature:

compute_eddy_viscosity!(model, ∂u∂x, ∂u∂y, ∂v∂x, ∂v∂y)

3D Signature:

compute_eddy_viscosity!(model,
    ∂u∂x, ∂u∂y, ∂u∂z,
    ∂v∂x, ∂v∂y, ∂v∂z,
    ∂w∂x, ∂w∂y, ∂w∂z
)

Returns: The eddy viscosity array model.eddy_viscosity

computeeddydiffusivity!

Tarang.compute_eddy_diffusivity!Function
compute_eddy_diffusivity!(model::AMDModel, velocity_gradients..., scalar_gradients...)

Compute eddy diffusivity for scalar transport using AMD model.

GPU-aware: Uses broadcasting for GPU arrays, optimized SIMD loops for CPU.

For a scalar field b with gradient ∇b, the eddy diffusivity is:

κₑ = max(0, κₑ†)

where: κₑ† = -C (Δₖ² ∂v/∂xₖ ∂b/∂xₖ) / (∂b/∂xₙ ∂b/∂xₙ)

For 2D flows, v is the vertical velocity component. For 3D flows (buoyancy-driven), w is the vertical velocity.

source

Compute eddy diffusivity for scalar transport (AMD model only).

compute_eddy_diffusivity!(model::AMDModel,
    ∂w∂x, ∂w∂y, ∂w∂z,
    ∂b∂x, ∂b∂y, ∂b∂z
)

Returns: The eddy diffusivity array model.eddy_diffusivity


Subgrid Stress

computesgsstress

Tarang.compute_sgs_stressFunction
compute_sgs_stress(model::EddyViscosityModel, strain_components...)

Compute the deviatoric subgrid stress tensor:

τᵢⱼᵈ = -2 νₑ S̄ᵢⱼ

GPU-aware: Uses broadcasting which works for both CPU and GPU arrays.

2D Output

Returns (τ11, τ12, τ22).

3D Output

Returns (τ11, τ12, τ13, τ22, τ23, τ33).

source

Compute deviatoric SGS stress tensor τᵢⱼ = -2 νₑ S̄ᵢⱼ.

2D Signature:

compute_sgs_stress(model, S11, S12, S22) -> (τ11, τ12, τ22)

3D Signature:

compute_sgs_stress(model, S11, S12, S13, S22, S23, S33)
    -> (τ11, τ12, τ13, τ22, τ23, τ33)

Accessors

geteddyviscosity

Return the current eddy viscosity field.

get_eddy_viscosity(model::EddyViscosityModel) -> Array{T, N}

geteddydiffusivity

Return the current eddy diffusivity field (AMD only).

get_eddy_diffusivity(model::AMDModel) -> Array{T, N}

getfilterwidth

Return the filter width tuple.

get_filter_width(model::EddyViscosityModel) -> NTuple{N, T}

Statistics

meaneddyviscosity

Compute domain-averaged eddy viscosity.

mean_eddy_viscosity(model::EddyViscosityModel) -> T

maxeddyviscosity

Return maximum eddy viscosity in the domain.

max_eddy_viscosity(model::EddyViscosityModel) -> T

Dissipation Rate

sgs_dissipation

Tarang.sgs_dissipationFunction
sgs_dissipation(model::EddyViscosityModel, strain_magnitude::AbstractArray)

Compute the subgrid-scale dissipation rate:

εₛₛ = 2 νₑ |S̄|²

GPU-aware: Uses broadcasting which works for both CPU and GPU arrays. Returns the dissipation field.

source

Compute SGS dissipation rate field: εₛₛ = 2 νₑ |S̄|²

sgs_dissipation(model::EddyViscosityModel, strain_magnitude) -> Array{T, N}

meansgsdissipation

Tarang.mean_sgs_dissipationFunction
mean_sgs_dissipation(model::EddyViscosityModel, strain_magnitude::AbstractArray)

Compute domain-averaged SGS dissipation rate. GPU-aware: Uses broadcasting and sum() which work for both CPU and GPU arrays.

source

Compute domain-averaged SGS dissipation rate.

mean_sgs_dissipation(model::EddyViscosityModel, strain_magnitude) -> T

Configuration

set_constant!

Tarang.set_constant!Function
set_constant!(model::SmagorinskyModel, C_s::Real)

Update the Smagorinsky constant.

source
set_constant!(model::AMDModel, C::Real)

Update the AMD Poincaré constant.

source

Update the model constant.

set_constant!(model::SmagorinskyModel, C_s::Real)
set_constant!(model::AMDModel, C::Real)

reset!

Reset eddy viscosity (and diffusivity for AMD) to zero.

reset!(model::EddyViscosityModel)
reset!(model::AMDModel)  # Also resets eddy_diffusivity

Exports

export SGSModel, EddyViscosityModel
export SmagorinskyModel, AMDModel
export compute_eddy_viscosity!, compute_eddy_diffusivity!
export compute_sgs_stress
export get_eddy_viscosity, get_eddy_diffusivity, get_filter_width
export mean_eddy_viscosity, max_eddy_viscosity
export reset!, set_constant!
export sgs_dissipation, mean_sgs_dissipation

Index