33 density_calculator, smoothing_kernel,
44 smoothing_length; viscosity=nothing,
55 state_equation=nothing, correction=nothing,
6+ clip_negative_pressure=true,
67 reference_particle_spacing=0.0)
78
89Boundary model for [`WallBoundarySystem`](@ref).
@@ -22,6 +23,15 @@ Boundary model for [`WallBoundarySystem`](@ref).
2223- `correction`: Correction method of the adjacent fluid system (see [Corrections](@ref corrections)).
2324- `viscosity`: Slip (default) or no-slip condition. See description below for further
2425 information.
26+ - `clip_negative_pressure=true`: Clip negative boundary pressures to avoid sticking
27+ artifacts from attractive fluid-boundary forces at free
28+ surfaces. Note that this is not a correct formulation
29+ at interior boundaries (away from free surfaces).
30+ Disable this option when simulating closed systems without
31+ free surfaces to avoid artificially increased boundary
32+ pressures that cause larger gaps between fluid and boundary
33+ in areas of low pressure, against which the particle
34+ shifting technique is fighting.
2535- `reference_particle_spacing`: The reference particle spacing used for weighting values at the boundary,
2636 which currently is only needed when using surface tension.
2737# Examples
@@ -39,24 +49,38 @@ boundary_model = BoundaryModelDummyParticles(densities, masses, AdamiPressureExt
3949BoundaryModelDummyParticles(AdamiPressureExtrapolation, ViscosityAdami)
4050```
4151"""
42- struct BoundaryModelDummyParticles{DC, ELTYPE <: Real , VECTOR, SE, K, V, COR, C}
43- pressure :: VECTOR # Vector{ELTYPE}
44- hydrodynamic_mass :: VECTOR # Vector{ELTYPE}
45- state_equation :: SE
46- density_calculator :: DC
47- smoothing_kernel :: K
48- smoothing_length :: ELTYPE
49- viscosity :: V
50- correction :: COR
51- cache :: C
52- end
53-
54- # The default constructor needs to be accessible for Adapt.jl to work with this struct.
55- # See the comments in general/gpu.jl for more details.
52+ struct BoundaryModelDummyParticles{DC, SE, CLIP, ELTYPE <: Real , VECTOR, K, V, COR, C}
53+ pressure :: VECTOR # Vector{ELTYPE}
54+ hydrodynamic_mass :: VECTOR # Vector{ELTYPE}
55+ state_equation :: SE
56+ density_calculator :: DC
57+ smoothing_kernel :: K
58+ smoothing_length :: ELTYPE
59+ viscosity :: V
60+ correction :: COR
61+ cache :: C
62+ # Store this both as field and type parameter to avoid annoying hand-written
63+ # `adapt_structure` functions.
64+ clip_negative_pressure :: Bool
65+
66+ function BoundaryModelDummyParticles (pressure, hydrodynamic_mass, state_equation,
67+ density_calculator, smoothing_kernel,
68+ smoothing_length, viscosity, correction,
69+ cache, clip_negative_pressure)
70+ return new{typeof (density_calculator), typeof (state_equation),
71+ clip_negative_pressure, eltype (pressure), typeof (pressure),
72+ typeof (smoothing_kernel), typeof (viscosity), typeof (correction),
73+ typeof (cache)}(pressure, hydrodynamic_mass, state_equation,
74+ density_calculator, smoothing_kernel, smoothing_length,
75+ viscosity, correction, cache, clip_negative_pressure)
76+ end
77+ end
78+
5679function BoundaryModelDummyParticles (initial_density, hydrodynamic_mass,
5780 density_calculator, smoothing_kernel,
5881 smoothing_length; viscosity= nothing ,
5982 state_equation= nothing , correction= nothing ,
83+ clip_negative_pressure= true ,
6084 reference_particle_spacing= 0.0 )
6185 pressure = initial_boundary_pressure (initial_density, density_calculator,
6286 state_equation)
@@ -82,10 +106,17 @@ function BoundaryModelDummyParticles(initial_density, hydrodynamic_mass,
82106
83107 return BoundaryModelDummyParticles (pressure, hydrodynamic_mass, state_equation,
84108 density_calculator, smoothing_kernel,
85- smoothing_length, viscosity, correction, cache)
109+ smoothing_length, viscosity, correction, cache,
110+ clip_negative_pressure)
111+ end
112+
113+ @inline function Base. ndims (boundary_model:: BoundaryModelDummyParticles )
114+ return ndims (boundary_model. smoothing_kernel)
86115end
87116
88- @inline Base. ndims (boundary_model:: BoundaryModelDummyParticles ) = ndims (boundary_model. smoothing_kernel)
117+ @inline function clip_negative_pressure (:: BoundaryModelDummyParticles{<:Any, <:Any, CLIP} ) where {CLIP}
118+ return CLIP
119+ end
89120
90121@doc raw """
91122 AdamiPressureExtrapolation(; pressure_offset=0, allow_loop_flipping=true)
108139 loop is not thread parallelizable.
109140 This can cause error variations between simulations with
110141 different numbers of threads.
111-
112142"""
113143struct AdamiPressureExtrapolation{ELTYPE}
114144 pressure_offset :: ELTYPE
@@ -423,33 +453,33 @@ end
423453
424454function compute_pressure! (boundary_model, :: Union{SummationDensity, ContinuityDensity} ,
425455 system, v, u, v_ode, u_ode, semi)
426-
427- # Limit pressure to be non-negative to avoid attractive forces between fluid and
428- # boundary particles at free surfaces (sticking artifacts).
429456 @threaded semi for particle in eachparticle (system)
430- apply_state_equation! (boundary_model, current_density (v, system, particle) ,
431- particle)
457+ @inbounds apply_state_equation! (boundary_model,
458+ current_density (v, system, particle), particle)
432459 end
433460
434461 return boundary_model
435462end
436463
437- # Use this function to avoid passing closures to Polyester.jl with `@batch` (`@threaded`).
438- # Otherwise, `@threaded` does not work here with Julia ARM on macOS.
439- # See https://github.com/JuliaSIMD/Polyester.jl/issues/88.
440- @inline function apply_state_equation! (boundary_model, density, particle)
441- boundary_model. pressure[particle] = max (boundary_model. state_equation (density), 0 )
464+ @propagate_inbounds function apply_state_equation! (boundary_model, density, particle)
465+ pressure = boundary_model. state_equation (density)
466+
467+ # This is determined statically and has therefore no overhead.
468+ if clip_negative_pressure (boundary_model)
469+ # Clip pressure to avoid sticking artifacts from negative pressures at free surfaces.
470+ pressure = max (pressure, 0 )
471+ end
472+
473+ boundary_model. pressure[particle] = pressure
442474end
443475
444476@propagate_inbounds function apply_state_equation! (boundary_model:: BoundaryModelDummyParticles {<: Any ,
445- <: Any ,
446- <: Any ,
447477 Nothing},
448478 density, particle)
449479 # Contact-only wall setups can reuse dummy particles for rigid contact without
450480 # configuring a hydrodynamic state equation. In that case, keep the auxiliary wall
451481 # pressure at zero because it is only meaningful for fluid-coupled updates.
452- boundary_model. pressure[particle] = zero ( eltype (boundary_model . pressure))
482+ boundary_model. pressure[particle] = 0
453483end
454484
455485function compute_pressure! (boundary_model,
@@ -518,9 +548,11 @@ function compute_adami_density!(boundary_model, system, v, particle)
518548 compute_wall_velocity! (viscosity, system, v, particle)
519549 end
520550
521- # Limit pressure to be non-negative to avoid attractive forces between fluid and
522- # boundary particles at free surfaces (sticking artifacts).
523- @inbounds pressure[particle] = max (pressure[particle], 0 )
551+ # Clip pressure to avoid sticking artifacts from negative pressures at free surfaces.
552+ # This is determined statically and has therefore no overhead.
553+ if clip_negative_pressure (boundary_model)
554+ @inbounds pressure[particle] = max (pressure[particle], 0 )
555+ end
524556
525557 # Apply inverse state equation to compute density (not used with EDAC)
526558 inverse_state_equation! (density, state_equation, pressure, particle)
0 commit comments