From eab5f7472b0c96e7511f6758551751c8b886016f Mon Sep 17 00:00:00 2001 From: Mo8it Date: Tue, 5 Apr 2022 03:22:39 +0200 Subject: [PATCH] Separate Luxor and CairoMakie graphics --- graphics/CairoMakie_graphics/Project.toml | 4 + .../elliptical_distance.jl | 31 +++++ graphics/CairoMakie_graphics/potential.jl | 60 ++++++++ .../CairoMakie_graphics/reward_shaping.jl | 29 ++++ graphics/Luxor_graphics/Project.toml | 5 + graphics/Luxor_graphics/center_of_mass.jl | 130 ++++++++++++++++++ .../periodic_boundary_conditions.jl | 115 ++++++++++++++++ .../Luxor_graphics/radial_distribution.jl | 87 ++++++++++++ .../Luxor_graphics/verlet_and_cell_lists.jl | 96 +++++++++++++ 9 files changed, 557 insertions(+) create mode 100644 graphics/CairoMakie_graphics/Project.toml create mode 100644 graphics/CairoMakie_graphics/elliptical_distance.jl create mode 100644 graphics/CairoMakie_graphics/potential.jl create mode 100644 graphics/CairoMakie_graphics/reward_shaping.jl create mode 100644 graphics/Luxor_graphics/Project.toml create mode 100644 graphics/Luxor_graphics/center_of_mass.jl create mode 100644 graphics/Luxor_graphics/periodic_boundary_conditions.jl create mode 100644 graphics/Luxor_graphics/radial_distribution.jl create mode 100644 graphics/Luxor_graphics/verlet_and_cell_lists.jl diff --git a/graphics/CairoMakie_graphics/Project.toml b/graphics/CairoMakie_graphics/Project.toml new file mode 100644 index 0000000..8794b62 --- /dev/null +++ b/graphics/CairoMakie_graphics/Project.toml @@ -0,0 +1,4 @@ +[deps] +CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" +LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" +ReCo = "b25f7548-fcc9-4c91-bc24-841b54f4dd54" diff --git a/graphics/CairoMakie_graphics/elliptical_distance.jl b/graphics/CairoMakie_graphics/elliptical_distance.jl new file mode 100644 index 0000000..e585ec7 --- /dev/null +++ b/graphics/CairoMakie_graphics/elliptical_distance.jl @@ -0,0 +1,31 @@ +using CairoMakie +using LaTeXStrings: @L_str + +include("../src/Visualization/common_CairoMakie.jl") + +function gen_elliptical_distance_graphics() + init_cairomakie!() + + fig = gen_figure() + + ax = Axis(fig[1, 1]; xlabel=L"x", ylabel=L"y") + + elliptical_b_a_ratio = 0.4 + as = 1:1:3 + + for a in as + x = collect(LinRange(-a, a, 1000)) + y = @. sqrt(a^2 - x^2) * elliptical_b_a_ratio + append!(x, reverse(x)) + append!(y, reverse(-y)) + lines!(x, y; label=L"a = %$a") + end + + axislegend(ax; position=:rt, padding=3, rowgap=-3) + + set_gaps!(fig) + + save_fig("elliptical_distance.pdf", fig) + + return nothing +end diff --git a/graphics/CairoMakie_graphics/potential.jl b/graphics/CairoMakie_graphics/potential.jl new file mode 100644 index 0000000..3063458 --- /dev/null +++ b/graphics/CairoMakie_graphics/potential.jl @@ -0,0 +1,60 @@ +using CairoMakie +using LaTeXStrings: @L_str + +include("../src/Visualization/common_CairoMakie.jl") + +const minimum_r_σ_ratio = 2^(1 / 6) + +function U_LJ_ϵ_ratio(r_σ_ratio::Real) + σ_r_ratio⁶ = r_σ_ratio^(-6) + return 4 * (σ_r_ratio⁶^2 - σ_r_ratio⁶) +end + +function U_WCA_ϵ_ratio(r_σ_ratio::Real) + if r_σ_ratio > minimum_r_σ_ratio + return zero(r_σ_ratio) + else + return U_LJ_ϵ_ratio(r_σ_ratio) + 1 + end +end + +function plot_potentials() + init_cairomakie!() + + fig = gen_figure() + + max_x = 2.5 + + max_y = 1.05 + min_y = -max_y + + ax = Axis( + fig[1, 1]; xlabel=L"r / σ", ylabel=L"U(r) / ϵ", limits=(0.88, max_x, min_y, max_y) + ) + + r_σ_ratio = LinRange(0.95, max_x, 1000) + + LJ = lines!(ax, r_σ_ratio, U_LJ_ϵ_ratio.(r_σ_ratio)) + + WCA = lines!(ax, r_σ_ratio, U_WCA_ϵ_ratio.(r_σ_ratio)) + + minimum_r_σ_ratio_line = lines!( + ax, + [minimum_r_σ_ratio, minimum_r_σ_ratio], + [min_y, max_y]; + linestyle=:dash, + linewidth=1, + ) + + Legend( + fig[1, 2], + [LJ, WCA, minimum_r_σ_ratio_line], + [L"U_{LJ}", L"U_{WCA}", L"\frac{r}{σ} = 2^{1/6}"], + ) + + set_gaps!(fig) + + save_fig("potential.pdf", fig) + + return nothing +end diff --git a/graphics/CairoMakie_graphics/reward_shaping.jl b/graphics/CairoMakie_graphics/reward_shaping.jl new file mode 100644 index 0000000..f22cf62 --- /dev/null +++ b/graphics/CairoMakie_graphics/reward_shaping.jl @@ -0,0 +1,29 @@ +using CairoMakie +using LaTeXStrings: @L_str + +using ReCo: ReCo + +include("../src/Visualization/common_CairoMakie.jl") + +function plot_reward_function() + init_cairomakie!() + + fig = gen_figure() + + min_x = 0.0 + max_x = 1.15 + + ax = Axis( + fig[1, 1]; xlabel=L"x / x_{\max}", ylabel=L"R(x)", limits=(min_x, max_x, 0.0, 1.05) + ) + + x = LinRange(min_x, max_x, 1000) + + lines!(ax, x, ReCo.RL.minimizing_reward.(x, 1.0)) + + set_gaps!(fig) + + save_fig("reward_shaping.pdf", fig) + + return nothing +end diff --git a/graphics/Luxor_graphics/Project.toml b/graphics/Luxor_graphics/Project.toml new file mode 100644 index 0000000..ed52a6a --- /dev/null +++ b/graphics/Luxor_graphics/Project.toml @@ -0,0 +1,5 @@ +[deps] +Luxor = "ae8d54c2-7ccd-5906-9d76-62fc9837b5bc" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +ReCo = "b25f7548-fcc9-4c91-bc24-841b54f4dd54" +StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" diff --git a/graphics/Luxor_graphics/center_of_mass.jl b/graphics/Luxor_graphics/center_of_mass.jl new file mode 100644 index 0000000..9967b78 --- /dev/null +++ b/graphics/Luxor_graphics/center_of_mass.jl @@ -0,0 +1,130 @@ +using Luxor + +using ReCo: ReCo + +function gen_COM_graphics() + box_length = 100 + box_height = 100 + + L = 0.39 * box_length + + R = 0.37 * box_length + + A = -0.9 * L + B = 0.65 * L + particle_radius = 0.05 * L + + Ap_vec = Vector(ReCo.Shape.project_to_unit_circle(A, L)) + Bp_vec = Vector(ReCo.Shape.project_to_unit_circle(B, L)) + for p in (Ap_vec, Bp_vec) + p[2] *= -1 + end + + Ap = Point(Ap_vec[1], Ap_vec[2]) + Bp = Point(Bp_vec[1], Bp_vec[2]) + + M = R * ((Ap + Bp) / 2) + + θ = atan(-M[2], M[1]) + + COM = ReCo.Shape.project_back_from_unit_circle(θ, L) + si, co = sincos(θ) + COMp = R * Point(co, -si) + + ## + + graphics_export_dir = "exports/graphics/COM" + mkpath(graphics_export_dir) + + Drawing(box_length, box_height, "$graphics_export_dir/linear.pdf") + origin() + fontsize(5) + + setcolor("black") + arrow(Point(-1.1 * L, 0), Point(1.2 * L, 0); arrowheadlength=0.1 * L, linewidth=1.0) + + green_orange = blend(Point(-1.5 * L, 0), Point(1.5 * L, 0)) + addstop(green_orange, 0.0, "orange") + addstop(green_orange, (L) / (3 * L), "green") + addstop(green_orange, (2 * L) / (3 * L), "orange") + addstop(green_orange, 1.0, "green") + setblend(green_orange) + setline(1.0) + line(Point(-L, 0), Point(L, 0), :stroke) + + setcolor("red") + setline(0.5) + for x in (-L, L) + line(Point(x, 0.05 * L), Point(x, -0.05 * L), :stroke) + end + + setcolor("cyan3") + line(Point(0, 0.05 * L), Point(0, -0.05 * L), :stroke) + + setcolor("blue") + for p in (A, B) + circle(Point(p, 0), particle_radius, :fill) + end + text("A", Point(A - 0.030 * L, -0.08 * L)) + text("B", Point(B - 0.030 * L, -0.08 * L)) + + setcolor("brown") + circle(Point(COM, 0), particle_radius, :fill) + text("COM", Point(COM - 0.098 * L, -0.08 * L)) + + setcolor("black") + text("x", Point(1.2 * L, 0.038 * L)) + text("-L/2", Point(-L - 0.15 * L, 0.20 * L)) + text("0", Point(0 - 0.030 * L, 0.18 * L)) + text("+L/2", Point(L - 0.15 * L, 0.20 * L)) + + finish() + + ## + + Drawing(box_length, box_height, "$graphics_export_dir/circular_projection.pdf") + origin() + fontsize(5) + + arrow(Point(-1.2 * R, 0), Point(1.2 * R, 0); arrowheadlength=0.1 * R, linewidth=1.0) + arrow(Point(0, 1.2 * R), Point(0, -1.2 * R); arrowheadlength=0.1 * R, linewidth=1.0) + + setcolor("black") + text("α", Point(1.22 * R, 0.035 * R)) + text("β", Point(-0.04 * R, -1.23 * R)) + + green_orange = blend(Point(0, -R), Point(0, R), "green", "orange") + setblend(green_orange) + setline(1.0) + circle(Point(0, 0), R, :stroke) + + setcolor("red") + setline(0.5) + line(Point(1.05 * R, 0), Point(0.95 * R, 0), :stroke) + setcolor("cyan3") + line(Point(-1.05 * R, 0), Point(-0.95 * R, 0), :stroke) + + setcolor("blue") + for pp in (Ap, Bp) + circle(R * pp, particle_radius, :fill) + end + text("A", 1.07 * R * Ap) + text("B", 1.14 * R * Bp) + + setcolor("black") + setdash("dot") + line(R * Ap, R * Bp, :stroke) + line(Point(0, 0), COMp, :stroke) + + setcolor("purple1") + circle(M, particle_radius, :fill) + text("COM'", 0.019 * R * M + R * Point(0.0, -0.04)) + + setcolor("brown") + circle(COMp, particle_radius, :fill) + text("COM", 0.029 * R * COMp) + + finish() + + return nothing +end diff --git a/graphics/Luxor_graphics/periodic_boundary_conditions.jl b/graphics/Luxor_graphics/periodic_boundary_conditions.jl new file mode 100644 index 0000000..34d489c --- /dev/null +++ b/graphics/Luxor_graphics/periodic_boundary_conditions.jl @@ -0,0 +1,115 @@ +using Luxor +using Random: Random +using StaticArrays: SVector + +using ReCo: ReCo + +function gen_periodic_boundary_conditions_graphics() + Random.seed!(23) + + drawing_box_length = 300 + + graphics_export_dir = "exports/graphics" + mkpath(graphics_export_dir) + + Drawing( + drawing_box_length, + drawing_box_length, + "$graphics_export_dir/periodic_boundary_conditions.pdf", + ) + origin() + + particle_radius = 10 + box_len = drawing_box_length / 3 + half_box_len = box_len / 2 + + N_in_one_box = 5 + + colors = ["red", "blue", "orange", "green", "cyan"] + + distance_limit = 0.99 * 2 * particle_radius + + particles = Vector{ReCo.Particle}(undef, 9 * N_in_one_box) + translation_vecs = [ + SVector(0.0, 0.0), + SVector(box_len, 0.0), + SVector(box_len, box_len), + SVector(0.0, box_len), + SVector(-box_len, box_len), + SVector(-box_len, 0.0), + SVector(-box_len, -box_len), + SVector(0.0, -box_len), + SVector(box_len, -box_len), + ] + + p1_c = SVector(0.0, 0.0) + + for p1_ind in 1:N_in_one_box + while true + x = (rand() - 0.5) * (box_len - 2 * particle_radius) + y = (rand() - 0.5) * (box_len - 2 * particle_radius) + + p1_c = SVector(x, y) + + no_collision = true + + for p2_ind in 1:(p1_ind - 1) + if ReCo.norm2d(p1_c - particles[p2_ind].c) < distance_limit + no_collision = false + + break + end + end + + if no_collision + break + end + end + + setcolor(colors[p1_ind]) + for box_ind in 1:9 + c = p1_c + translation_vecs[box_ind] + particle = ReCo.Particle(0, c, 0.0) + particles[p1_ind * box_ind] = particle + circle(c[1], c[2], particle_radius, :fill) + end + end + + setcolor("black") + setline(1.0) + for line_factor in (-3, -1, 1, 3) + line( + Point(line_factor * drawing_box_length / 6, drawing_box_length / 2), + Point(line_factor * drawing_box_length / 6, -drawing_box_length / 2), + :stroke, + ) + line( + Point(drawing_box_length / 2, line_factor * drawing_box_length / 6), + Point(-drawing_box_length / 2, line_factor * drawing_box_length / 6), + :stroke, + ) + end + + p1_ind = 3 + p2_ind = 5 + + p1_c = particles[p1_ind].c + p2_c = particles[p2_ind].c + normal_vec_form_p1_to_p2 = p2_c - p1_c + min_image_vec = ReCo.restrict_coordinates(normal_vec_form_p1_to_p2, half_box_len) + min_image_vec_from_p1 = p1_c + min_image_vec + + setcolor("black") + arrow(Point(p1_c[1], p1_c[2]), Point(p2_c[1], p2_c[2]); linewidth=2.0) + + setcolor("red") + arrow( + Point(p1_c[1], p1_c[2]), + Point(min_image_vec_from_p1[1], min_image_vec_from_p1[2]); + linewidth=2.0, + ) + + finish() + + return nothing +end diff --git a/graphics/Luxor_graphics/radial_distribution.jl b/graphics/Luxor_graphics/radial_distribution.jl new file mode 100644 index 0000000..e7a1648 --- /dev/null +++ b/graphics/Luxor_graphics/radial_distribution.jl @@ -0,0 +1,87 @@ +using Luxor +using Random: Random +using StaticArrays: SVector + +using ReCo: ReCo + +function gen_rdf_graphics() + Random.seed!(1) + + box_length = 100 + + graphics_export_dir = "exports/graphics" + mkpath(graphics_export_dir) + + Drawing(box_length, box_length, "$graphics_export_dir/rdf_shells.pdf") + origin() + + particle_radius = 6 + Δr = 2.4 * particle_radius + + setcolor("blue") + circle(Point(0, 0), particle_radius, :fill) + + N = 50 + + selected_shell_ind = 3 + selected_lower_radius = (selected_shell_ind - 1) * Δr + + particle_cs = Vector{SVector{2,Float64}}(undef, N) + + distance_limit = 0.99 * 2 * particle_radius + + x = y = distance = 0.0 + + for p1_ind in 1:N + while true + x = (rand() - 0.5) * box_length + y = (rand() - 0.5) * box_length + + p1_c = SVector(x, y) + + distance = ReCo.norm2d(p1_c) + + no_collision = true + + if distance >= distance_limit + for p2_ind in 1:(p1_ind - 1) + if ReCo.norm2d(p1_c - particle_cs[p2_ind]) < distance_limit + no_collision = false + + break + end + end + + if no_collision + particle_cs[p1_ind] = p1_c + break + end + end + end + + if selected_lower_radius <= distance < selected_lower_radius + Δr + setcolor("green") + else + setcolor("orange") + end + + circle(x, y, particle_radius, :fill) + end + + setcolor("black") + setline(0.2) + for shell_ind in 1:ceil(Int64, (box_length - 1) / 2 / Δr) + circle(Point(0, 0), shell_ind * Δr, :stroke) + end + + setcolor("red") + setline(0.3) + line(Point(0, 0), Point(Δr, 0), :stroke) + + fontsize(4.5) + text("Δr", Point(0.44 * Δr, -0.05 * Δr)) + + finish() + + return nothing +end diff --git a/graphics/Luxor_graphics/verlet_and_cell_lists.jl b/graphics/Luxor_graphics/verlet_and_cell_lists.jl new file mode 100644 index 0000000..1dbd019 --- /dev/null +++ b/graphics/Luxor_graphics/verlet_and_cell_lists.jl @@ -0,0 +1,96 @@ +using Luxor +using Random: Random +using StaticArrays: SVector + +using ReCo: ReCo + +function gen_verlet_and_cell_lists_graphics() + Random.seed!(3) + + box_length = 100 + + graphics_export_dir = "exports/graphics" + mkpath(graphics_export_dir) + + Drawing(box_length, box_length, "$graphics_export_dir/verlet_and_cell_lists.pdf") + origin() + + R_particle = 4.2 + σ = 2 * R_particle * 2^(-1 / 6) + R_interaction = 2^(1 / 6) * σ + R_skin = ReCo.DEFAULT_SKIN_TO_INTERACTION_RADIUS_RATIO * R_interaction + + setcolor("blue") + reference_particle_x = 0.25 * R_skin + reference_particle_y = -0.1 * R_skin + circle(Point(reference_particle_x, reference_particle_y), R_particle, :fill) + reference_particle_c = SVector(reference_particle_x, reference_particle_y) + + N = 107 + + particle_cs = Vector{SVector{2,Float64}}(undef, N) + + distance_limit = 0.98 * 2 * R_particle + + x = y = distance = 0.0 + + for p1_ind in 1:N + while true + x = (rand() - 0.5) * box_length + y = (rand() - 0.5) * box_length + + p1_c = SVector(x, y) + + distance = ReCo.norm2d(p1_c - reference_particle_c) + + no_collision = true + + if distance >= distance_limit + for p2_ind in 1:(p1_ind - 1) + if ReCo.norm2d(p1_c - particle_cs[p2_ind]) < distance_limit + no_collision = false + + break + end + end + + if no_collision + particle_cs[p1_ind] = p1_c + break + end + end + end + + if distance < R_interaction + setcolor("red") + elseif R_interaction <= distance < R_skin + setcolor("green") + else + setcolor("orange") + end + + circle(x, y, R_particle, :fill) + end + + setcolor("black") + setline(0.28) + for R in (R_interaction, R_skin) + circle(Point(reference_particle_x, reference_particle_y), R, :stroke) + end + + half_n_lines = floor(Int64, box_length / (2 * R_skin) + 0.5) + for i in 1:half_n_lines + coordinate = (i - 0.5) * R_skin + line(Point(coordinate, -box_length), Point(coordinate, box_length), :stroke) + line(Point(-coordinate, -box_length), Point(-coordinate, box_length), :stroke) + line(Point(-box_length, coordinate), Point(box_length, coordinate), :stroke) + line(Point(-box_length, -coordinate), Point(box_length, -coordinate), :stroke) + end + + setcolor((0.2, 0.0, 1.0, 0.3)) + rect(-1.5 * R_skin, -1.5 * R_skin, 3 * R_skin, 3 * R_skin, :fill) + + finish() + + return nothing +end