Skip to content

Commit a5972b0

Browse files
LasNikasLasNikas
andauthored
Make kernel_grad threshold compatible with single precision and small particle spacing (#913)
* adapt threshold kernel gradient * add link * apply formatter * fix tests * add check in ddt * consistent comments * fix * make volume check consistent * fix again * fix tests * implement suggestions * fix gpu tests * fix sqrt * fix sqrt bugs * fix numerical precision * implement suggestions * fix tests * implement suggestions --------- Co-authored-by: LasNikas <niklas.nehe@web.de>
1 parent 30713fc commit a5972b0

File tree

13 files changed

+57
-42
lines changed

13 files changed

+57
-42
lines changed

examples/n_body/n_body_system.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ function TrixiParticles.interact!(dv, v_particle_system, u_particle_system,
5959
TrixiParticles.foreach_point_neighbor(particle_system, neighbor_system,
6060
system_coords, neighbor_coords,
6161
semi) do particle, neighbor, pos_diff, distance
62-
# Only consider particles with a distance > 0
63-
distance < sqrt(eps()) && return
62+
# No interaction of a particle with itself
63+
particle_system === neighbor_system && particle === neighbor && return
6464

6565
# Original version
6666
# dv = -G * mass[neighbor] * pos_diff / norm(pos_diff)^3

src/general/corrections.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,9 @@ function compute_correction_values!(system,
216216
smoothing_length(system, particle))
217217

218218
kernel_correction_coefficient[particle] += volume * W
219-
if distance > sqrt(eps())
219+
220+
# Only consider particles with a distance > 0. See `src/general/smoothing_kernels.jl` for more details.
221+
if distance^2 > eps(initial_smoothing_length(system)^2)
220222
grad_W = kernel_grad(system_smoothing_kernel(system), pos_diff, distance,
221223
smoothing_length(system, particle))
222224
tmp = volume * grad_W

src/general/smoothing_kernels.jl

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,13 @@ abstract type AbstractSmoothingKernel{NDIMS} end
33
@inline Base.ndims(::AbstractSmoothingKernel{NDIMS}) where {NDIMS} = NDIMS
44

55
@inline function kernel_grad(kernel, pos_diff, distance, h)
6-
# TODO Use `eps` relative to `h` to allow scaling of simulations
7-
distance < sqrt(eps(typeof(h))) && return zero(pos_diff)
6+
# For `distance == 0`, the analytical gradient is zero, but the code divides by zero.
7+
# To account for rounding errors, we check if `distance` is almost zero.
8+
# Since the coordinates are in the order of the smoothing length `h`,
9+
# `distance^2` is in the order of `h^2`, hence the comparison `distance^2 < eps(h^2)`.
10+
# Note that this is faster than `distance < sqrt(eps(h^2))`.
11+
# Also note that `sqrt(eps(h^2)) != eps(h)`.
12+
distance^2 < eps(h^2) && return zero(pos_diff)
813

914
return kernel_deriv(kernel, distance, h) / distance * pos_diff
1015
end

src/preprocessing/particle_packing/rhs.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ function interact!(dv, v_particle_system, u_particle_system,
88
# Loop over all pairs of particles and neighbors within the kernel cutoff
99
foreach_point_neighbor(system, neighbor_system, system_coords, neighbor_coords,
1010
semi) do particle, neighbor, pos_diff, distance
11-
# Only consider particles with a distance > 0
12-
distance < sqrt(eps()) && return
11+
# Only consider particles with a distance > 0. See `src/general/smoothing_kernels.jl` for more details.
12+
distance^2 < eps(initial_smoothing_length(system)^2) && return
1313

1414
rho_a = system.initial_condition.density[particle]
1515
rho_b = neighbor_system.initial_condition.density[neighbor]

src/schemes/boundary/open_boundary/method_of_characteristics.jl

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ end
102102
# J2: Propagates downstream to the local flow
103103
# J3: Propagates upstream to the local flow
104104
function evaluate_characteristics!(system, v, u, v_ode, u_ode, semi, t)
105-
(; volume, cache, fluid_system, density, pressure) = system
105+
(; volume, cache, fluid_system, smoothing_length) = system
106106
(; characteristics, previous_characteristics) = cache
107107

108108
@threaded semi for particle in eachparticle(system)
@@ -165,8 +165,9 @@ function evaluate_characteristics!(system, v, u, v_ode, u_ode, semi, t)
165165
# of fluid particles by using the average of the values of the previous time step.
166166
# See eq. 27 in Negi (2020) https://doi.org/10.1016/j.cma.2020.113119
167167
@threaded semi for particle in each_integrated_particle(system)
168-
# Particle is outside of the influence of fluid particles
169-
if isapprox(volume[particle], 0)
168+
# Particle is outside of the influence of fluid particles.
169+
# `volume` is in the order of 1 / h^d, so volume * h^d is in the order of 1.
170+
if volume[particle] * smoothing_length^ndims(system) < eps(eltype(smoothing_length))
170171

171172
# Using the average of the values at the previous time step for particles which
172173
# are outside of the influence of fluid particles.
@@ -178,7 +179,9 @@ function evaluate_characteristics!(system, v, u, v_ode, u_ode, semi, t)
178179
for neighbor in each_integrated_particle(system)
179180
# Make sure that only neighbors in the influence of
180181
# the fluid particles are used.
181-
if volume[neighbor] > sqrt(eps())
182+
# `volume` is in the order of 1 / h^d, so volume * h^d is in the order of 1.
183+
if volume[neighbor] * smoothing_length^ndims(system) >
184+
eps(eltype(smoothing_length))
182185
avg_J1 += previous_characteristics[1, neighbor]
183186
avg_J2 += previous_characteristics[2, neighbor]
184187
avg_J3 += previous_characteristics[3, neighbor]

src/schemes/fluid/entropically_damped_sph/rhs.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,11 @@ function interact!(dv, v_particle_system, u_particle_system,
6767
dv_adhesion = adhesion_force(surface_tension_a, particle_system, neighbor_system,
6868
particle, neighbor, pos_diff, distance)
6969

70+
dv_particle = dv_pressure + dv_viscosity_ + dv_tvf + dv_surface_tension +
71+
dv_adhesion
72+
7073
for i in 1:ndims(particle_system)
71-
@inbounds dv[i,
72-
particle] += dv_pressure[i] + dv_viscosity_[i] + dv_tvf[i] +
73-
dv_surface_tension[i] + dv_adhesion[i]
74+
@inbounds dv[i, particle] += dv_particle[i]
7475
end
7576

7677
v_diff = current_velocity(v_particle_system, particle_system, particle) -

src/schemes/fluid/surface_tension.jl

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,8 @@ end
174174
neighbor_system::AbstractFluidSystem,
175175
particle, neighbor, pos_diff, distance,
176176
rho_a, rho_b, grad_kernel)
177-
# No cohesion with oneself
178-
distance < sqrt(eps()) && return zero(pos_diff)
177+
# No cohesion with oneself. See `src/general/smoothing_kernels.jl` for more details.
178+
distance^2 < eps(initial_smoothing_length(particle_system)^2) && return zero(pos_diff)
179179

180180
m_b = hydrodynamic_mass(neighbor_system, neighbor)
181181
support_radius = compact_support(smoothing_kernel,
@@ -194,8 +194,8 @@ end
194194
(; surface_tension_coefficient) = surface_tension_a
195195

196196
smoothing_length_ = smoothing_length(particle_system, particle)
197-
# No surface tension with oneself
198-
distance < sqrt(eps()) && return zero(pos_diff)
197+
# No surface tension with oneself. See `src/general/smoothing_kernels.jl` for more details.
198+
distance^2 < eps(initial_smoothing_length(particle_system)^2) && return zero(pos_diff)
199199

200200
m_b = hydrodynamic_mass(neighbor_system, neighbor)
201201
n_a = surface_normal(particle_system, particle)
@@ -215,8 +215,8 @@ end
215215
rho_a, rho_b, grad_kernel)
216216
(; surface_tension_coefficient) = surface_tension_a
217217

218-
# No surface tension with oneself
219-
distance < sqrt(eps()) && return zero(pos_diff)
218+
# No surface tension with oneself. See `src/general/smoothing_kernels.jl` for more details.
219+
distance^2 < eps(initial_smoothing_length(particle_system)^2) && return zero(pos_diff)
220220

221221
n_a = surface_normal(particle_system, particle)
222222
curvature_a = curvature(particle_system, particle)
@@ -285,8 +285,8 @@ end
285285
rho_a, rho_b, grad_kernel)
286286
(; surface_tension_coefficient) = surface_tension_a
287287

288-
# No surface tension with oneself
289-
distance < sqrt(eps()) && return zero(pos_diff)
288+
# No surface tension with oneself. See `src/general/smoothing_kernels.jl` for more details.
289+
distance^2 < eps(initial_smoothing_length(particle_system)^2) && return zero(pos_diff)
290290

291291
S_a = stress_tensor(particle_system, particle)
292292
S_b = stress_tensor(neighbor_system, neighbor)
@@ -302,8 +302,8 @@ end
302302
pos_diff, distance)
303303
(; adhesion_coefficient) = neighbor_system
304304

305-
# No adhesion with oneself
306-
distance < sqrt(eps()) && return zero(pos_diff)
305+
# No adhesion with oneself. See `src/general/smoothing_kernels.jl` for more details.
306+
distance^2 < eps(initial_smoothing_length(particle_system)^2) && return zero(pos_diff)
307307

308308
# No reason to calculate the adhesion force if adhesion coefficient is near zero
309309
abs(adhesion_coefficient) < eps() && return zero(pos_diff)

src/schemes/fluid/weakly_compressible_sph/density_diffusion.jl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,9 @@ function update!(density_diffusion::DensityDiffusionAntuono, v, u, system, semi)
187187
foreach_point_neighbor(system, system, system_coords, system_coords, semi;
188188
points=each_integrated_particle(system)) do particle, neighbor,
189189
pos_diff, distance
190-
# Only consider particles with a distance > 0
191-
distance < sqrt(eps(typeof(distance))) && return
190+
# Density diffusion terms are all zero for distance zero.
191+
# See `src/general/smoothing_kernels.jl` for more details.
192+
distance^2 < eps(initial_smoothing_length(system)^2) && return
192193

193194
rho_a = current_density(v, system, particle)
194195
rho_b = current_density(v, system, neighbor)
@@ -215,8 +216,9 @@ end
215216
pos_diff, distance, m_b, rho_a, rho_b,
216217
particle_system::AbstractFluidSystem,
217218
grad_kernel)
218-
# Density diffusion terms are all zero for distance zero
219-
distance < sqrt(eps(typeof(distance))) && return
219+
# Density diffusion terms are all zero for distance zero.
220+
# See `src/general/smoothing_kernels.jl` for more details.
221+
distance^2 < eps(initial_smoothing_length(particle_system)^2) && return
220222

221223
(; delta) = density_diffusion
222224
sound_speed = system_sound_speed(particle_system)

src/schemes/fluid/weakly_compressible_sph/rhs.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,11 @@ function interact!(dv, v_particle_system, u_particle_system,
8686
dv_adhesion = adhesion_force(surface_tension_a, particle_system, neighbor_system,
8787
particle, neighbor, pos_diff, distance)
8888

89+
dv_particle = dv_pressure + dv_viscosity_ + dv_tvf + dv_surface_tension +
90+
dv_adhesion
91+
8992
for i in 1:ndims(particle_system)
90-
@inbounds dv[i,
91-
particle] += dv_pressure[i] + dv_viscosity_[i] + dv_tvf[i] +
92-
dv_surface_tension[i] + dv_adhesion[i]
93+
@inbounds dv[i, particle] += dv_particle[i]
9394
# Debug example
9495
# debug_array[i, particle] += dv_pressure[i]
9596
end

src/schemes/structure/discrete_element_method/rhs.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ function interact!(dv, v_particle_system, u_particle_system, v_neighbor_system,
1212
neighbor,
1313
pos_diff,
1414
distance
15-
distance < sqrt(eps()) && return
15+
# See `src/general/smoothing_kernels.jl` for more details.
16+
distance^2 < eps(first(particle_system.radius)^2) && return
1617

1718
# Retrieve particle properties
1819
m_a = particle_system.mass[particle]

0 commit comments

Comments
 (0)