forked from trixi-framework/TrixiParticles.jl
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpressure_acceleration.jl
More file actions
143 lines (125 loc) · 7.58 KB
/
pressure_acceleration.jl
File metadata and controls
143 lines (125 loc) · 7.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# As shown in "Variational and momentum preservation aspects of Smooth Particle Hydrodynamic
# formulations" by Bonet and Lok (1999), for a consistent formulation this form has to be
# used with `SummationDensity`.
# This can also be seen in the tests for total energy conservation, which fail with the
# other `pressure_acceleration` form.
# We assume symmetry of the kernel gradient in this formulation. See below for the
# asymmetric version.
@inline function pressure_acceleration_summation_density(m_a, m_b, rho_a, rho_b, p_a, p_b,
W_a)
return -m_b * (p_a / rho_a^2 + p_b / rho_b^2) * W_a
end
# Same as above, but not assuming symmetry of the kernel gradient. To be used with
# corrections that do not produce a symmetric kernel gradient.
@inline function pressure_acceleration_summation_density(m_a, m_b, rho_a, rho_b, p_a, p_b,
W_a, W_b)
return -m_b * (p_a / rho_a^2 * W_a - p_b / rho_b^2 * W_b)
end
# As shown in "Variational and momentum preservation aspects of Smooth Particle Hydrodynamic
# formulations" by Bonet and Lok (1999), for a consistent formulation this form has to be
# used with `ContinuityDensity` with the formulation `\rho_a * \sum m_b / \rho_b ...`.
# This can also be seen in the tests for total energy conservation, which fail with the
# other `pressure_acceleration` form.
# We assume symmetry of the kernel gradient in this formulation. See below for the
# asymmetric version.
@inline function pressure_acceleration_continuity_density(m_a, m_b, rho_a, rho_b, p_a, p_b,
W_a)
return -m_b * (p_a + p_b) / (rho_a * rho_b) * W_a
end
# Same as above, but not assuming symmetry of the kernel gradient. To be used with
# corrections that do not produce a symmetric kernel gradient.
@inline function pressure_acceleration_continuity_density(m_a, m_b, rho_a, rho_b, p_a, p_b,
W_a, W_b)
return -m_b / (rho_a * rho_b) * (p_a * W_a - p_b * W_b)
end
# This formulation was introduced by Hu and Adams (2006). https://doi.org/10.1016/j.jcp.2005.09.001
# They argued that the formulation is more flexible because of the possibility to formulate
# different inter-particle averages or to assume different inter-particle distributions.
# Ramachandran (2019) and Adami (2012) use this formulation for the pressure acceleration.
#
# However, the tests show that the formulation is only linear and angular momentum conserving
# but not energy conserving.
#
# Note that the authors also used this formulation for an ISPH method in (https://doi.org/10.1016/j.jcp.2007.07.013)
#
# TODO: Further investigations on energy conservation.
@inline function inter_particle_averaged_pressure(m_a, m_b, rho_a, rho_b, p_a, p_b, W_a)
volume_a = m_a / rho_a
volume_b = m_b / rho_b
volume_term = (volume_a^2 + volume_b^2) / m_a
# Inter-particle averaged pressure
pressure_tilde = (rho_b * p_a + rho_a * p_b) / (rho_a + rho_b)
return -volume_term * pressure_tilde * W_a
end
# Same as `pressure_acceleration_continuity_density`, but using the minus formulation
# when pressures are negative to avoid tensile instability.
# See Lyu et al. (2021). https://doi.org/10.1016/j.apor.2021.102938
@inline function tensile_instability_correction(m_a, m_b, rho_a, rho_b, p_a, p_b, W_a)
p = p_b + abs(p_a)
return -m_b * p / (rho_a * rho_b) * W_a
end
function choose_pressure_acceleration_formulation(pressure_acceleration,
density_calculator, NDIMS, ELTYPE,
correction)
if correction isa KernelCorrection ||
correction isa GradientCorrection ||
correction isa BlendedGradientCorrection ||
correction isa MixedKernelGradientCorrection
if isempty(methods(pressure_acceleration,
(ELTYPE, ELTYPE, ELTYPE, ELTYPE, ELTYPE, ELTYPE,
SVector{NDIMS, ELTYPE}, SVector{NDIMS, ELTYPE})))
throw(ArgumentError("when a correction with an asymmetric kernel gradient is " *
"used, the passed pressure acceleration formulation must " *
"provide a version with the arguments " *
"`m_a, m_b, rho_a, rho_b, p_a, p_b, W_a, W_b`"))
end
else
if isempty(methods(pressure_acceleration,
(ELTYPE, ELTYPE, ELTYPE, ELTYPE, ELTYPE, ELTYPE,
SVector{NDIMS, ELTYPE})))
throw(ArgumentError("when not using a correction with an asymmetric kernel " *
"gradient, the passed pressure acceleration formulation must " *
"provide a version with the arguments " *
"`m_a, m_b, rho_a, rho_b, p_a, p_b, W_a`, " *
"using the symmetry of the kernel gradient"))
end
end
return pressure_acceleration
end
function choose_pressure_acceleration_formulation(pressure_acceleration::Nothing,
density_calculator::SummationDensity,
NDIMS, ELTYPE,
correction)
# Choose the pressure acceleration formulation corresponding to the density calculator.
return pressure_acceleration_summation_density
end
function choose_pressure_acceleration_formulation(pressure_acceleration::Nothing,
density_calculator::ContinuityDensity,
NDIMS, ELTYPE,
correction)
# Choose the pressure acceleration formulation corresponding to the density calculator.
return pressure_acceleration_continuity_density
end
# Formulation using symmetric gradient formulation for corrections not depending on local neighborhood.
@inline function pressure_acceleration(particle_system, neighbor_system, particle, neighbor,
m_a, m_b, p_a, p_b, rho_a, rho_b, pos_diff,
distance, W_a, correction)
(; pressure_acceleration_formulation) = particle_system
# Without correction or with `AkinciFreeSurfaceCorrection`, the kernel gradient is
# symmetric, so call the symmetric version of the pressure acceleration formulation.
return pressure_acceleration_formulation(m_a, m_b, rho_a, rho_b, p_a, p_b, W_a)
end
# Formulation using asymmetric gradient formulation for corrections depending on local neighborhood.
@inline function pressure_acceleration(particle_system, neighbor_system, particle, neighbor,
m_a, m_b, p_a, p_b, rho_a, rho_b, pos_diff,
distance, W_a,
correction::Union{KernelCorrection,
GradientCorrection,
BlendedGradientCorrection,
MixedKernelGradientCorrection})
(; pressure_acceleration_formulation) = particle_system
W_b = smoothing_kernel_grad(neighbor_system, -pos_diff, distance, neighbor)
# With correction, the kernel gradient is not necessarily symmetric, so call the
# asymmetric version of the pressure acceleration formulation.
return pressure_acceleration_formulation(m_a, m_b, rho_a, rho_b, p_a, p_b, W_a, W_b)
end