Download video

(Visualization made with ParaView)

Logo.jl

The Julia logo crashing into a plate and braking it into many pieces. The complete script for this tutorial can be found here: Logo.jl.

First, we have to load the Peridynamics.jl package.

using Peridynamics

Now we create the plate in the background by specifying the dimensions and the point spacing.

# PLATE - INDEX: p
dimXYₚ = 0.1 # [m]
dimZₚ = 0.01 # [m]
Δxₚ = dimXYₚ/50 # [m]
pcₚ = PointCloud(dimXYₚ, dimXYₚ, dimZₚ, Δxₚ)

A cubic point cloud is assembled, and only the points inside a specified radius are preserved to create the spheres of the logo. These points are then copied three times and moved to the correct position to represent the logo.

# SPHERES OF LOGO - INDEX: s
Øₛ = 0.03 # [m]
Vₛ = 4 / 3 * π * (Øₛ / 2)^3 # [m³]
Δxₛ = Øₛ / 20 # [m]
pcₛ₀ = PointCloud(Øₛ, Øₛ, Øₛ, Δxₛ)
sphere_point_set = @views findall(
    sqrt.(
        pcₛ₀.position[1, :] .^ 2 + pcₛ₀.position[2, :] .^ 2 + pcₛ₀.position[3, :] .^ 2
    ) .<= Øₛ / 2,
)
pcₛ₀.position[3, sphere_point_set] .+= Øₛ / 2 + dimZₚ / 2 + 1.1Δxₚ
pcₛ₁ = PointCloud(
    pcₛ₀.position[:, sphere_point_set],
    pcₛ₀.volume[sphere_point_set],
    zeros(Bool, length(sphere_point_set)),
    pcₛ₀.radius[sphere_point_set],
    length(sphere_point_set),
)
pcₛ₂ = deepcopy(pcₛ₁)
pcₛ₃ = deepcopy(pcₛ₁)
rₗ = Øₛ / 2 + 0.2 * Øₛ
pcₛ₁.position[2, :] .+= rₗ
pcₛ₂.position[1, :] .+= rₗ * cos(30π / 180)
pcₛ₂.position[2, :] .-= rₗ * sin(30π / 180)
pcₛ₃.position[1, :] .-= rₗ * cos(30π / 180)
pcₛ₃.position[2, :] .-= rₗ * sin(30π / 180)

Different material properties are used for the plate and the spheres.

Plate
  • Horizon $\delta = 3.015 \Delta x_p$
  • Density $\rho = 2000\,\mathrm{kg}\,\mathrm{m}^{-3}$
  • Youngs modulus $E = 30 \times 10^9 \, \mathrm{Pa}$
  • Griffith's parameter $G_c = 10 \, \mathrm{N} \, \mathrm{m}^{-1}$
Julia-logo spheres
  • Horizon $\delta = 3.015 \Delta x_s$
  • Density $\rho = 7850\,\mathrm{kg}\,\mathrm{m}^{-3}$
  • Youngs modulus $E = 210 \times 10^9 \, \mathrm{Pa}$
  • Griffith's parameter $G_c = 1000 \, \mathrm{N} \, \mathrm{m}^{-1}$
matₚ = BondBasedMaterial(;
    horizon=3.015Δxₚ,
    density=2000,
    young_modulus=30e9,
    critical_energy_release_rate=10.0,
)
matₛ = BondBasedMaterial(;
    horizon=3.015Δxₛ,
    density=7850.0,
    young_modulus=210e9,
    critical_energy_release_rate=1000.0,
)

All material points of the spheres have a initial velocity of $-20\, \mathrm{m} \, \mathrm{s}^{-1}$ in $z$-direction.

icₛ = [VelocityIC(-20.0, 1:(pcₛ₁.n_points), 3)]

For the contact analysis, every body needs to be specified with a BodySetup. Time can be saved by using only one sphere for the calculation of the stable time step.

plate = BodySetup(pcₚ, matₚ)
sphere1 = BodySetup(pcₛ₁, matₛ; ics=icₛ)
sphere2 = BodySetup(pcₛ₂, matₛ; ics=icₛ, calc_timestep=false)
sphere3 = BodySetup(pcₛ₃, matₛ; ics=icₛ, calc_timestep=false)
body_setup = [plate, sphere1, sphere2, sphere3]

Contact between the plate and the three spheres needs to be specified.

contact = [Contact((1, 2), Δxₚ), Contact((1, 3), Δxₚ), Contact((1, 4), Δxₚ)]

For this simulation, 3000 time steps with explicit time integration and the velocity verlet algorithm are used.

td = TimeDiscretization(3000)

Now we give the simulation a name and create a directory for the results.

simulation_name = "Logo"
resfolder = joinpath(@__DIR__, "results", simulation_name)
mkpath(resfolder)
es = ExportSettings(resfolder, 10)

To complete everything, the PDContactAnalysis is created and submitted for simulation.

JOB = PDContactAnalysis(;
    name=simulation_name, body_setup=body_setup, contact=contact, td=td, es=es
)
results = submit(JOB);