Skip to content

Commit 376ab3c

Browse files
author
LasNikas
committed
second part
1 parent 185f9af commit 376ab3c

1 file changed

Lines changed: 121 additions & 0 deletions

File tree

docs/literate/src/tut_packing.jl

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,124 @@ plot!(p5, Plots.Shape, geometry, linestyle=:dash, label=nothing, axis=false, gri
118118
# As shown in the plot, the interface of the geometry surface is not well resolved yet.
119119
# In other words, there is no body-fitted configuration.
120120
# This is where the particle packing will come into play.
121+
# If we want to assign the mass of each sampled partcle consistently with its density,
122+
# we can adjust it as follows:
123+
shape_sampled.mass .= density * TrixiParticles.volume(geometry) / nparticles(shape_sampled)
124+
125+
# # Particle packing
126+
127+
# In the following, we will essentially follow the same steps described in
128+
# [Setting up your simulation from scratch](@ref setting_up_simulation_from_scratch).
129+
# That means we will generate systems that are then passed to the [`Semidiscretization`](@ref Semidiscretization).
130+
# The difference from a typical physical simulation is that we use [`ParticlePackingSystem`](@ref ParticlePackingSystem),
131+
# which does not represent any physical law. Instead, we only use the simulation framework to time-integrate
132+
# the packing process.
133+
134+
# We first need to import [OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl).
135+
using OrdinaryDiffEq
136+
137+
# Next, we set a background pressure. This can be chosen arbitrarily.
138+
# A higher value results in smaller time steps, but the final packed state
139+
# will remain the same after running the same number of steps.
140+
background_pressure = 1.0
141+
142+
# For particle interaction, we select a [smoothing kernel](@ref smoothing_kernel)
143+
# with a suitable smoothing length. Empirically, a factor of `0.8` times the
144+
# particle spacing gives good results [neher2025robustefficientpreprocessingtechniques](@cite).
145+
smoothing_kernel = SchoenbergQuinticSplineKernel{ndims(geometry)}()
146+
smoothing_length = 0.8 * particle_spacing
147+
148+
# Now we can create the packing system. For learning purposes, let’s first try
149+
# passing no signed distance field (SDF) and see what happens.
150+
packing_system = ParticlePackingSystem(shape_sampled;
151+
smoothing_kernel=smoothing_kernel,
152+
smoothing_length=smoothing_length,
153+
signed_distance_field=nothing, background_pressure)
154+
155+
# We now proceed with the familiar steps from
156+
# [Semidiscretization](@ref tut_semidiscretization) and [Time integration](@ref tut_time_integration).
157+
semi = Semidiscretization(packing_system)
158+
159+
## Use a high `tspan` to guarantee that the simulation runs for at least `maxiters`
160+
tspan = (0, 10000.0)
161+
ode = semidiscretize(semi, tspan)
162+
163+
maxiters = 100
164+
callbacks = CallbackSet(UpdateCallback())
165+
time_integrator = RDPK3SpFSAL35()
166+
167+
sol = solve(ode, time_integrator;
168+
abstol=1e-7, reltol=1e-4, save_everystep=false, maxiters=maxiters,
169+
callback=callbacks)
170+
171+
packed_ic = InitialCondition(sol, packing_system, semi)
172+
173+
p_not_constrained = plot(packed_ic, xlims=my_xlims, ylims=my_ylims)
174+
plot!(p_not_constrained, Plots.Shape, geometry, xlims=my_xlims, ylims=my_ylims)
175+
176+
# As we can see in the plot, the particles are not constrained to the
177+
# geometric surface.
178+
179+
# We therefore add an SDF for the geometry and repeat the same procedure.
180+
packing_system = ParticlePackingSystem(shape_sampled;
181+
smoothing_kernel=smoothing_kernel,
182+
smoothing_length=smoothing_length,
183+
signed_distance_field,
184+
background_pressure)
185+
186+
# Again, we follow the same steps for semidiscretization and time integration.
187+
semi = Semidiscretization(packing_system)
188+
189+
tspan = (0, 10000.0)
190+
ode = semidiscretize(semi, tspan)
191+
192+
maxiters = 1000
193+
callbacks = CallbackSet(UpdateCallback())
194+
time_integrator = RDPK3SpFSAL35()
195+
196+
sol = solve(ode, time_integrator;
197+
abstol=1e-7, reltol=1e-4, save_everystep=false, maxiters=maxiters,
198+
callback=callbacks)
199+
200+
packed_ic = InitialCondition(sol, packing_system, semi)
201+
202+
p = plot(packed_ic, xlims=my_xlims, ylims=my_ylims)
203+
plot!(p, Plots.Shape, geometry, xlims=my_xlims, ylims=my_ylims)
204+
205+
# We can see that the particles now stay inside the geometry,
206+
# but their distribution on the boundary is still not optimal.
207+
# Therefore, we set up a dedicated boundary packing system.
208+
# To do this, we set `is_boundary = true`.
209+
# For highly convex geometries, it is useful to slightly compress the
210+
# boundary layer thickness. The background for this is that the true
211+
# geometric volume is often larger than what was assumed when sampling
212+
# the boundary particles, because the mass was computed assuming an
213+
# interior particle volume.
214+
# A `boundary_compress_factor` of `0.8` or `0.9` works well for most shapes.
215+
# Since we have a relatively large particle spacing compared to the
216+
# geometry size in this example, we will choose `0.7`.
217+
boundary_system = ParticlePackingSystem(boundary_sampled;
218+
is_boundary=true,
219+
smoothing_kernel=smoothing_kernel,
220+
smoothing_length=smoothing_length,
221+
boundary_compress_factor=0.7,
222+
signed_distance_field, background_pressure)
223+
224+
# We can now couple the boundary system with the interior system:
225+
semi = Semidiscretization(packing_system, boundary_system)
226+
227+
tspan = (0, 10000.0)
228+
ode = semidiscretize(semi, tspan)
229+
230+
maxiters = 1000
231+
callbacks = CallbackSet(UpdateCallback())
232+
time_integrator = RDPK3SpFSAL35()
233+
234+
sol = solve(ode, time_integrator;
235+
abstol=1e-7, reltol=1e-4, save_everystep=false, maxiters=maxiters,
236+
callback=callbacks)
237+
238+
packed_ic = InitialCondition(sol, packing_system, semi)
239+
packed_boundary_ic = InitialCondition(sol, boundary_system, semi)
240+
p_final = plot(packed_ic, packed_boundary_ic, xlims=my_xlims, ylims=my_ylims)
241+
plot(p_final, Plots.Shape, geometry, xlims=my_xlims, ylims=my_ylims, linestyle=:dash)

0 commit comments

Comments
 (0)