mirror of
https://gitlab.rlp.net/mobitar/ReCo.jl.git
synced 2024-12-21 00:51:21 +00:00
Fixed graphics
This commit is contained in:
parent
e8faf811f1
commit
f4d47c7d2d
15 changed files with 442 additions and 365 deletions
|
@ -9,7 +9,7 @@ using ProgressMeter: ProgressMeter
|
|||
|
||||
using ReCo: ReCo
|
||||
|
||||
includet("../graphics/common_CairoMakie.jl")
|
||||
includet("../src/Visualization/common_CairoMakie.jl")
|
||||
|
||||
# IMPORTANT: Disable the periodic boundary conditions
|
||||
# The arguments types have to match for the function to be overwritten!
|
||||
|
@ -35,10 +35,11 @@ function msd_simulation(
|
|||
half_box_len::Float64,
|
||||
T::Float64,
|
||||
snapshot_at::Float64,
|
||||
parent_dir::String,
|
||||
parent_dir::String;
|
||||
comment::String="",
|
||||
seed::Int64=42,
|
||||
)
|
||||
Random.seed!(42)
|
||||
Random.seed!(seed)
|
||||
|
||||
dir = ReCo.init_sim(;
|
||||
n_particles=1,
|
||||
|
@ -76,7 +77,7 @@ function mean_squared_displacement(;
|
|||
parent_dir = main_parent_dir * "/$v₀"
|
||||
|
||||
Threads.@threads for sim_ind in 1:n_simulations
|
||||
dir = msd_simulation(v₀, half_box_len, T, 0.5, parent_dir, "$sim_ind")
|
||||
dir = msd_simulation(v₀, half_box_len, T, 0.5, parent_dir; comment="$sim_ind")
|
||||
|
||||
sim_dirs[sim_ind, v₀_ind] = dir
|
||||
|
||||
|
@ -172,10 +173,8 @@ function run_msd_analysis()
|
|||
end
|
||||
|
||||
function plot_random_walk(; T::Float64, v₀::Float64, seed::Int64)
|
||||
Random.seed!(seed)
|
||||
|
||||
half_box_len = max_possible_displacement(T, v₀)
|
||||
dir = msd_simulation(v₀, half_box_len, T, 8.0, "random_walk_$(Dates.now())")
|
||||
dir = msd_simulation(v₀, half_box_len, T, 8.0, "random_walk_$(Dates.now())"; seed=seed)
|
||||
|
||||
ts = Float64[]
|
||||
cs = SVector{2,Float64}[]
|
||||
|
@ -209,12 +208,14 @@ function plot_random_walk(; T::Float64, v₀::Float64, seed::Int64)
|
|||
|
||||
end_point_plot = scatter!(ax, cs[end]; markersize=marker_size, color=:red)
|
||||
|
||||
expected_mean_squared_displacement_plot = poly!(
|
||||
expected_mean_squared_displacement_plot = arc!(
|
||||
ax,
|
||||
Circle(Point2(0.0, 0.0), expected_mean_displacement);
|
||||
strokecolor=:orange,
|
||||
strokewidth=1,
|
||||
color=RGBAf(0.0, 0.0, 0.0, 0.0),
|
||||
Point2(0.0, 0.0),
|
||||
expected_mean_displacement,
|
||||
0,
|
||||
2 * π;
|
||||
color=:orange,
|
||||
linewidth=1,
|
||||
)
|
||||
|
||||
Legend(
|
||||
|
|
|
@ -9,7 +9,7 @@ using Random: Random
|
|||
|
||||
using ReCo: ReCo
|
||||
|
||||
includet("../../graphics/common_CairoMakie.jl")
|
||||
includet("../../src/Visualization/common_CairoMakie.jl")
|
||||
|
||||
function radial_distribution_simulation(;
|
||||
n_particles::Int64, v₀s::NTuple{N,Float64}, T::Float64, packing_ratio::Float64
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using CairoMakie
|
||||
using LaTeXStrings: @L_str
|
||||
|
||||
includet("common_CairoMakie.jl")
|
||||
includet("../src/Visualization/common_CairoMakie.jl")
|
||||
|
||||
const minimum_r_σ_ratio = 2^(1 / 6)
|
||||
|
||||
|
|
322
src/Animation.jl
322
src/Animation.jl
|
@ -1,322 +0,0 @@
|
|||
module Animation
|
||||
|
||||
export animate, plot_snapshot
|
||||
|
||||
using CairoMakie
|
||||
using GLMakie
|
||||
using ColorSchemes: ColorSchemes
|
||||
using LaTeXStrings: @L_str
|
||||
using JLD2: JLD2
|
||||
using ProgressMeter: ProgressMeter
|
||||
|
||||
using ..ReCo: ReCo
|
||||
|
||||
include("../graphics/common_CairoMakie.jl")
|
||||
|
||||
const DEFAULT_CENTER_OF_MASS_CIRCLE_COLOR = RGBAf(1, 1, 1, 0.5)
|
||||
|
||||
function angle_color(φ::Float64, color_scheme::ColorSchemes.ColorScheme)
|
||||
return get(color_scheme, rem2pi(φ, RoundDown) / (2 * π))
|
||||
end
|
||||
|
||||
function animate_bundle!(args, sim_consts::ReCo.SimConsts)
|
||||
bundle_t = args.bundle.t
|
||||
bundle_c = args.bundle.c
|
||||
bundle_φ = args.bundle.φ
|
||||
|
||||
for snapshot in 1:length(bundle_t)
|
||||
@simd for particle_ind in 1:(sim_consts.n_particles)
|
||||
c = bundle_c[particle_ind, snapshot]
|
||||
φ = bundle_φ[particle_ind, snapshot]
|
||||
|
||||
args.circles[][particle_ind] = Circle(
|
||||
Point2(c[1], c[2]), sim_consts.particle_radius
|
||||
)
|
||||
|
||||
color = angle_color(φ, args.color_scheme)
|
||||
args.colors[][particle_ind] = RGBAf(color)
|
||||
|
||||
if args.show_interaction_circle
|
||||
args.interaction_circles[][particle_ind] = Circle(
|
||||
Point2(c[1], c[2]), sim_consts.interaction_r
|
||||
)
|
||||
args.interaction_colors[][particle_ind] = RGBAf(color, 0.08)
|
||||
end
|
||||
|
||||
if args.show_skin_circle
|
||||
args.skin_circles[][particle_ind] = Circle(
|
||||
Point2(c[1], c[2]), sim_consts.skin_r
|
||||
)
|
||||
|
||||
args.skin_colors[][particle_ind] = RGBAf(color, 0.04)
|
||||
end
|
||||
end
|
||||
|
||||
if args.show_center_of_mass
|
||||
center_of_mass = ReCo.center_of_mass(
|
||||
view(bundle_c, :, snapshot), sim_consts.half_box_len
|
||||
)
|
||||
args.center_of_mass_circle[] = Circle(
|
||||
Point2(center_of_mass[1], center_of_mass[2]),
|
||||
args.center_of_mass_circle_radius,
|
||||
)
|
||||
end
|
||||
|
||||
if args.n_bundle == 1 && snapshot == 1
|
||||
poly!(args.ax, args.circles; color=args.colors)
|
||||
|
||||
if args.show_center_of_mass
|
||||
poly!(
|
||||
args.ax,
|
||||
args.center_of_mass_circle;
|
||||
color=DEFAULT_CENTER_OF_MASS_CIRCLE_COLOR,
|
||||
)
|
||||
end
|
||||
|
||||
if args.show_interaction_circle
|
||||
poly!(args.ax, args.interaction_circles; color=args.interaction_colors)
|
||||
end
|
||||
|
||||
if args.show_skin_circle
|
||||
poly!(args.ax, args.skin_circles; color=args.skin_colors)
|
||||
end
|
||||
|
||||
println("Recording started!")
|
||||
else
|
||||
if args.show_frame_diff && snapshot > 1
|
||||
@simd for i in 1:(sim_consts.n_particles)
|
||||
first_ind = 2 * i - 1
|
||||
second_ind = 2 * i
|
||||
frame_min_1 = snapshot - 1
|
||||
|
||||
args.segments_x[][first_ind] = bundle_c[i, frame_min_1][1]
|
||||
args.segments_x[][second_ind] = bundle_c[i, snapshot][1]
|
||||
|
||||
args.segments_y[][first_ind] = bundle_c[i, frame_min_1][2]
|
||||
args.segments_y[][second_ind] = bundle_c[i, snapshot][2]
|
||||
end
|
||||
|
||||
if snapshot == 2
|
||||
linesegments!(
|
||||
args.ax, args.segments_x, args.segments_y; color=args.colors
|
||||
)
|
||||
end
|
||||
|
||||
notify(args.segments_x)
|
||||
notify(args.segments_y)
|
||||
end
|
||||
|
||||
notify(args.circles)
|
||||
notify(args.colors)
|
||||
|
||||
if args.show_center_of_mass
|
||||
notify(args.center_of_mass_circle)
|
||||
end
|
||||
|
||||
if args.show_interaction_circle
|
||||
notify(args.interaction_circles)
|
||||
notify(args.interaction_colors)
|
||||
end
|
||||
|
||||
if args.show_skin_circle
|
||||
notify(args.skin_circles)
|
||||
notify(args.skin_colors)
|
||||
end
|
||||
end
|
||||
|
||||
args.ax.title = "t = $(round(bundle_t[snapshot], digits=3))"
|
||||
|
||||
recordframe!(args.io)
|
||||
end
|
||||
|
||||
return nothing
|
||||
end
|
||||
|
||||
function gen_axis_and_colorbar(fig, sim_consts::ReCo.SimConsts)
|
||||
ax = Axis(
|
||||
fig[1, 1];
|
||||
limits=(
|
||||
-sim_consts.half_box_len,
|
||||
sim_consts.half_box_len,
|
||||
-sim_consts.half_box_len,
|
||||
sim_consts.half_box_len,
|
||||
),
|
||||
aspect=AxisAspect(1),
|
||||
xlabel=L"x",
|
||||
ylabel=L"y",
|
||||
)
|
||||
|
||||
color_scheme = ColorSchemes.cyclic_mrybm_35_75_c68_n256_s25
|
||||
|
||||
Colorbar(fig[1, 2]; limits=(0, 2), colormap=color_scheme, label=L"\varphi / \pi")
|
||||
|
||||
return (ax, color_scheme)
|
||||
end
|
||||
|
||||
function animate(
|
||||
sim_dir::String;
|
||||
framerate::Int64=1,
|
||||
show_center_of_mass::Bool=false,
|
||||
show_interaction_circle::Bool=false,
|
||||
show_skin_circle::Bool=false,
|
||||
show_frame_diff::Bool=false,
|
||||
show_progress::Bool=true,
|
||||
)
|
||||
println("Generating animation...")
|
||||
|
||||
GLMakie.activate!()
|
||||
set_theme!(theme_black())
|
||||
|
||||
fig = Figure(; resolution=(1080, 1080))
|
||||
|
||||
sim_consts = ReCo.load_sim_consts(sim_dir)
|
||||
|
||||
ax, color_scheme = gen_axis_and_colorbar(fig, sim_consts)
|
||||
|
||||
n_particles = sim_consts.n_particles
|
||||
|
||||
animation_path = "$sim_dir/animation.mkv"
|
||||
|
||||
record(fig, animation_path; framerate=framerate) do io
|
||||
circles = Observable(Vector{Circle}(undef, n_particles))
|
||||
colors = Observable(Vector{RGBAf}(undef, n_particles))
|
||||
|
||||
center_of_mass_circle =
|
||||
segments_x =
|
||||
segments_y =
|
||||
interaction_circles =
|
||||
skin_circles = interaction_colors = skin_colors = nothing
|
||||
|
||||
center_of_mass_circle_radius = 3 * sim_consts.particle_radius
|
||||
|
||||
if show_center_of_mass
|
||||
center_of_mass_circle = Observable(
|
||||
Circle(Point2(0.0, 0.0), center_of_mass_circle_radius)
|
||||
)
|
||||
end
|
||||
|
||||
if show_interaction_circle
|
||||
interaction_circles = Observable(Vector{Circle}(undef, n_particles))
|
||||
skin_circles = Observable(Vector{Circle}(undef, n_particles))
|
||||
end
|
||||
|
||||
if show_skin_circle
|
||||
interaction_colors = Observable(Vector{RGBAf}(undef, n_particles))
|
||||
skin_colors = Observable(Vector{RGBAf}(undef, n_particles))
|
||||
end
|
||||
|
||||
if show_frame_diff
|
||||
segments_x = Observable(zeros(2 * n_particles))
|
||||
segments_y = Observable(zeros(2 * n_particles))
|
||||
end
|
||||
|
||||
bundle_paths = ReCo.sorted_bundle_paths(sim_dir)
|
||||
|
||||
progress = ProgressMeter.Progress(
|
||||
length(bundle_paths); dt=2, enabled=show_progress, desc="Animation: "
|
||||
)
|
||||
|
||||
for (n_bundle, bundle_path) in enumerate(bundle_paths)
|
||||
bundle::ReCo.Bundle = JLD2.load_object(bundle_path)
|
||||
|
||||
args = (;
|
||||
# Input
|
||||
show_center_of_mass,
|
||||
show_interaction_circle,
|
||||
show_skin_circle,
|
||||
show_frame_diff,
|
||||
# Internal
|
||||
io,
|
||||
ax,
|
||||
bundle,
|
||||
circles,
|
||||
colors,
|
||||
center_of_mass_circle_radius,
|
||||
center_of_mass_circle,
|
||||
segments_x,
|
||||
segments_y,
|
||||
interaction_circles,
|
||||
skin_circles,
|
||||
interaction_colors,
|
||||
skin_colors,
|
||||
color_scheme,
|
||||
n_bundle,
|
||||
)
|
||||
|
||||
animate_bundle!(args, sim_consts)
|
||||
|
||||
ProgressMeter.next!(progress)
|
||||
end
|
||||
end
|
||||
|
||||
println("Animation done.")
|
||||
|
||||
return nothing
|
||||
end
|
||||
|
||||
function get_wanted_snapshot_number(n_snapshots::Int64)
|
||||
print("There are $n_snapshots snapshots. Enter the wanted snapshot number: ")
|
||||
answer = readline()
|
||||
|
||||
snapshot = parse(Int64, answer)
|
||||
|
||||
@assert 0 < snapshot <= n_snapshots
|
||||
|
||||
return snapshot
|
||||
end
|
||||
|
||||
function plot_snapshot(sim_dir::String; show_center_of_mass::Bool=false)
|
||||
bundles_info = ReCo.BundlesInfo(sim_dir)
|
||||
snapshot = get_wanted_snapshot_number(bundles_info.total_n_snapshots)
|
||||
|
||||
bundle_path = ""
|
||||
snapshot_counter = 0
|
||||
bundle_snapshot = 0
|
||||
|
||||
for bundle_ind in 1:(bundles_info.n_bundles)
|
||||
bundle_n_snapshots = bundles_info.bundle_n_snapshots[bundle_ind]
|
||||
snapshot_counter += bundle_n_snapshots
|
||||
if snapshot_counter >= snapshot
|
||||
bundle_snapshot = bundle_n_snapshots - snapshot_counter + snapshot
|
||||
bundle_path = bundles_info.sorted_bundle_paths[bundle_ind]
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
bundle::ReCo.Bundle = JLD2.load_object(bundle_path)
|
||||
sim_consts = ReCo.load_sim_consts(sim_dir)
|
||||
|
||||
println("Initializing")
|
||||
|
||||
init_cairomakie!()
|
||||
fig = gen_figure()
|
||||
|
||||
ax, color_scheme = gen_axis_and_colorbar(fig, sim_consts)
|
||||
|
||||
@simd for particle_ind in 1:(sim_consts.n_particles)
|
||||
c = bundle.c[particle_ind, bundle_snapshot]
|
||||
φ = bundle.φ[particle_ind, bundle_snapshot]
|
||||
|
||||
color = angle_color(φ, color_scheme)
|
||||
|
||||
poly!(ax, Circle(Point2(c[1], c[2]), sim_consts.particle_radius); color=color)
|
||||
end
|
||||
|
||||
if show_center_of_mass
|
||||
center_of_mass = ReCo.center_of_mass(
|
||||
view(bundle.c, :, bundle_snapshot), sim_consts.half_box_len
|
||||
)
|
||||
circle = Circle(
|
||||
Point2(center_of_mass[1], center_of_mass[2]), 3 * sim_consts.particle_radius
|
||||
)
|
||||
poly!(ax, circle; color=DEFAULT_CENTER_OF_MASS_CIRCLE_COLOR)
|
||||
end
|
||||
|
||||
set_gaps!(fig)
|
||||
|
||||
save_fig("$snapshot.pdf", fig; parent_dir="$sim_dir/graphics")
|
||||
|
||||
return nothing
|
||||
end
|
||||
|
||||
end # module
|
|
@ -17,7 +17,7 @@ struct LocalCOMEnv <: Env
|
|||
direction_angle_state_space = gen_angle_state_space(n_direction_angle_states)
|
||||
|
||||
min_distance = 0.0
|
||||
max_distance = args.skin_r
|
||||
max_distance = args.skin_radius
|
||||
|
||||
distance_state_space = gen_distance_state_space(
|
||||
min_distance, max_distance, n_distance_states
|
||||
|
@ -50,10 +50,12 @@ mutable struct LocalCOMEnvHelper <: EnvHelper
|
|||
half_box_len::Float64
|
||||
max_elliptical_distance::Float64
|
||||
|
||||
function LocalCOMEnvHelper(shared::EnvHelperSharedProps, half_box_len::Float64, skin_r)
|
||||
function LocalCOMEnvHelper(
|
||||
shared::EnvHelperSharedProps, half_box_len::Float64, skin_radius
|
||||
)
|
||||
max_elliptical_distance = sqrt(2) * half_box_len / shared.elliptical_a_b_ratio
|
||||
|
||||
max_distance_to_local_center_of_mass = skin_r
|
||||
max_distance_to_local_center_of_mass = skin_radius
|
||||
|
||||
return new(
|
||||
shared,
|
||||
|
@ -72,7 +74,7 @@ mutable struct LocalCOMEnvHelper <: EnvHelper
|
|||
end
|
||||
|
||||
function gen_env_helper(::LocalCOMEnv, env_helper_shared::EnvHelperSharedProps; args)
|
||||
return LocalCOMEnvHelper(env_helper_shared, args.half_box_len, args.skin_r)
|
||||
return LocalCOMEnvHelper(env_helper_shared, args.half_box_len, args.skin_radius)
|
||||
end
|
||||
|
||||
function pre_integration_hook!(env_helper::LocalCOMEnvHelper)
|
||||
|
|
10
src/RL/RL.jl
10
src/RL/RL.jl
|
@ -62,7 +62,7 @@ function run_rl(;
|
|||
n_particles::Int64=100,
|
||||
seed::Int64=42,
|
||||
ϵ_stable::Float64=0.0001,
|
||||
skin_to_interaction_r_ratio::Float64=ReCo.DEFAULT_SKIN_TO_INTERACTION_R_RATIO,
|
||||
skin_to_interaction_radius_ratio::Float64=ReCo.DEFAULT_SKIN_TO_INTERACTION_R_RATIO,
|
||||
packing_ratio::Float64=0.15,
|
||||
show_progress::Bool=true,
|
||||
) where {E<:Env}
|
||||
|
@ -79,12 +79,12 @@ function run_rl(;
|
|||
sim_consts = ReCo.gen_sim_consts(
|
||||
n_particles,
|
||||
0.0;
|
||||
skin_to_interaction_r_ratio=skin_to_interaction_r_ratio,
|
||||
skin_to_interaction_radius_ratio=skin_to_interaction_radius_ratio,
|
||||
packing_ratio=packing_ratio,
|
||||
)
|
||||
n_particles = sim_consts.n_particles # Not always equal to the input!
|
||||
|
||||
env_args = (skin_r=sim_consts.skin_r,)
|
||||
env_args = (skin_radius=sim_consts.skin_radius,)
|
||||
|
||||
env = EnvType(; args=env_args)
|
||||
|
||||
|
@ -98,7 +98,9 @@ function run_rl(;
|
|||
env, agent, hook, n_steps_before_actions_update, elliptical_a_b_ratio, n_particles
|
||||
)
|
||||
|
||||
env_helper_args = (half_box_len=sim_consts.half_box_len, skin_r=sim_consts.skin_r)
|
||||
env_helper_args = (
|
||||
half_box_len=sim_consts.half_box_len, skin_radius=sim_consts.skin_radius
|
||||
)
|
||||
|
||||
env_helper = gen_env_helper(env, env_helper_shared; args=env_helper_args)
|
||||
|
||||
|
|
|
@ -33,7 +33,10 @@ using .RL
|
|||
include("simulation.jl")
|
||||
include("run.jl")
|
||||
|
||||
include("Animation.jl")
|
||||
include("Visualization/Animation.jl")
|
||||
using .Animation
|
||||
|
||||
include("Visualization/SnapshotPlot.jl")
|
||||
using .SnapshotPlot
|
||||
|
||||
end # module
|
257
src/Visualization/Animation.jl
Normal file
257
src/Visualization/Animation.jl
Normal file
|
@ -0,0 +1,257 @@
|
|||
module Animation
|
||||
|
||||
export animate
|
||||
|
||||
using GLMakie
|
||||
using ColorSchemes: ColorSchemes
|
||||
using LaTeXStrings: @L_str
|
||||
using JLD2: JLD2
|
||||
using ProgressMeter: ProgressMeter
|
||||
|
||||
using ..ReCo: ReCo
|
||||
|
||||
include("common.jl")
|
||||
|
||||
function animate_bundle!(args, sim_consts::ReCo.SimConsts)
|
||||
bundle_t = args.bundle.t
|
||||
bundle_c = args.bundle.c
|
||||
bundle_φ = args.bundle.φ
|
||||
|
||||
for bundle_snapshot in 1:length(bundle_t)
|
||||
@simd for particle_ind in 1:(sim_consts.n_particles)
|
||||
c = bundle_c[particle_ind, bundle_snapshot]
|
||||
φ = bundle_φ[particle_ind, bundle_snapshot]
|
||||
|
||||
args.particle_xs[][particle_ind] = c[1]
|
||||
args.particle_ys[][particle_ind] = c[2]
|
||||
|
||||
color = angle_color(φ, args.color_scheme)
|
||||
args.particle_colors[][particle_ind] = color
|
||||
|
||||
if args.show_interaction_circle
|
||||
args.interaction_colors[][particle_ind] = ColorSchemes.ColorTypes.RGBA(
|
||||
color, 0.08
|
||||
)
|
||||
end
|
||||
|
||||
if args.show_skin_circle
|
||||
args.skin_colors[][particle_ind] = ColorSchemes.ColorTypes.RGBA(color, 0.04)
|
||||
end
|
||||
end
|
||||
|
||||
if args.show_center_of_mass
|
||||
center_of_mass = ReCo.center_of_mass(
|
||||
view(bundle_c, :, bundle_snapshot), sim_consts.half_box_len
|
||||
)
|
||||
args.center_of_mass_point[] = Point(center_of_mass)
|
||||
end
|
||||
|
||||
if args.n_bundle == 1 && bundle_snapshot == 1
|
||||
scatter!(
|
||||
args.ax,
|
||||
args.particle_xs,
|
||||
args.particle_ys;
|
||||
markersize=2 * sim_consts.particle_radius,
|
||||
markerspace=SceneSpace,
|
||||
color=args.particle_colors,
|
||||
)
|
||||
|
||||
if args.show_center_of_mass
|
||||
scatter!(
|
||||
args.ax,
|
||||
args.center_of_mass_point;
|
||||
markersize=6 * sim_consts.particle_radius,
|
||||
markerspace=SceneSpace,
|
||||
color=ColorSchemes.ColorTypes.RGBA(1.0, 1.0, 1.0, 0.6),
|
||||
)
|
||||
end
|
||||
|
||||
if args.show_interaction_circle
|
||||
scatter!(
|
||||
args.ax,
|
||||
args.particle_xs,
|
||||
args.particle_ys;
|
||||
markersize=2 * sim_consts.interaction_radius,
|
||||
markerspace=SceneSpace,
|
||||
color=args.interaction_colors,
|
||||
)
|
||||
end
|
||||
|
||||
if args.show_skin_circle
|
||||
scatter!(
|
||||
args.ax,
|
||||
args.particle_xs,
|
||||
args.particle_ys;
|
||||
markersize=2 * sim_consts.skin_radius,
|
||||
markerspace=SceneSpace,
|
||||
color=args.skin_colors,
|
||||
)
|
||||
end
|
||||
|
||||
println("Recording started!")
|
||||
else
|
||||
if args.show_frame_diff && bundle_snapshot > 1
|
||||
@simd for i in 1:(sim_consts.n_particles)
|
||||
first_ind = 2 * i - 1
|
||||
second_ind = 2 * i
|
||||
frame_min_1 = bundle_snapshot - 1
|
||||
|
||||
args.segment_xs[][first_ind] = bundle_c[i, frame_min_1][1]
|
||||
args.segment_xs[][second_ind] = bundle_c[i, bundle_snapshot][1]
|
||||
|
||||
args.segment_ys[][first_ind] = bundle_c[i, frame_min_1][2]
|
||||
args.segment_ys[][second_ind] = bundle_c[i, bundle_snapshot][2]
|
||||
end
|
||||
|
||||
if bundle_snapshot == 2
|
||||
linesegments!(
|
||||
args.ax,
|
||||
args.segment_xs,
|
||||
args.segment_ys;
|
||||
color=args.particle_colors,
|
||||
)
|
||||
end
|
||||
|
||||
notify(args.segment_xs)
|
||||
notify(args.segment_ys)
|
||||
end
|
||||
|
||||
notify(args.particle_xs)
|
||||
notify(args.particle_ys)
|
||||
notify(args.particle_colors)
|
||||
|
||||
if args.show_center_of_mass
|
||||
notify(args.center_of_mass_point)
|
||||
end
|
||||
|
||||
if args.show_interaction_circle
|
||||
notify(args.interaction_colors)
|
||||
end
|
||||
|
||||
if args.show_skin_circle
|
||||
notify(args.skin_colors)
|
||||
end
|
||||
end
|
||||
|
||||
args.ax.title = "t = $(round(bundle_t[bundle_snapshot], digits=3))"
|
||||
|
||||
recordframe!(args.io)
|
||||
end
|
||||
|
||||
return nothing
|
||||
end
|
||||
|
||||
function animate(
|
||||
sim_dir::String;
|
||||
framerate::Int64=1,
|
||||
show_center_of_mass::Bool=false,
|
||||
show_interaction_circle::Bool=false,
|
||||
show_skin_circle::Bool=false,
|
||||
show_frame_diff::Bool=false,
|
||||
show_progress::Bool=true,
|
||||
)
|
||||
println("Initializing GLMakie...")
|
||||
|
||||
GLMakie.activate!()
|
||||
set_theme!(theme_black())
|
||||
|
||||
fig = Figure(; resolution=(1080, 1080))
|
||||
|
||||
sim_consts = ReCo.load_sim_consts(sim_dir)
|
||||
|
||||
ax, color_scheme = gen_axis_and_colorbar(fig, sim_consts)
|
||||
|
||||
n_particles = sim_consts.n_particles
|
||||
|
||||
animation_path = "$sim_dir/animation.mkv"
|
||||
|
||||
record(fig, animation_path; framerate=framerate) do io
|
||||
particle_xs = Observable(Vector{Float64}(undef, n_particles))
|
||||
particle_ys = Observable(Vector{Float64}(undef, n_particles))
|
||||
|
||||
particle_colors = Observable(
|
||||
Vector{ColorSchemes.ColorTypes.RGB{Float64}}(undef, n_particles)
|
||||
)
|
||||
|
||||
center_of_mass_point =
|
||||
segment_xs =
|
||||
segment_ys =
|
||||
interaction_circle_xs =
|
||||
interaction_circle_ys =
|
||||
skin_circle_xs =
|
||||
skin_circle_ys = interaction_colors = skin_colors = nothing
|
||||
|
||||
if show_center_of_mass
|
||||
center_of_mass_point = Observable(Point2(0.0, 0.0))
|
||||
end
|
||||
|
||||
if show_interaction_circle
|
||||
interaction_circle_xs = Observable(Vector{Float64}(undef, n_particles))
|
||||
interaction_circle_ys = Observable(Vector{Float64}(undef, n_particles))
|
||||
|
||||
interaction_colors = Observable(
|
||||
Vector{ColorSchemes.ColorTypes.RGBA{Float64}}(undef, n_particles)
|
||||
)
|
||||
end
|
||||
|
||||
if show_skin_circle
|
||||
skin_circle_xs = Observable(Vector{Float64}(undef, n_particles))
|
||||
skin_circle_ys = Observable(Vector{Float64}(undef, n_particles))
|
||||
|
||||
skin_colors = Observable(
|
||||
Vector{ColorSchemes.ColorTypes.RGBA{Float64}}(undef, n_particles)
|
||||
)
|
||||
end
|
||||
|
||||
if show_frame_diff
|
||||
segment_xs = Observable(zeros(2 * n_particles))
|
||||
segment_ys = Observable(zeros(2 * n_particles))
|
||||
end
|
||||
|
||||
bundle_paths = ReCo.sorted_bundle_paths(sim_dir)
|
||||
|
||||
progress = ProgressMeter.Progress(
|
||||
length(bundle_paths); dt=2, enabled=show_progress, desc="Animation: "
|
||||
)
|
||||
|
||||
for (n_bundle, bundle_path) in enumerate(bundle_paths)
|
||||
bundle::ReCo.Bundle = JLD2.load_object(bundle_path)
|
||||
|
||||
args = (;
|
||||
# Input
|
||||
show_center_of_mass,
|
||||
show_interaction_circle,
|
||||
show_skin_circle,
|
||||
show_frame_diff,
|
||||
# Internal
|
||||
io,
|
||||
ax,
|
||||
bundle,
|
||||
particle_xs,
|
||||
particle_ys,
|
||||
particle_colors,
|
||||
center_of_mass_point,
|
||||
segment_xs,
|
||||
segment_ys,
|
||||
interaction_circle_xs,
|
||||
interaction_circle_ys,
|
||||
skin_circle_xs,
|
||||
skin_circle_ys,
|
||||
interaction_colors,
|
||||
skin_colors,
|
||||
color_scheme,
|
||||
n_bundle,
|
||||
)
|
||||
|
||||
animate_bundle!(args, sim_consts)
|
||||
|
||||
ProgressMeter.next!(progress)
|
||||
end
|
||||
end
|
||||
|
||||
println("Animation done.")
|
||||
|
||||
return nothing
|
||||
end
|
||||
|
||||
end # module
|
86
src/Visualization/SnapshotPlot.jl
Normal file
86
src/Visualization/SnapshotPlot.jl
Normal file
|
@ -0,0 +1,86 @@
|
|||
module SnapshotPlot
|
||||
|
||||
export plot_snapshot
|
||||
|
||||
using CairoMakie
|
||||
using ColorSchemes: ColorSchemes
|
||||
using LaTeXStrings: @L_str
|
||||
|
||||
using ..ReCo: ReCo
|
||||
|
||||
include("common.jl")
|
||||
include("common_CairoMakie.jl")
|
||||
|
||||
function get_wanted_snapshot_number(total_n_snapshots::Int64)
|
||||
print("There are $total_n_snapshots snapshots. Enter the wanted snapshot number: ")
|
||||
answer = readline()
|
||||
|
||||
snapshot = parse(Int64, answer)
|
||||
|
||||
return snapshot
|
||||
end
|
||||
|
||||
function plot_snapshot(sim_dir::String; show_center_of_mass::Bool=false)
|
||||
bundles_info = ReCo.BundlesInfo(sim_dir)
|
||||
wanted_snapshot_out_of_total = get_wanted_snapshot_number(
|
||||
bundles_info.total_n_snapshots
|
||||
)
|
||||
|
||||
bundle, bundle_snapshot = ReCo.get_bundle_to_snapshot(
|
||||
bundles_info, wanted_snapshot_out_of_total
|
||||
)
|
||||
|
||||
sim_consts = ReCo.load_sim_consts(sim_dir)
|
||||
|
||||
println("Initializing CairoMakie...")
|
||||
|
||||
init_cairomakie!()
|
||||
fig = gen_figure()
|
||||
|
||||
ax, color_scheme = gen_axis_and_colorbar(fig, sim_consts)
|
||||
|
||||
particle_xs = Vector{Float64}(undef, sim_consts.n_particles)
|
||||
particle_ys = Vector{Float64}(undef, sim_consts.n_particles)
|
||||
particle_colors = Vector{ColorSchemes.ColorTypes.RGB}(undef, sim_consts.n_particles)
|
||||
|
||||
@simd for particle_ind in 1:(sim_consts.n_particles)
|
||||
c = bundle.c[particle_ind, bundle_snapshot]
|
||||
φ = bundle.φ[particle_ind, bundle_snapshot]
|
||||
|
||||
color = angle_color(φ, color_scheme)
|
||||
|
||||
particle_xs[particle_ind] = c[1]
|
||||
particle_ys[particle_ind] = c[2]
|
||||
particle_colors[particle_ind] = color
|
||||
end
|
||||
|
||||
scatter!(
|
||||
ax,
|
||||
particle_xs,
|
||||
particle_ys;
|
||||
markersize=2 * sim_consts.particle_radius,
|
||||
markerspace=SceneSpace,
|
||||
color=particle_colors,
|
||||
)
|
||||
|
||||
if show_center_of_mass
|
||||
center_of_mass = ReCo.center_of_mass(
|
||||
view(bundle.c, :, bundle_snapshot), sim_consts.half_box_len
|
||||
)
|
||||
scatter!(
|
||||
ax,
|
||||
Point(center_of_mass);
|
||||
markersize=6 * sim_consts.particle_radius,
|
||||
markerspace=SceneSpace,
|
||||
color=ColorSchemes.ColorTypes.RGBA(0.0, 0.0, 0.0, 0.6),
|
||||
)
|
||||
end
|
||||
|
||||
set_gaps!(fig)
|
||||
|
||||
save_fig("$wanted_snapshot_out_of_total.pdf", fig; parent_dir="$sim_dir/graphics")
|
||||
|
||||
return nothing
|
||||
end
|
||||
|
||||
end # module
|
26
src/Visualization/common.jl
Normal file
26
src/Visualization/common.jl
Normal file
|
@ -0,0 +1,26 @@
|
|||
using ColorSchemes
|
||||
|
||||
function angle_color(φ::Float64, color_scheme::ColorSchemes.ColorScheme)
|
||||
return get(color_scheme, rem2pi(φ, RoundDown) / (2 * π))
|
||||
end
|
||||
|
||||
function gen_axis_and_colorbar(fig, sim_consts::ReCo.SimConsts)
|
||||
ax = Axis(
|
||||
fig[1, 1];
|
||||
limits=(
|
||||
-sim_consts.half_box_len,
|
||||
sim_consts.half_box_len,
|
||||
-sim_consts.half_box_len,
|
||||
sim_consts.half_box_len,
|
||||
),
|
||||
aspect=AxisAspect(1),
|
||||
xlabel=L"x",
|
||||
ylabel=L"y",
|
||||
)
|
||||
|
||||
color_scheme = ColorSchemes.cyclic_mrybm_35_75_c68_n256_s25
|
||||
|
||||
Colorbar(fig[1, 2]; limits=(0, 2), colormap=color_scheme, label=L"\varphi / \pi")
|
||||
|
||||
return (ax, color_scheme)
|
||||
end
|
27
src/data.jl
27
src/data.jl
|
@ -9,8 +9,8 @@ struct SimConsts
|
|||
Dᵣ::Float64
|
||||
σ::Float64
|
||||
ϵ::Float64
|
||||
interaction_r::Float64
|
||||
skin_r::Float64
|
||||
interaction_radius::Float64
|
||||
skin_radius::Float64
|
||||
n_steps_before_verlet_list_update::Int64
|
||||
grid_n::Int64
|
||||
half_box_len::Float64
|
||||
|
@ -116,7 +116,7 @@ function append_bundle_properties!(
|
|||
for bundle_ind in first_bundle:length(bundle_paths)
|
||||
bundle::Bundle = JLD2.load_object(bundle_paths[bundle_ind])
|
||||
|
||||
for (v_ind, v) in enumerat(vs)
|
||||
for (v_ind, v) in enumerate(vs)
|
||||
property = properties[v_ind]
|
||||
bundle_property = getproperty(bundle, property)
|
||||
|
||||
|
@ -164,4 +164,25 @@ function load_sim_consts(dir::String)
|
|||
sim_consts::ReCo.SimConsts = JLD2.load_object("$dir/sim_consts.jld2")
|
||||
|
||||
return sim_consts
|
||||
end
|
||||
|
||||
function get_bundle_to_snapshot(
|
||||
bundles_info::BundlesInfo, snapshot::Int64
|
||||
)::Tuple{Bundle,Int64}
|
||||
@assert 0 < snapshot <= bundles_info.total_n_snapshots
|
||||
|
||||
snapshot_counter = 0
|
||||
|
||||
for bundle_ind in 1:(bundles_info.n_bundles)
|
||||
bundle_n_snapshots = bundles_info.bundle_n_snapshots[bundle_ind]
|
||||
snapshot_counter += bundle_n_snapshots
|
||||
if snapshot_counter >= snapshot
|
||||
bundle_snapshot = bundle_n_snapshots - snapshot_counter + snapshot
|
||||
bundle_path = bundles_info.sorted_bundle_paths[bundle_ind]
|
||||
|
||||
bundle::ReCo.Bundle = JLD2.load_object(bundle_path)
|
||||
|
||||
return (bundle, bundle_snapshot)
|
||||
end
|
||||
end
|
||||
end
|
14
src/run.jl
14
src/run.jl
|
@ -2,8 +2,8 @@ function empty_hook(args...)
|
|||
return nothing
|
||||
end
|
||||
|
||||
function gen_cell_list_box(half_box_len::Float64, skin_r::Float64)
|
||||
return CellListMap.Box(SVector(2 * half_box_len, 2 * half_box_len), skin_r)
|
||||
function gen_cell_list_box(half_box_len::Float64, skin_radius::Float64)
|
||||
return CellListMap.Box(SVector(2 * half_box_len, 2 * half_box_len), skin_radius)
|
||||
end
|
||||
|
||||
function run_sim(
|
||||
|
@ -81,8 +81,8 @@ function run_sim(
|
|||
args = (
|
||||
v₀=sim_consts.v₀,
|
||||
δt=sim_consts.δt,
|
||||
skin_r=sim_consts.skin_r,
|
||||
skin_r²=sim_consts.skin_r^2,
|
||||
skin_radius=sim_consts.skin_radius,
|
||||
skin_radius²=sim_consts.skin_radius^2,
|
||||
n_snapshots=n_snapshots,
|
||||
ϵσ⁶δtμₜ24=24 * sim_consts.ϵ * sim_consts.σ^6 * sim_consts.δt * sim_consts.μₜ,
|
||||
σ⁶2=2 * sim_consts.σ^6,
|
||||
|
@ -90,8 +90,8 @@ function run_sim(
|
|||
sqrt_Dᵣδt2=sqrt(2 * sim_consts.Dᵣ * sim_consts.δt),
|
||||
v₀δt=sim_consts.v₀ * sim_consts.δt,
|
||||
μₜ=sim_consts.μₜ,
|
||||
interaction_r=sim_consts.interaction_r,
|
||||
interaction_r²=sim_consts.interaction_r^2,
|
||||
interaction_radius=sim_consts.interaction_radius,
|
||||
interaction_radius²=sim_consts.interaction_radius^2,
|
||||
n_particles=sim_consts.n_particles,
|
||||
half_box_len=sim_consts.half_box_len,
|
||||
particles=particles,
|
||||
|
@ -102,7 +102,7 @@ function run_sim(
|
|||
],
|
||||
n_bundle_snapshots=n_bundle_snapshots,
|
||||
bundle=Bundle(sim_consts.n_particles, n_bundle_snapshots),
|
||||
box=gen_cell_list_box(sim_consts.half_box_len, sim_consts.skin_r),
|
||||
box=gen_cell_list_box(sim_consts.half_box_len, sim_consts.skin_radius),
|
||||
show_progress=show_progress,
|
||||
)
|
||||
|
||||
|
|
19
src/setup.jl
19
src/setup.jl
|
@ -51,7 +51,7 @@ function gen_sim_consts(
|
|||
v₀::Float64;
|
||||
δt::Float64=DEFAULT_δt,
|
||||
packing_ratio::Float64=DEFAULT_PACKING_RATIO,
|
||||
skin_to_interaction_r_ratio::Float64=DEFAULT_SKIN_TO_INTERACTION_R_RATIO,
|
||||
skin_to_interaction_radius_ratio::Float64=DEFAULT_SKIN_TO_INTERACTION_R_RATIO,
|
||||
half_box_len::Float64=0.0,
|
||||
)
|
||||
@assert n_particles > 0
|
||||
|
@ -65,17 +65,18 @@ function gen_sim_consts(
|
|||
Dᵣ = 3 * Dₜ / ((2 * particle_radius)^2)
|
||||
σ = 2 * particle_radius * 2^(-1 / 6)
|
||||
ϵ = DEFAULT_ϵ
|
||||
interaction_r = 2^(1 / 6) * σ
|
||||
interaction_radius = 2^(1 / 6) * σ
|
||||
|
||||
skin_r = skin_to_interaction_r_ratio * interaction_r
|
||||
skin_radius = skin_to_interaction_radius_ratio * interaction_radius
|
||||
|
||||
buffer = 2.5
|
||||
max_approach_after_one_integration_step = buffer * (2 * v₀ * δt)
|
||||
@assert skin_r >= interaction_r + max_approach_after_one_integration_step
|
||||
@assert skin_radius >= interaction_radius + max_approach_after_one_integration_step
|
||||
|
||||
if v₀ != 0.0
|
||||
n_steps_before_verlet_list_update = floor(
|
||||
Int64, (skin_r - interaction_r) / max_approach_after_one_integration_step
|
||||
Int64,
|
||||
(skin_radius - interaction_radius) / max_approach_after_one_integration_step,
|
||||
)
|
||||
else
|
||||
n_steps_before_verlet_list_update = 1000
|
||||
|
@ -106,8 +107,8 @@ function gen_sim_consts(
|
|||
Dᵣ,
|
||||
σ,
|
||||
ϵ,
|
||||
interaction_r,
|
||||
skin_r,
|
||||
interaction_radius,
|
||||
skin_radius,
|
||||
n_steps_before_verlet_list_update,
|
||||
grid_n,
|
||||
half_box_len,
|
||||
|
@ -159,7 +160,7 @@ function init_sim(;
|
|||
v₀::Float64,
|
||||
δt::Float64=DEFAULT_δt,
|
||||
packing_ratio::Float64=DEFAULT_PACKING_RATIO,
|
||||
skin_to_interaction_r_ratio::Float64=DEFAULT_SKIN_TO_INTERACTION_R_RATIO,
|
||||
skin_to_interaction_radius_ratio::Float64=DEFAULT_SKIN_TO_INTERACTION_R_RATIO,
|
||||
exports_dir::String=DEFAULT_EXPORTS_DIR,
|
||||
parent_dir::String=DEFAULT_PARENT_DIR,
|
||||
comment::String=DEFAULT_COMMENT,
|
||||
|
@ -170,7 +171,7 @@ function init_sim(;
|
|||
v₀;
|
||||
δt=δt,
|
||||
packing_ratio=packing_ratio,
|
||||
skin_to_interaction_r_ratio=skin_to_interaction_r_ratio,
|
||||
skin_to_interaction_radius_ratio=skin_to_interaction_radius_ratio,
|
||||
half_box_len,
|
||||
)
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ function euler!(
|
|||
p2 = args.particles[id2]
|
||||
|
||||
overlapping, r⃗₁₂, distance² = are_overlapping(
|
||||
p1_c, p2.c, args.interaction_r², args.half_box_len
|
||||
p1_c, p2.c, args.interaction_radius², args.half_box_len
|
||||
)
|
||||
|
||||
state_update_helper_hook!(env_helper, id1, id2, r⃗₁₂)
|
||||
|
|
Loading…
Reference in a new issue