@@ -81,6 +81,16 @@ function OpenBoundarySystem(boundary_zones::Union{BoundaryZone, Nothing}...;
8181 density_diffusion (fluid_system) : nothing )
8282 boundary_zones_ = filter (bz -> ! isnothing (bz), boundary_zones)
8383
84+ if boundary_model isa BoundaryModelDynamicalPressureZhang &&
85+ ! isnothing (shifting_technique)
86+ # When dynamical pressure is used with shifting, the shifting is ramped up until
87+ # it reaches the full value at two compact supports away from the free surface
88+ # of the boundary zone.
89+ # In order to prevent discontinuities in the shifting velocity, the boundary zone
90+ # must be wide enough to accommodate this ramping region.
91+ check_boundary_zone_widths (boundary_zones_, fluid_system)
92+ end
93+
8494 initial_conditions = union ((bz. initial_condition for bz in boundary_zones_). .. )
8595
8696 buffer = SystemBuffer (nparticles (initial_conditions), buffer_size)
@@ -605,15 +615,30 @@ end
605615 - boundary_zone. face_normal)
606616 dist_free_surface = boundary_zone. zone_width - dist_to_transition
607617
608- if dist_free_surface < compact_support (fluid_system, fluid_system)
609- # Ramp shifting velocity near the free surface using a kernel-weighted transition.
618+ # Width of the free-surface region where shifting is disabled.
619+ free_surface_region_width = compact_support (fluid_system, fluid_system)
620+ # Width of the ramp region behind the free-surface region where shifting is ramped
621+ # from zero to the unmodified value.
622+ ramp_width = free_surface_region_width
623+
624+ if dist_free_surface <= free_surface_region_width
625+ # The free-surface region is the layer within one compact support of the
626+ # free surface. Shifting is disabled there to avoid shifting particles with
627+ # incomplete support.
628+ for dim in 1 : ndims (system)
629+ cache. delta_v[dim, particle] = zero (eltype (system))
630+ end
631+ elseif dist_free_surface < free_surface_region_width + ramp_width
632+ # Between one and two compact supports from the free surface, shifting is
633+ # ramped from zero to the unmodified shifting velocity with a kernel-weighted
634+ # transition.
610635 # According to our experiments, the proposed alternative approaches lead to particle disorder:
611636 # - Sun et al. 2017: only use surface-tangential component
612637 # - Zhang et al. 2025: disable shifting entirely
613638 kernel_max = smoothing_kernel (system, 0 , particle)
614- dist_from_cutoff = compact_support (fluid_system, fluid_system) -
615- dist_free_surface
616- shifting_weight = smoothing_kernel (system, dist_from_cutoff , particle) /
639+ # Distance from the area where full shifting is applied.
640+ dist_from_ramp_end = free_surface_region_width + ramp_width - dist_free_surface
641+ shifting_weight = smoothing_kernel (system, dist_from_ramp_end , particle) /
617642 kernel_max
618643 delta_v_ramped = delta_v (system, particle) * shifting_weight
619644 for dim in 1 : ndims (system)
689714
690715@inline use_open_boundary_interpolation_neighbor (system) = false
691716
692- function check_configuration (system:: OpenBoundarySystem , systems,
693- neighborhood_search:: PointNeighbors.AbstractNeighborhoodSearch )
717+ function check_configuration (system:: OpenBoundarySystem , systems, neighborhood_search)
694718 (; boundary_model, boundary_zones) = system
695719
696720 # Store index of the fluid system. This is necessary for re-linking
@@ -710,3 +734,19 @@ function check_configuration(system::OpenBoundarySystem, systems,
710734 " See the PointNeighbors.jl documentation for more details." ))
711735 end
712736end
737+
738+ function check_boundary_zone_widths (boundary_zones, fluid_system)
739+ support = compact_support (system_smoothing_kernel (fluid_system),
740+ initial_smoothing_length (fluid_system))
741+ minimum_width = 2 * support
742+
743+ for (i, zone) in enumerate (boundary_zones)
744+ if zone. zone_width < minimum_width
745+ throw (ArgumentError (" boundary zone $i has width $(zone. zone_width) , " *
746+ " but must be at least two compact supports " *
747+ " ($(minimum_width) )" ))
748+ end
749+ end
750+
751+ return nothing
752+ end
0 commit comments