1
0
Fork 0
mirror of https://gitlab.rlp.net/mobitar/ReCo.jl.git synced 2024-11-12 22:40:44 +00:00
ReCo.jl/analysis/mean_squared_displacement.jl

243 lines
6.6 KiB
Julia
Raw Normal View History

2022-01-23 02:05:05 +00:00
using CairoMakie
using LaTeXStrings: @L_str
using Dates: Dates
using Random: Random
using StaticArrays: SVector
using JLD2: JLD2
2022-01-23 03:18:51 +00:00
using CellListMap: CellListMap
2022-01-23 04:26:27 +00:00
using ProgressMeter: ProgressMeter
2022-01-23 02:05:05 +00:00
using ReCo: ReCo
2022-01-29 13:32:04 +00:00
includet("../src/Visualization/common_CairoMakie.jl")
2022-01-24 19:43:37 +00:00
2022-01-23 03:18:51 +00:00
# IMPORTANT: Disable the periodic boundary conditions
# The arguments types have to match for the function to be overwritten!
2022-01-23 04:26:27 +00:00
ReCo.push_to_verlet_list!(::Any, ::Any, ::Any) = nothing
2022-01-23 03:18:51 +00:00
ReCo.update_verlet_lists!(::Any, ::CellListMap.CellList) = nothing
2022-01-23 04:26:27 +00:00
ReCo.update_verlet_lists!(::Any, ::Nothing) = nothing
2022-01-23 03:18:51 +00:00
ReCo.gen_cell_list(::Vector{SVector{2,Float64}}, ::CellListMap.Box) = nothing
2022-01-23 04:26:27 +00:00
ReCo.gen_cell_list(::Vector{SVector{2,Float64}}, ::Nothing) = nothing
2022-01-23 03:18:51 +00:00
ReCo.gen_cell_list_box(::Float64, ::Float64) = nothing
ReCo.restrict_coordinate(value::Float64, ::Float64) = value
ReCo.restrict_coordinates(v::SVector{2,Float64}, ::Float64) = v
2022-01-23 04:26:27 +00:00
ReCo.restrict_coordinates!(::ReCo.Particle, ::Float64) = nothing
2022-01-23 02:05:05 +00:00
2022-01-23 17:33:48 +00:00
const δt = 1e-4
const Dₜ = ReCo.DEFAULT_Dₜ
function max_possible_displacement(T::Float64, v₀::Float64, δt::Float64=δt, Dₜ::Float64=Dₜ)
return T * v₀ + T / δt * sqrt(2 * Dₜ * δt)
end
function msd_simulation(
v₀::Float64,
half_box_len::Float64,
T::Float64,
snapshot_at::Float64,
2022-01-29 13:32:04 +00:00
parent_dir::String;
2022-01-23 17:33:48 +00:00
comment::String="",
2022-01-29 13:32:04 +00:00
seed::Int64=42,
2022-01-23 17:33:48 +00:00
)
2022-01-29 13:32:04 +00:00
Random.seed!(seed)
2022-01-24 19:43:37 +00:00
2022-01-23 17:33:48 +00:00
dir = ReCo.init_sim(;
n_particles=1,
v₀=v₀,
parent_dir=parent_dir,
comment=comment,
half_box_len=half_box_len,
)
ReCo.run_sim(
dir;
duration=T,
seed=rand(1:typemax(Int64)),
snapshot_at=snapshot_at,
n_bundle_snapshots=1000,
)
return dir
end
2022-01-23 02:05:05 +00:00
function mean_squared_displacement(;
2022-01-24 19:43:37 +00:00
n_simulations::Int64, v₀s::NTuple{N,Float64}, T::Float64
) where {N}
2022-01-23 02:05:05 +00:00
n_v₀s = length(v₀s)
main_parent_dir = "mean_squared_displacement_$(Dates.now())"
sim_dirs = Matrix{String}(undef, (n_simulations, n_v₀s))
2022-01-23 04:26:27 +00:00
progress = ProgressMeter.Progress(n_v₀s * n_simulations; dt=3, desc="MSD: ")
2022-01-23 02:05:05 +00:00
for (v₀_ind, v₀) in enumerate(v₀s)
2022-01-23 17:33:48 +00:00
half_box_len = max_possible_displacement(T, v₀)
2022-01-23 02:05:05 +00:00
parent_dir = main_parent_dir * "/$v₀"
Threads.@threads for sim_ind in 1:n_simulations
2022-01-29 13:32:04 +00:00
dir = msd_simulation(v₀, half_box_len, T, 0.5, parent_dir; comment="$sim_ind")
2022-01-23 02:05:05 +00:00
sim_dirs[sim_ind, v₀_ind] = dir
2022-01-23 04:26:27 +00:00
ProgressMeter.next!(progress; showvalues=[(:v₀, v₀)])
2022-01-23 02:05:05 +00:00
end
end
ts = Float64[]
2022-01-24 19:43:37 +00:00
ReCo.append_bundle_properties!(
(ts,), (:t,), sim_dirs[1, 1]; particle_slice=1, snapshot_slice=:, first_bundle=2
) # Skip the first bundle to avoid t = 0
2022-01-23 02:05:05 +00:00
mean_sq_displacements = zeros((length(ts), n_v₀s))
@simd for v₀_ind in 1:n_v₀s
for sim_ind in 1:n_simulations
sim_dir = sim_dirs[sim_ind, v₀_ind]
bundle_paths = ReCo.sorted_bundle_paths(sim_dir)
snapshot_ind = 1
2022-01-23 17:33:48 +00:00
for i in 2:length(bundle_paths) # Skip the first bundle to avoid t = 0
2022-01-23 02:05:05 +00:00
bundle::ReCo.Bundle = JLD2.load_object(bundle_paths[i])
for c in bundle.c
sq_displacement = ReCo.sq_norm2d(c)
mean_sq_displacements[snapshot_ind, v₀_ind] += sq_displacement
snapshot_ind += 1
end
end
end
end
mean_sq_displacements ./= n_simulations
return (ts, mean_sq_displacements)
end
function expected_mean_squared_displacement(t::Float64, v₀::Float64)
Dₜ = ReCo.DEFAULT_Dₜ
particle_radius = ReCo.DEFAULT_PARTICLE_RADIUS
Dᵣ = 3 * Dₜ / ((2 * particle_radius)^2)
return (4 * Dₜ + 2 * v₀^2 / Dᵣ) * t + 2 * v₀^2 * (exp(-Dᵣ * t) - 1) / (Dᵣ^2)
end
2022-01-23 17:33:48 +00:00
function plot_mean_sq_displacement_with_expectation(
2022-01-24 19:43:37 +00:00
ts::Vector{Float64}, mean_sq_displacements::Matrix{Float64}, v₀s::NTuple{N,Float64}
) where {N}
2022-01-23 17:33:48 +00:00
init_cairomakie!()
fig = gen_figure()
2022-01-23 02:05:05 +00:00
ax = Axis(fig[1, 1]; xlabel=L"t", ylabel=L"\mathbf{MSD}", xscale=log10, yscale=log10)
t_linrange = LinRange(ts[1], ts[end], 1000)
v₀_scatter_plots = []
for (v₀_ind, v₀) in enumerate(v₀s)
scatter_plot = scatter!(
ax, ts, view(mean_sq_displacements, :, v₀_ind); markersize=4
)
push!(v₀_scatter_plots, scatter_plot)
expected_mean_sq_displacements = expected_mean_squared_displacement.(t_linrange, v₀)
lines!(ax, t_linrange, expected_mean_sq_displacements)
end
2022-01-23 04:26:27 +00:00
Legend(fig[1, 2], v₀_scatter_plots, [L"v_0 = %$v₀" for v₀ in v₀s])
2022-01-23 02:05:05 +00:00
2022-01-23 17:33:48 +00:00
set_gaps!(fig)
2022-01-23 02:05:05 +00:00
2022-01-23 17:33:48 +00:00
save_fig("mean_squared_displacement.pdf", fig)
2022-01-23 02:05:05 +00:00
return nothing
end
2022-01-23 17:33:48 +00:00
function run_msd_analysis()
2022-01-24 19:43:37 +00:00
v₀s = (0.0, 20.0, 40.0, 60.0, 80.0)
2022-01-23 02:05:05 +00:00
ts, mean_sq_displacements = mean_squared_displacement(;
2022-01-23 04:26:27 +00:00
n_simulations=200 * Threads.nthreads(), v₀s=v₀s, T=100.0
2022-01-23 02:05:05 +00:00
)
plot_mean_sq_displacement_with_expectation(ts, mean_sq_displacements, v₀s)
return nothing
end
2022-01-24 19:43:37 +00:00
function plot_random_walk(; T::Float64, v₀::Float64, seed::Int64)
2022-01-23 17:33:48 +00:00
half_box_len = max_possible_displacement(T, v₀)
2022-01-29 13:32:04 +00:00
dir = msd_simulation(v₀, half_box_len, T, 8.0, "random_walk_$(Dates.now())"; seed=seed)
2022-01-23 17:33:48 +00:00
ts = Float64[]
cs = SVector{2,Float64}[]
2022-01-24 19:43:37 +00:00
ReCo.append_bundle_properties!(
(ts, cs), (:t, :c), dir; particle_slice=1, snapshot_slice=:
)
2022-01-23 17:33:48 +00:00
init_cairomakie!()
fig = gen_figure()
max_displacement = maximum(ReCo.norm2d.(cs))
expected_mean_displacement = sqrt(expected_mean_squared_displacement(ts[end], v₀))
limit = max(max_displacement, expected_mean_displacement)
limit *= 1.04
ax = Axis(
fig[1, 1];
xlabel=L"x",
ylabel=L"y",
aspect=AxisAspect(1),
limits=(-limit, limit, -limit, limit),
)
path_plot = lines!(ax, cs; linewidth=0.5)
marker_size = 4
start_point_plot = scatter!(ax, cs[1]; markersize=marker_size, color=:lime)
end_point_plot = scatter!(ax, cs[end]; markersize=marker_size, color=:red)
2022-01-29 13:32:04 +00:00
expected_mean_squared_displacement_plot = arc!(
2022-01-23 17:33:48 +00:00
ax,
2022-01-29 13:32:04 +00:00
Point2(0.0, 0.0),
expected_mean_displacement,
0,
2 * π;
color=:orange,
linewidth=1,
2022-01-23 17:33:48 +00:00
)
Legend(
fig[1, 2],
[
start_point_plot,
end_point_plot,
path_plot,
expected_mean_squared_displacement_plot,
],
["Start point", "End point", "Path", "Expected mean displacement"],
)
set_gaps!(fig)
save_fig("random_walk.pdf", fig)
return nothing
end
function run_random_walk()
2022-01-24 19:43:37 +00:00
plot_random_walk(; T=100_000.0, v₀=0.0, seed=12345)
2022-01-23 17:33:48 +00:00
return nothing
end