Skip to content

Commit

Permalink
Generalize surface normal calc (#539)
Browse files Browse the repository at this point in the history
* fix merge

* fix merge

* fix merge

* fix merge

* fix merge

* more merge fixes

* format

* fix

* fix

* fix

* fix

* fix

* more fixes

* fix

* fix

* fix

* more fixes

* fix

* fix

* format

* running

* update

* update

* optimization

* update

* update

* update

* update

* format

* up

* update

* remove unused code

* switch to support radius

* update

* fix doc

* add adhesion coefficient

* update_broken

* update

* format

* add to examples

* fix tests

* fix merge

* fix typos

* add basic test

* format

* rename

* format

* rename container system

* reduce example run time

* update news and readme

* format

* fix test

* reduce run time

* format

* fix

* correct merge

* update doc test

* revert

* fix tests

* fix

* fix

* review comments

* fix

* fix

* correct some stuff

* init with empty initial condition

* review update

* rename function

* remove unnecessary if

* docs

* fix doc

* revert one change

* fix typo

* update

* try to avoid allocs

* fix mem allocs

* review update

* update docs

* update

* review

* fix

* format

* make examples smaller

* reduce resolution

* review

* rename

* use trixi_include

* format

* use trixi_include

* update

* update

* review update

* format

* fix test errors

* update

* fix

* remove invalid surface normals

* add

* fix

* update

* update

* update

* fix

* update

* update

* update

* remove unused

* remove unused

* format

* fix tests

* fix

* fix

* fix naming

* format

* fix test

* set test up for 1.11

* fix test

* rename to number_density

* back merge

* fix

* format

* fix

* fix tests

* back merge from #584

* move additonal changes from #584

* add test

* add test

* format

* Increase errors for 1.11

* Fix invalidations

* Fix tests

* Update ci.yml

* revert

* Update ci.yml

* Update test/validation/validation.jl

Co-authored-by: Erik Faulhaber <[email protected]>

* format

* Update news and set to 0.2.4

* update

* fix MD format

* Update NEWS.md

* some fixes

* add docs

* review fixes

* remove independent setting of smoothing_kernel and smoothing_length

* remove calls to surface_normal method smoothing kernel

* format

* update news

* typo

* Update NEWS.md

* forgot some renames

* fix doc tests

* fix docs

* fix tests

* format

* Update NEWS.md

* fix tests

* Update NEWS.md

* fix

* fix

* fix

* fix

* review fixes

* review comments

* fix test

* typo

* review updates

* review update

* add boundary system

* update

* update

* format

* remove color since it is unused in this PR

* review comment

* format

* merge error

* review comment

* fix

* remove surface_normal_method()

* merge error

* function was renamed in PN

* format

* fix test

* fix error

* fix

* review comments

* review comments

* review comments

* format

* merge

* format

* add comment

* remove ideal_neighbor()

* format

* typo

* add missing docs

* only initialize necessary values

* fix test

* fix examples

---------

Co-authored-by: Erik Faulhaber <[email protected]>
  • Loading branch information
svchb and efaulhaber authored Jan 30, 2025
1 parent 3d73412 commit 2540f08
Show file tree
Hide file tree
Showing 28 changed files with 788 additions and 273 deletions.
12 changes: 11 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,20 @@
TrixiParticles.jl follows the interpretation of [semantic versioning (semver)](https://julialang.github.io/Pkg.jl/dev/compatibility/#Version-specifier-format-1)
used in the Julia ecosystem. Notable changes will be documented in this file for human readability.

## Version 0.2.6

This comment has been minimized.

Copy link
@svchb

svchb Jan 30, 2025

Author Collaborator

### Features

- Support for surface tension was added to EDAC (#539)

### Refactored

- Surface normal calculation was moved from surface_tension.jl to surface_normal_sph.jl (#539)

## Version 0.2.5

### Features

- Add particle packing for 2D (.asc) and 3D (.stl) geometries (#529)

### Compatibility Changes
Expand All @@ -26,7 +37,6 @@ used in the Julia ecosystem. Notable changes will be documented in this file for
- A new user tutorial was added (#514)
- Several docs fixes (#663, #659, #637, #658, #664)


## Version 0.2.3

### Highlights
Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "TrixiParticles"
uuid = "66699cd8-9c01-4e9d-a059-b96c86d16b3a"
authors = ["erik.faulhaber <[email protected]>"]
version = "0.2.6-dev"
version = "0.2.6"

[deps]
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
Expand Down
14 changes: 8 additions & 6 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,14 @@ makedocs(sitename="TrixiParticles.jl",
"Util" => joinpath("general", "util.md")
],
"Systems" => [
"Discrete Element Method (Solid)" => joinpath("systems",
"dem.md"),
"Weakly Compressible SPH (Fluid)" => joinpath("systems",
"weakly_compressible_sph.md"),
"Entropically Damped Artificial Compressibility for SPH (Fluid)" => joinpath("systems",
"entropically_damped_sph.md"),
"Fluid Models" => [
"Overview" => joinpath("systems", "fluid.md"),
"Weakly Compressible SPH (Fluid)" => joinpath("systems",
"weakly_compressible_sph.md"),
"Entropically Damped Artificial Compressibility for SPH (Fluid)" => joinpath("systems",
"entropically_damped_sph.md")
],
"Discrete Element Method (Solid)" => joinpath("systems", "dem.md"),
"Total Lagrangian SPH (Elastic Structure)" => joinpath("systems",
"total_lagrangian_sph.md"),
"Boundary" => joinpath("systems", "boundary.md")
Expand Down
89 changes: 89 additions & 0 deletions docs/src/systems/fluid.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# [Fluid Models](@id fluid_models)
Currently available fluid methods are the [weakly compressible SPH method](@ref wcsph) and the [entropically damped artificial compressibility for SPH](@ref edac).
This page lists models and techniques that apply to both of these methods.

## [Viscosity](@id viscosity_wcsph)

TODO: Explain viscosity.

```@autodocs
Modules = [TrixiParticles]
Pages = [joinpath("schemes", "fluid", "viscosity.jl")]
```

## [Corrections](@id corrections)

```@autodocs
Modules = [TrixiParticles]
Pages = [joinpath("general", "corrections.jl")]
```



## [Surface Normals](@id surface_normal)
```@autodocs
Modules = [TrixiParticles]
Pages = [joinpath("schemes", "fluid", "surface_normal_sph.jl")]
```

## [Surface Tension](@id surface_tension)

### Akinci-based intra-particle force surface tension and wall adhesion model
The work by Akinci proposes three forces:
- a cohesion force
- a surface area minimization force
- a wall adhesion force

The classical model is composed of the curvature minimization and cohesion force.

#### Cohesion force
The model calculates the cohesion force based on the support radius ``h_c`` and the distance between particles.
This force is determined using two distinct regimes within the support radius:
- For particles closer than half the support radius,
a repulsive force is calculated to prevent particles from clustering too tightly,
enhancing the simulation's stability and realism.
- Beyond half the support radius and within the full support radius,
an attractive force is computed, simulating the effects of surface tension that draw particles together.
The cohesion force, ``F_{\text{cohesion}}``, for a pair of particles is given by:
```math
F_{\text{cohesion}} = -\sigma m_b C(r) \frac{r}{\Vert r \Vert},
```
where:
- ``\sigma`` represents the surface tension coefficient, adjusting the overall strength of the cohesion effect.
- ``C`` is a scalar function of the distance between particles.

The cohesion kernel ``C`` is defined as
```math
C(r)=\frac{32}{\pi h_c^9}
\begin{cases}
(h_c-r)^3 r^3, & \text{if } 2r > h_c \\
2(h_c-r)^3 r^3 - \frac{h^6}{64}, & \text{if } r > 0 \text{ and } 2r \leq h_c \\
0, & \text{otherwise}
\end{cases}
```

#### Surface area minimization force
To model the minimization of the surface area and curvature of the fluid, a curvature force is used, which is calculated as
```math
F_{\text{curvature}} = -\sigma (n_a - n_b)
```

#### Wall adhesion force
The wall adhesion model proposed by Akinci et al. is based on a kernel function which is 0 from 0.0 to 0.5 support radiia with a maximum at 0.75.
With the force calculated with an adhesion coefficient ``\beta`` as
```math
F_{\text{adhesion}} = -\beta m_b A(r) \frac{r}{\Vert r \Vert},
```
with ``A`` being the adhesion kernel defined as
```math
A(r)= \frac{0.007}{h_c^{3.25}}
\begin{cases}
\sqrt[4]{- \frac{4r^2}{h_c} + 6r - 2h_c}, & \text{if } 2r > h_c \text{ and } r \leq h_c \\
0, & \text{otherwise.}
\end{cases}
```

```@autodocs
Modules = [TrixiParticles]
Pages = [joinpath("schemes", "fluid", "surface_tension.jl")]
```
78 changes: 0 additions & 78 deletions docs/src/systems/weakly_compressible_sph.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,6 @@ Modules = [TrixiParticles]
Pages = [joinpath("schemes", "fluid", "weakly_compressible_sph", "state_equations.jl")]
```

## [Viscosity](@id viscosity_wcsph)

TODO: Explain viscosity.

```@autodocs
Modules = [TrixiParticles]
Pages = [joinpath("schemes", "fluid", "viscosity.jl")]
```

## [Density Diffusion](@id density_diffusion)

Density diffusion can be used with [`ContinuityDensity`](@ref) to remove the noise in the
Expand Down Expand Up @@ -118,72 +109,3 @@ term is very expensive and adds about 40--50% of computational cost.
Modules = [TrixiParticles]
Pages = [joinpath("schemes", "fluid", "weakly_compressible_sph", "density_diffusion.jl")]
```

## [Corrections](@id corrections)

```@autodocs
Modules = [TrixiParticles]
Pages = [joinpath("general", "corrections.jl")]
```

## [Surface Tension](@id surface_tension)

### Akinci-based intra-particle force surface tension and wall adhesion model
The work by Akinci proposes three forces:
- a cohesion force
- a surface area minimization force
- a wall adhesion force

The classical model is composed of the curvature minimization and cohesion force.

#### Cohesion force
The model calculates the cohesion force based on the distance between particles and the support radius ``h_c``.
This force is determined using two distinct regimes within the support radius:
- For particles closer than half the support radius,
a repulsive force is calculated to prevent particle clustering too tightly,
enhancing the simulation's stability and realism.
- Beyond half the support radius and within the full support radius,
an attractive force is computed, simulating the effects of surface tension that draw particles together.
The cohesion force, ``F_{\text{cohesion}}``, for a pair of particles is given by:
```math
F_{\text{cohesion}} = -\sigma m_b C(r) \frac{r}{\Vert r \Vert},
```
where:
- ``\sigma`` represents the surface tension coefficient, adjusting the overall strength of the cohesion effect.
- ``C`` is a scalar function of the distance between particles.

The cohesion kernel ``C`` is defined as
```math
C(r)=\frac{32}{\pi h_c^9}
\begin{cases}
(h_c-r)^3 r^3, & \text{if } 2r > h_c \\
2(h_c-r)^3 r^3 - \frac{h^6}{64}, & \text{if } r > 0 \text{ and } 2r \leq h_c \\
0, & \text{otherwise}
\end{cases}
```

#### Surface area minimization force
To model the minimization of the surface area and curvature of the fluid, a curvature force is used, which is calculated as
```math
F_{\text{curvature}} = -\sigma (n_a - n_b)
```

#### Wall adhesion force
The wall adhesion model proposed by Akinci et al. is based on a kernel function which is 0 from 0.0 to 0.5 support radiia with a maximum at 0.75.
With the force calculated with an adhesion coefficient ``\beta`` as
```math
F_{\text{adhesion}} = -\beta m_b A(r) \frac{r}{\Vert r \Vert},
```
with ``A`` being the adhesion kernel defined as
```math
A(r)= \frac{0.007}{h_c^{3.25}}
\begin{cases}
\sqrt[4]{- \frac{4r^2}{h_c} + 6r - 2h_c}, & \text{if } 2r > h_c \text{ and } r \leq h_c \\
0, & \text{otherwise.}
\end{cases}
```

```@autodocs
Modules = [TrixiParticles]
Pages = [joinpath("schemes", "fluid", "surface_tension.jl")]
```
6 changes: 4 additions & 2 deletions examples/fluid/dam_break_2d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ fluid_system = WeaklyCompressibleSPHSystem(tank.fluid, fluid_density_calculator,
smoothing_length, viscosity=viscosity,
density_diffusion=density_diffusion,
acceleration=(0.0, -gravity), correction=nothing,
surface_tension=nothing)
surface_tension=nothing,
reference_particle_spacing=fluid_particle_spacing)

# ==========================================================================================
# ==== Boundary
Expand All @@ -70,7 +71,8 @@ boundary_model = BoundaryModelDummyParticles(tank.boundary.density, tank.boundar
state_equation=state_equation,
boundary_density_calculator,
smoothing_kernel, smoothing_length,
correction=nothing)
correction=nothing,
reference_particle_spacing=fluid_particle_spacing)

boundary_system = BoundarySPHSystem(tank.boundary, boundary_model, adhesion_coefficient=0.0)

Expand Down
13 changes: 8 additions & 5 deletions examples/fluid/dam_break_oil_film_2d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,16 @@ oil_viscosity = ViscosityMorris(nu=nu_sim_oil)
trixi_include(@__MODULE__, joinpath(examples_dir(), "fluid", "dam_break_2d.jl"),
sol=nothing, fluid_particle_spacing=fluid_particle_spacing,
viscosity=ViscosityMorris(nu=nu_sim_water), smoothing_length=smoothing_length,
gravity=gravity, density_diffusion=nothing, sound_speed=sound_speed)
gravity=gravity, density_diffusion=nothing, sound_speed=sound_speed,
prefix="")

# ==========================================================================================
# ==== Setup oil layer

oil_size = (W, 0.1 * H)
oil_density = 700.0
oil_eos = StateEquationCole(; sound_speed, reference_density=oil_density, exponent=1,
clip_negative_pressure=false)

oil = RectangularShape(fluid_particle_spacing,
round.(Int, oil_size ./ fluid_particle_spacing),
Expand All @@ -50,12 +53,12 @@ end
oil_state_equation = StateEquationCole(; sound_speed, reference_density=oil_density,
exponent=1, clip_negative_pressure=false)
oil_system = WeaklyCompressibleSPHSystem(oil, fluid_density_calculator,
oil_state_equation, smoothing_kernel,
oil_eos, smoothing_kernel,
smoothing_length, viscosity=oil_viscosity,
density_diffusion=density_diffusion,
acceleration=(0.0, -gravity),
surface_tension=SurfaceTensionAkinci(surface_tension_coefficient=0.02),
correction=AkinciFreeSurfaceCorrection(oil_density))
surface_tension=SurfaceTensionAkinci(surface_tension_coefficient=0.01),
correction=AkinciFreeSurfaceCorrection(oil_density),
reference_particle_spacing=fluid_particle_spacing)

# ==========================================================================================
# ==== Simulation
Expand Down
24 changes: 14 additions & 10 deletions examples/fluid/falling_water_spheres_2d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ sphere2 = SphereShape(fluid_particle_spacing, sphere_radius, sphere2_center,

# ==========================================================================================
# ==== Fluid
fluid_smoothing_length = 1.0 * fluid_particle_spacing

# Using a smoothing_length of exactly 1.0 * fluid_particle is necessary for this model to be accurate.
# This yields some numerical issues though which can be circumvented by subtracting eps().
fluid_smoothing_length = 1.0 * fluid_particle_spacing - eps()
fluid_smoothing_kernel = SchoenbergCubicSplineKernel{2}()

fluid_density_calculator = ContinuityDensity()
Expand All @@ -50,13 +53,13 @@ alpha = 8 * nu / (fluid_smoothing_length * sound_speed)
viscosity = ArtificialViscosityMonaghan(alpha=alpha, beta=0.0)
density_diffusion = DensityDiffusionAntuono(sphere2, delta=0.1)

sphere_surface_tension = WeaklyCompressibleSPHSystem(sphere1, fluid_density_calculator,
state_equation, fluid_smoothing_kernel,
sphere_surface_tension = EntropicallyDampedSPHSystem(sphere1, fluid_smoothing_kernel,
fluid_smoothing_length,
viscosity=viscosity,
sound_speed, viscosity=viscosity,
density_calculator=ContinuityDensity(),
acceleration=(0.0, -gravity),
surface_tension=SurfaceTensionAkinci(surface_tension_coefficient=0.05),
correction=AkinciFreeSurfaceCorrection(fluid_density))
reference_particle_spacing=fluid_particle_spacing)

sphere = WeaklyCompressibleSPHSystem(sphere2, fluid_density_calculator,
state_equation, fluid_smoothing_kernel,
Expand All @@ -72,19 +75,20 @@ boundary_model = BoundaryModelDummyParticles(tank.boundary.density, tank.boundar
state_equation=state_equation,
boundary_density_calculator,
fluid_smoothing_kernel, fluid_smoothing_length,
viscosity=ViscosityAdami(nu=wall_viscosity))
viscosity=ViscosityAdami(nu=wall_viscosity),
reference_particle_spacing=fluid_particle_spacing)

boundary_system = BoundarySPHSystem(tank.boundary, boundary_model,
adhesion_coefficient=0.001)
adhesion_coefficient=1.0)

# ==========================================================================================
# ==== Simulation
semi = Semidiscretization(boundary_system, sphere_surface_tension, sphere)
semi = Semidiscretization(sphere_surface_tension, sphere, boundary_system)
ode = semidiscretize(semi, tspan)

info_callback = InfoCallback(interval=50)
saving_callback = SolutionSavingCallback(dt=0.01, output_directory="out", prefix="",
write_meta_data=true)
saving_callback = SolutionSavingCallback(dt=0.01, output_directory="out",
prefix="", write_meta_data=true)

callbacks = CallbackSet(info_callback, saving_callback)

Expand Down
16 changes: 8 additions & 8 deletions examples/fluid/falling_water_spheres_3d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,35 @@ using OrdinaryDiffEq

# ==========================================================================================
# ==== Resolution
fluid_particle_spacing = 0.008
fluid_particle_spacing = 0.005

# ==========================================================================================
# ==== Experiment Setup
gravity = 9.81
nu = 0.01
nu = 0.001
fluid_density = 1000.0
sound_speed = 50

sphere1_radius = 0.05

sphere1_center = (0.5, 0.5, 0.2)
sphere2_center = (1.5, 0.5, 0.2)
sphere1_center = (0.5, 0.5, 0.075)
sphere2_center = (1.5, 0.5, 0.075)
sphere1 = SphereShape(fluid_particle_spacing, sphere1_radius, sphere1_center,
fluid_density, sphere_type=VoxelSphere(), velocity=(0.0, 0.0, -2.0))
fluid_density, sphere_type=VoxelSphere(), velocity=(0.0, 0.0, -1.0))
sphere2 = SphereShape(fluid_particle_spacing, sphere1_radius, sphere2_center,
fluid_density, sphere_type=VoxelSphere(), velocity=(0.0, 0.0, -2.0))
fluid_density, sphere_type=VoxelSphere(), velocity=(0.0, 0.0, -1.0))

# `compact_support` needs to be `2.0 * particle_spacing` to be correct
fluid_smoothing_length = 1.0 * fluid_particle_spacing

trixi_include(@__MODULE__,
joinpath(examples_dir(), "fluid", "falling_water_spheres_2d.jl"),
fluid_particle_spacing=fluid_particle_spacing, tspan=(0.0, 0.2),
fluid_particle_spacing=fluid_particle_spacing, tspan=(0.0, 0.1),
initial_fluid_size=(0.0, 0.0, 0.0),
tank_size=(2.0, 1.0, 0.1), sound_speed=sound_speed,
faces=(true, true, true, true, true, false),
acceleration=(0.0, 0.0, -gravity), sphere1=sphere1, sphere2=sphere2,
fluid_smoothing_length=fluid_smoothing_length,
fluid_smoothing_kernel=SchoenbergCubicSplineKernel{3}(),
nu=nu, alpha=10 * nu / (fluid_smoothing_length * sound_speed),
surface_tension_coefficient=1.5, adhesion_coefficient=0.5)
surface_tension_coefficient=10, adhesion_coefficient=0.1)
Loading

1 comment on commit 2540f08

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/124003

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.2.6 -m "<description of version>" 2540f081bf829be1baaea75ee69413a66f3d17d0
git push origin v0.2.6

Please sign in to comment.