Skip to content

Add simple SGS to Adami and Morris Viscosity #753

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 45 commits into from
Jun 13, 2025
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
9657150
add sgs
svchb Apr 9, 2025
f3dde2b
Merge remote-tracking branch 'origin/main' into sgs
svchb Apr 9, 2025
639be87
update
svchb Apr 9, 2025
365c160
fix
svchb Apr 9, 2025
1c9e306
remove
svchb Apr 9, 2025
19451d8
fix doc
svchb Apr 9, 2025
22d62ea
fix
svchb Apr 9, 2025
6d7bec4
fixes
svchb Apr 9, 2025
5f90bf7
typo
svchb Apr 9, 2025
2963202
tpo
svchb Apr 9, 2025
82c9e9b
format
svchb Apr 9, 2025
183d413
Merge branch 'main' into sgs
svchb Apr 11, 2025
cbdadd5
Merge branch 'main' into sgs
svchb Apr 17, 2025
4f208f9
Merge branch 'main' into sgs
svchb May 6, 2025
5ff0c74
add explanation
svchb May 6, 2025
77bf5ef
adjust tests
svchb May 6, 2025
a288da5
Merge remote-tracking branch 'upstream/main' into sgs
svchb May 12, 2025
bad1954
add to validation setup for wcsph
svchb May 13, 2025
a48ca7d
Merge branch 'main' into sgs
svchb May 13, 2025
bea7af6
review fixes
svchb May 13, 2025
fa6df69
Update taylor_green_vortex_2d.jl
svchb May 14, 2025
0458976
Update validation_taylor_green_vortex_2d.jl
svchb May 14, 2025
de606e1
Update dam_break_2d.jl
svchb May 14, 2025
c45fdb6
fix and add citations
svchb May 14, 2025
a1920a5
Merge branch 'main' into sgs
svchb May 14, 2025
41938af
add news
svchb May 14, 2025
1716f99
Merge branch 'sgs' of https://github.com/svchb/TrixiParticles.jlOpen …
svchb May 14, 2025
8e83d5b
Merge branch 'main' into sgs
svchb May 16, 2025
af656b6
implement suggestions
svchb May 21, 2025
6a14443
format
svchb May 21, 2025
646b496
Merge branch 'main' into sgs
svchb May 21, 2025
639a5a4
Merge branch 'main' into sgs
svchb May 21, 2025
0ee856e
rename viscosity
svchb May 22, 2025
df12585
Merge branch 'main' into sgs
svchb May 22, 2025
f038002
too much renaming
svchb May 22, 2025
5643d86
Merge branch 'sgs' of https://github.com/svchb/TrixiParticles.jlOpen …
svchb May 22, 2025
2e9c7ff
Merge branch 'main' into sgs
svchb May 22, 2025
9c9186f
implement suggestions
svchb May 23, 2025
507138a
Merge branch 'main' into sgs
svchb May 26, 2025
7436332
Merge branch 'main' into sgs
efaulhaber May 28, 2025
1f72f09
Merge branch 'main' into sgs
svchb May 28, 2025
2f3bbbb
Update validation_taylor_green_vortex_2d.jl
svchb May 28, 2025
1d19cef
Merge branch 'main' into sgs
LasNikas Jun 12, 2025
1188a9a
Merge branch 'main' into sgs
svchb Jun 13, 2025
6a83b83
fix tests again
svchb Jun 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ used in the Julia ecosystem. Notable changes will be documented in this file for

### Features

- New Viscosity model 'ViscosityMorrisSGS' and 'ViscosityAdamiSGS' were added which use simplified Smagorinsky type SGS (#753).
- New viscosity models `ViscosityMorrisSGS` and `ViscosityAdamiSGS` were added, which use a simplified Smagorinsky-type SGS (#753).

- With all CPU backends, a new array type is used for the integration array, which defines
broadcasting to be multithreaded, leading to speedups of up to 5x with large thread counts
Expand Down
16 changes: 15 additions & 1 deletion docs/src/refs.bib
Original file line number Diff line number Diff line change
Expand Up @@ -756,4 +756,18 @@ @inproceedings{Lilly1967
pages = {195--210},
year = {1967},
doi = {10.5065/D62R3PMM}
}
}

@article{Zhu2021,
author = {Zhu, Yujie and Zhang, Chi and Yu, Yongchuan and Hu, Xiangyu},
journal = {Journal of Hydrodynamics},
title = {A {CAD}-compatible body-fitted particle generator for arbitrarily complex geometry and its application to wave-structure interaction},
year = {2021},
issn = {1878-0342},
month = apr,
number = {2},
pages = {195--206},
volume = {33},
doi = {10.1007/s42241-021-0031-y},
publisher = {Springer Science and Business Media LLC}
}
14 changes: 7 additions & 7 deletions examples/fluid/dam_break_2d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ smoothing_kernel = WendlandC2Kernel{2}()

fluid_density_calculator = ContinuityDensity()
alpha = 0.02
viscosity = ArtificialViscosityMonaghan(alpha=alpha, beta=0.0)
viscosity_fluid = ArtificialViscosityMonaghan(alpha=alpha, beta=0.0)
# A typical formula to convert Artificial viscosity to a
# kinematic viscosity is provided by Monaghan as
# nu = alpha * smoothing_length * sound_speed/8
Expand All @@ -57,10 +57,10 @@ viscosity = ArtificialViscosityMonaghan(alpha=alpha, beta=0.0)
# nu = 1.0e-6

# This allows the use of a physical viscosity model like:
# viscosity = ViscosityAdami(nu=nu)
# viscosity_fluid = ViscosityAdami(nu=nu)
# or with additional dissipation through a Smagorinsky model
# viscosity = ViscosityAdamiSGS(nu=nu)
# For more details see the documentation [Viscosity model overview](@ref viscosity_sph).
# viscosity_fluid = ViscosityAdamiSGS(nu=nu)
# For more details see the documentation "Viscosity model overview".

# Alternatively the density diffusion model by Molteni & Colagrossi can be used,
# which will run faster.
Expand All @@ -69,7 +69,7 @@ density_diffusion = DensityDiffusionAntuono(tank.fluid, delta=0.1)

fluid_system = WeaklyCompressibleSPHSystem(tank.fluid, fluid_density_calculator,
state_equation, smoothing_kernel,
smoothing_length, viscosity=viscosity,
smoothing_length, viscosity=viscosity_fluid,
density_diffusion=density_diffusion,
acceleration=(0.0, -gravity), correction=nothing,
surface_tension=nothing,
Expand All @@ -80,8 +80,8 @@ fluid_system = WeaklyCompressibleSPHSystem(tank.fluid, fluid_density_calculator,
boundary_density_calculator = AdamiPressureExtrapolation()
viscosity_wall = nothing
# For a no-slip condition the corresponding wall viscosity without SGS can be set
#viscosity_wall = ViscosityAdami(nu=nu)
#viscosity_wall = ViscosityMorris(nu=nu)
# viscosity_wall = ViscosityAdami(nu=nu)
# viscosity_wall = ViscosityMorris(nu=nu)
boundary_model = BoundaryModelDummyParticles(tank.boundary.density, tank.boundary.mass,
state_equation=state_equation,
boundary_density_calculator,
Expand Down
2 changes: 1 addition & 1 deletion examples/fluid/dam_break_2phase_2d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ water_viscosity = ViscosityMorris(nu=nu_sim_water)

trixi_include(@__MODULE__, joinpath(examples_dir(), "fluid", "dam_break_2d.jl"),
sol=nothing, fluid_particle_spacing=fluid_particle_spacing,
viscosity=water_viscosity, smoothing_length=smoothing_length,
viscosity_fluid=water_viscosity, smoothing_length=smoothing_length,
gravity=gravity, tspan=tspan, density_diffusion=nothing,
sound_speed=sound_speed, exponent=7,
tank_size=(floor(5.366 * H / fluid_particle_spacing) * fluid_particle_spacing,
Expand Down
3 changes: 2 additions & 1 deletion examples/fluid/dam_break_oil_film_2d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ oil_viscosity = ViscosityMorris(nu=nu_sim_oil)
# TODO: broken if both systems use surface tension
trixi_include(@__MODULE__, joinpath(examples_dir(), "fluid", "dam_break_2d.jl"),
sol=nothing, fluid_particle_spacing=fluid_particle_spacing, tspan=tspan,
viscosity=ViscosityMorris(nu=nu_sim_water), smoothing_length=smoothing_length,
viscosity_fluid=ViscosityMorris(nu=nu_sim_water),
smoothing_length=smoothing_length,
gravity=gravity, density_diffusion=nothing, sound_speed=sound_speed,
prefix="", reference_particle_spacing=fluid_particle_spacing)

Expand Down
4 changes: 2 additions & 2 deletions examples/fluid/hydrostatic_water_column_2d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ smoothing_length = 1.2 * fluid_particle_spacing
smoothing_kernel = SchoenbergCubicSplineKernel{2}()

alpha = 0.02
viscosity = ArtificialViscosityMonaghan(alpha=alpha, beta=0.0)
viscosity_fluid = ArtificialViscosityMonaghan(alpha=alpha, beta=0.0)

fluid_density_calculator = ContinuityDensity()

# This is to set acceleration with `trixi_include`
system_acceleration = (0.0, -gravity)
fluid_system = WeaklyCompressibleSPHSystem(tank.fluid, fluid_density_calculator,
state_equation, smoothing_kernel,
smoothing_length, viscosity=viscosity,
smoothing_length, viscosity=viscosity_fluid,
acceleration=system_acceleration,
source_terms=nothing)

Expand Down
77 changes: 35 additions & 42 deletions src/schemes/fluid/viscosity.jl
Original file line number Diff line number Diff line change
Expand Up @@ -245,32 +245,32 @@ by incorporating a subgrid-scale (SGS) eddy viscosity via a Smagorinsky-type [Sm
The effective kinematic viscosity is defined as

```math
\nu_{\mathrm{eff}} = \nu_{\\mathrm{std}} + \nu_{\\mathrm{SGS}},
\nu_{\text{eff}} = \nu_{\text{std}} + \nu_{\text{SGS}},
```

with

```math
\nu_{\mathrm{SGS}} = (C_S * h)^2 * |S|,
\nu_{\text{SGS}} = (C_S h)^2 |S|,
```

and an approximation for the strain rate magnitude given by

```math
|S| \approx \frac{\|v_a - v_b\|}{\|r_a - r_b\| + \epsilon},
|S| \approx \frac{\|v_ab\|}{\|r_ab\| + \epsilon},
```

where:
- $C_S$ is the Smagorinsky constant (typically 0.1 to 0.2),
- $h$ is the local smoothing length, and
- ``C_S`` is the Smagorinsky constant (typically 0.1 to 0.2),
- ``h`` is the local smoothing length.

The effective dynamic viscosities are then computed as
```math
\eta_{a,\mathrm{eff}} = \rho_a\, \nu_{\mathrm{eff}},
\eta_{a,\text{eff}} = \rho_a\, \nu_{\text{eff}},
```
and averaged as
```math
\bar{\eta}_{ab} = \frac{2 \eta_{a,\mathrm{eff}} \eta_{b,\mathrm{eff}}}{\eta_{a,\mathrm{eff}}+\eta_{b,\mathrm{eff}}}.
\bar{\eta}_{ab} = \frac{2 \eta_{a,\text{eff}} \eta_{b,\text{eff}}}{\eta_{a,\text{eff}}+\eta_{b,\text{eff}}}.
```

This model is appropriate for turbulent flows where unresolved scales contribute additional dissipation.
Expand All @@ -281,12 +281,11 @@ This model is appropriate for turbulent flows where unresolved scales contribute
- `epsilon=0.01`: Parameter to prevent singularities
"""
struct ViscosityAdamiSGS{ELTYPE}
nu::ELTYPE # kinematic viscosity [e.g., 1e-6 m²/s]
C_S::ELTYPE # Smagorinsky constant [e.g., 0.1-0.2]
epsilon::ELTYPE # Epsilon for singularity prevention [e.g., 0.001]
nu :: ELTYPE # kinematic viscosity [e.g., 1e-6 m²/s]
C_S :: ELTYPE # Smagorinsky constant [e.g., 0.1-0.2]
epsilon :: ELTYPE # Epsilon for singularity prevention [e.g., 0.001]
end

# Convenient constructor with default values for C_S and epsilon.
ViscosityAdamiSGS(; nu, C_S=0.1, epsilon=0.001) = ViscosityAdamiSGS(nu, C_S, epsilon)

@propagate_inbounds function (viscosity::ViscosityAdamiSGS)(particle_system,
Expand Down Expand Up @@ -322,9 +321,9 @@ ViscosityAdamiSGS(; nu, C_S=0.1, epsilon=0.001) = ViscosityAdamiSGS(nu, C_S, eps
#
# In SPH, one could compute ∂ᵢvⱼ via kernel gradients, but this is costly.
# A common low-order surrogate is to approximate the strain‐rate magnitude by a
# finite-difference along each particle pair:
# finite difference along each particle pair:
#
# |S| ≈ ‖vₐ–v_b‖ / (‖rₐ–r_b‖ + δ),
# |S| ≈ ‖v_ab‖ / (‖r_ab‖ + δ),
#
# where δ regularizes the denominator to avoid singularities when particles are very close.
#
Expand Down Expand Up @@ -354,24 +353,36 @@ end
ViscosityMorrisSGS(; nu, C_S=0.1, epsilon=0.001)

Subgrid-scale (SGS) viscosity model based on the formulation by [Morris (1997)](@cite Morris1997),
extended with a Smagorinsky-type eddy viscosity term [Smagorinsky (1963)](@cite Smagorinsky1963) for modeling turbulent flows.
by incorporating a subgrid-scale (SGS) eddy viscosity via a Smagorinsky-type [Smagorinsky (1963)](@cite Smagorinsky1963) closure.
The effective kinematic viscosity is defined as

```math
\nu_{\text{eff}} = \nu_{\text{std}} + \nu_{\text{SGS}},
```

with

The acceleration on particle `a` due to viscosity interaction with particle `b` is calculated as:
```math
\frac{d v_a}{dt} = \sum_b m_b \frac{\mu_{a,\mathrm{eff}} + \mu_{b,\mathrm{eff}}}{\rho_a \rho_b} \frac{r_{ab} \cdot \nabla_a W_{ab}}{r_{ab}^2 + \epsilon h_{ab}^2} v_{ab}
where $v_{ab} = v_a - v_b$, $r_{ab} = r_a - r_b$, $r_{ab} = \|r_{ab}\|$, $h_{ab} = (h_a + h_b)/2$, $W_{ab}$ is the smoothing kernel, $\rho$ is density, $m$ is mass, and $\epsilon$ is a regularization parameter.
\nu_{\text{SGS}} = (C_S h)^2 |S|,
```

and an approximation for the strain rate magnitude given by

The effective dynamic viscosity $\mu_{i,\mathrm{eff}}$ for each particle `i` (a or b) includes both the standard molecular viscosity and an SGS eddy viscosity contribution:
```math
\mu_{i,\mathrm{eff}} = \rho_i \nu_{i,\mathrm{eff}} = \rho_i (\nu_{\mathrm{std}} + \nu_{i,\mathrm{SGS}})
|S| \approx \frac{\|v_ab\|}{\|r_ab\| + \epsilon},
```
The standard kinematic viscosity $\nu_{\mathrm{std}}$ is provided by the `nu` parameter. The SGS kinematic viscosity is calculated using the Smagorinsky model:

where:
- ``C_S`` is the Smagorinsky constant (typically 0.1 to 0.2),
- ``h`` is the local smoothing length.

The effective dynamic viscosities are then computed as
```math
\nu_{i,\mathrm{SGS}} = (C_S h_{ab})^2 |\bar{S}_{ab}|
\eta_{a,\text{eff}} = \rho_a\, \nu_{\text{eff}},
```
where $C_S$ is the Smagorinsky constant. This implementation uses a simplified pairwise approximation for the strain rate tensor magnitude $|\bar{S}_{ab}|$:
and averaged as
```math
|\bar{S}_{ab}| \approx \frac{\|v_a - v_b\|}{\|r_a - r_b\| + \epsilon}
\bar{\eta}_{ab} = \frac{2 \eta_{a,\text{eff}} \eta_{b,\text{eff}}}{\eta_{a,\text{eff}}+\eta_{b,\text{eff}}}.
```

This model is appropriate for turbulent flows where unresolved scales contribute additional dissipation.
Expand Down Expand Up @@ -413,26 +424,8 @@ ViscosityMorrisSGS(; nu, C_S=0.1, epsilon=0.001) = ViscosityMorrisSGS(nu, C_S, e
v_b = viscous_velocity(v_neighbor_system, neighbor_system, neighbor)
v_diff = v_a - v_b

# ------------------------------------------------------------------------------
# SGS part: Compute the subgrid-scale eddy viscosity.
# ------------------------------------------------------------------------------
# In classical LES [Lilly (1967)](@cite Lilly1967) the Smagorinsky model defines:
# ν_SGS = (C_S Δ)^2 |S|,
# where |S| is the norm of the strain-rate tensor Sᵢⱼ = ½(∂ᵢvⱼ+∂ⱼvᵢ).
#
# In SPH, one could compute ∂ᵢvⱼ via kernel gradients, but this is costly.
# A common low-order surrogate is to approximate the strain‐rate magnitude by a
# finite-difference along each particle pair:
#
# |S| ≈ ‖vₐ–v_b‖ / (‖rₐ–r_b‖ + δ),
#
# where δ regularizes the denominator to avoid singularities when particles are very close.
#
# This yields:
# S_mag = norm(v_diff) / (distance + ε)
#
# and then the Smagorinsky eddy viscosity:
# ν_SGS = (C_S * h̄)^2 * S_mag.
# See comments above for `ViscosityAdamiSGS`.
S_mag = norm(v_diff) / (distance + epsilon)
nu_SGS = (viscosity.C_S * smoothing_length_average)^2 * S_mag

Expand Down
12 changes: 6 additions & 6 deletions test/examples/examples_fluid.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,18 @@
clip_negative_pressure=true),
"WCSPH with ViscosityAdami" => (
# from 0.02*10.0*1.2*0.05/8
viscosity=ViscosityAdami(nu=0.0015),),
viscosity_fluid=ViscosityAdami(nu=0.0015),),
"WCSPH with ViscosityMorris" => (
# from 0.02*10.0*1.2*0.05/8
viscosity=ViscosityMorris(nu=0.0015),),
viscosity_fluid=ViscosityMorris(nu=0.0015),),
"WCSPH with ViscosityAdami and SummationDensity" => (
# from 0.02*10.0*1.2*0.05/8
viscosity=ViscosityAdami(nu=0.0015),
viscosity_fluid=ViscosityAdami(nu=0.0015),
fluid_density_calculator=SummationDensity(),
clip_negative_pressure=true),
"WCSPH with ViscosityMorris and SummationDensity" => (
# from 0.02*10.0*1.2*0.05/8
viscosity=ViscosityMorris(nu=0.0015),
viscosity_fluid=ViscosityMorris(nu=0.0015),
fluid_density_calculator=SummationDensity(),
clip_negative_pressure=true),
"WCSPH with smoothing_length=1.3" => (smoothing_length=1.3,),
Expand All @@ -55,15 +55,15 @@
smoothing_kernel,
smoothing_length,
sound_speed,
viscosity=viscosity,
viscosity=viscosity_fluid,
density_calculator=ContinuityDensity(),
acceleration=(0.0,
-gravity))),
"EDAC with SummationDensity" => (fluid_system=EntropicallyDampedSPHSystem(tank.fluid,
smoothing_kernel,
smoothing_length,
sound_speed,
viscosity=viscosity,
viscosity=viscosity_fluid,
density_calculator=SummationDensity(),
acceleration=(0.0,
-gravity)),),
Expand Down
1 change: 0 additions & 1 deletion test/schemes/fluid/viscosity.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
include("../../test_util.jl")
@testset verbose=true "Viscosity" begin
particle_spacing = 0.2
smoothing_length = 1.2 * particle_spacing
Expand Down
Loading