Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
20c9e72
add automatic reordering
Sep 30, 2025
da82198
fix typo
Sep 30, 2025
07671f4
Merge branch 'main' into automatic-ordering-clamped-particles
Sep 30, 2025
51affb8
revise docs
Sep 30, 2025
270dd86
indentation
Sep 30, 2025
b1b813d
Merge branch 'main' into automatic-ordering-clamped-particles
Oct 2, 2025
1ad1a2b
add tests
Oct 2, 2025
6263795
Merge branch 'main' into automatic-ordering-clamped-particles
Oct 6, 2025
1c71c74
Merge branch 'main' into automatic-ordering-clamped-particles
Oct 8, 2025
09cf86b
Merge branch 'main' into automatic-ordering-clamped-particles
Oct 10, 2025
aff99ba
Merge branch 'main' into automatic-ordering-clamped-particles
Oct 13, 2025
37310d2
add vector variant
Oct 14, 2025
d2b8fa7
force unique indices
Oct 14, 2025
f5816a2
Merge branch 'main' into automatic-ordering-clamped-particles
Oct 14, 2025
1304c97
Merge branch 'main' into automatic-ordering-clamped-particles
Oct 22, 2025
88b09e3
add depwarning
Oct 22, 2025
93a5372
Merge branch 'main' into automatic-ordering-clamped-particles
Oct 27, 2025
c3c2d13
fix regex
Oct 28, 2025
7604078
fix again
Oct 28, 2025
407ef63
implement suggestions
Oct 28, 2025
aa26aa7
apply formatter
Oct 28, 2025
2d2ce7e
Merge branch 'main' into automatic-ordering-clamped-particles
Oct 29, 2025
0e33f31
fix examples
Oct 29, 2025
2133216
fix
Oct 29, 2025
7f84978
implement suggestions
Oct 30, 2025
34f4c3b
rm datatype restriction
Oct 30, 2025
acd73df
implement suggestions
Oct 31, 2025
79fc6aa
adapt example files
Oct 31, 2025
65096c3
fix
Oct 31, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/general/initial_condition.jl
Original file line number Diff line number Diff line change
Expand Up @@ -415,3 +415,16 @@ function find_too_close_particles(coords, min_distance)

return result
end

function move_particles_to_end!(ic::InitialCondition, particle_ids_to_move)
sort_key = [i in particle_ids_to_move ? 1 : 0 for i in eachparticle(ic)]
permutation = sortperm(sort_key)

ic.coordinates .= ic.coordinates[:, permutation]
ic.velocity .= ic.velocity[:, permutation]
ic.mass .= ic.mass[permutation]
ic.density .= ic.density[permutation]
ic.pressure .= ic.pressure[permutation]

return ic
end
42 changes: 35 additions & 7 deletions src/schemes/structure/total_lagrangian_sph/system.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
TotalLagrangianSPHSystem(initial_condition,
smoothing_kernel, smoothing_length,
young_modulus, poisson_ratio;
n_clamped_particles=0, boundary_model=nothing,
n_clamped_particles=0,
clamped_particles::Vector{Int}=Int[],
acceleration=ntuple(_ -> 0.0, NDIMS),
penalty_force=nothing, source_terms=nothing)
penalty_force=nothing, viscosity=nothing,
source_terms=nothing, boundary_model=nothing)

System for particles of an elastic structure.

Expand All @@ -13,6 +15,16 @@ all relevant quantities and operators are measured with respect to the
initial configuration (O’Connor & Rogers 2021, Belytschko et al. 2000).
See [Total Lagrangian SPH](@ref tlsph) for more details on the method.

There are two approaches to specify clamped particles in the system:

1. **Manual ordering**: Provide the number of clamped particles via `n_clamped_particles`,
ensuring that these particles are the last entries in the `InitialCondition`
(see the info box below for details).

2. **Automatic ordering**: Pass the indices of the particles to be clamped via `clamped_particles`.
In this case, the specified particles will be internally reordered so that they become
the last particles in the `InitialCondition`.

# Arguments
- `initial_condition`: Initial condition representing the system's particles.
- `young_modulus`: Young's modulus.
Expand All @@ -24,8 +36,10 @@ See [Total Lagrangian SPH](@ref tlsph) for more details on the method.

# Keyword Arguments
- `n_clamped_particles`: Number of clamped particles which are fixed and not integrated
to clamp the structure. Note that the clamped particles must be the **last**
particles in the `InitialCondition`. See the info box below.
to clamp the structure. Note that the clamped particles must be the **last**
particles in the `InitialCondition`. See the info box below.
- `clamped_particles`: A vector of indices specifying the clamped particles which are fixed
and not integrated to clamp the structure.
- `boundary_model`: Boundary model to compute the hydrodynamic density and pressure for
fluid-structure interaction (see [Boundary Models](@ref boundary_models)).
- `penalty_force`: Penalty force to ensure regular particle position under large deformations
Expand All @@ -40,7 +54,8 @@ See [Total Lagrangian SPH](@ref tlsph) for more details on the method.
See, for example, [`SourceTermDamping`](@ref).

!!! note
The clamped particles must be the **last** particles in the `InitialCondition`.
If specifying the clamped particles manually (via `n_clamped_particles`),
the clamped particles must be the **last** particles in the `InitialCondition`.
To do so, e.g. use the `union` function:
```jldoctest; output = false, setup = :(clamped_particles = RectangularShape(0.1, (1, 4), (0.0, 0.0), density=1.0); beam = RectangularShape(0.1, (3, 4), (0.1, 0.0), density=1.0))
structure = union(beam, clamped_particles)
Expand Down Expand Up @@ -84,11 +99,12 @@ end
function TotalLagrangianSPHSystem(initial_condition,
smoothing_kernel, smoothing_length,
young_modulus, poisson_ratio;
n_clamped_particles=0, boundary_model=nothing,
n_clamped_particles=0,
clamped_particles::Vector{Int}=Int[],
acceleration=ntuple(_ -> 0.0,
ndims(smoothing_kernel)),
penalty_force=nothing, viscosity=nothing,
source_terms=nothing)
source_terms=nothing, boundary_model=nothing)
NDIMS = ndims(initial_condition)
ELTYPE = eltype(initial_condition)
n_particles = nparticles(initial_condition)
Expand All @@ -103,6 +119,18 @@ function TotalLagrangianSPHSystem(initial_condition,
throw(ArgumentError("`acceleration` must be of length $NDIMS for a $(NDIMS)D problem"))
end

# Handle clamped particles:
# If only n_clamped_particles > 0: assume manual ordering (do nothing).
# If both are 0/empty: no clamped particles (do nothing).
if !isempty(clamped_particles)
# Check consistency if both methods are used
if n_clamped_particles > 0 && n_clamped_particles != length(clamped_particles)
throw(ArgumentError("`n_clamped_particles` must equal length of `clamped_particles` when both are specified"))
end
n_clamped_particles = length(clamped_particles)
move_particles_to_end!(initial_condition, clamped_particles)
end

initial_coordinates = copy(initial_condition.coordinates)
current_coordinates = copy(initial_condition.coordinates)
mass = copy(initial_condition.mass)
Expand Down
Loading