mirror of
https://gitlab.rlp.net/mobitar/ReCo.jl.git
synced 2024-11-08 22:21:08 +00:00
Bundles for resuming simulations
This commit is contained in:
parent
10018160e2
commit
e2f06265df
8 changed files with 208 additions and 151 deletions
|
@ -24,6 +24,5 @@ includet("Particle.jl")
|
||||||
includet("setup.jl")
|
includet("setup.jl")
|
||||||
includet("simulation.jl")
|
includet("simulation.jl")
|
||||||
includet("data.jl")
|
includet("data.jl")
|
||||||
includet("animation.jl")
|
# includet("animation.jl")
|
||||||
includet("postprocess.jl")
|
|
||||||
includet("run.jl")
|
includet("run.jl")
|
|
@ -31,7 +31,7 @@ function pair_correlation(sol, variables)
|
||||||
for j in 1:(variables.N)
|
for j in 1:(variables.N)
|
||||||
if i != j
|
if i != j
|
||||||
for k in 1:n_last_frames
|
for k in 1:n_last_frames
|
||||||
frame = variables.n_frames - k + 1
|
frame = variables.n_snapshots - k + 1
|
||||||
c1 = sol.center[i, frame]
|
c1 = sol.center[i, frame]
|
||||||
c2 = sol.center[j, frame]
|
c2 = sol.center[j, frame]
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ function animate(directory::String, sol::Solution, variables; framerate=0)
|
||||||
π2 = 2 * π
|
π2 = 2 * π
|
||||||
particle_radius = variables.particle_diameter / 2
|
particle_radius = variables.particle_diameter / 2
|
||||||
|
|
||||||
@showprogress 0.6 for frame in 1:(variables.n_frames)
|
@showprogress 0.6 for frame in 1:(variables.n_snapshots)
|
||||||
@simd for i in 1:(variables.N)
|
@simd for i in 1:(variables.N)
|
||||||
circles[][i] = Circle(Point2(sol.center[i, frame]), particle_radius)
|
circles[][i] = Circle(Point2(sol.center[i, frame]), particle_radius)
|
||||||
|
|
||||||
|
|
64
src/data.jl
64
src/data.jl
|
@ -1,52 +1,60 @@
|
||||||
struct Solution
|
struct Bundle
|
||||||
t::Vector{Float64}
|
t::Vector{Float64}
|
||||||
center::Matrix{Vector{Float64}}
|
c::Matrix{Vector{Float64}}
|
||||||
φ::Matrix{Float64}
|
φ::Matrix{Float64}
|
||||||
|
end
|
||||||
|
|
||||||
function Solution(N::Int64, n_frames::Int64)
|
function Bundle(N::Int64, n_snapshots::Int64)
|
||||||
return new(
|
return Bundle(
|
||||||
zeros(n_frames), [zeros(2) for i in 1:N, j in 1:n_frames], zeros((N, n_frames))
|
zeros(n_snapshots),
|
||||||
|
[zeros(2) for i in 1:N, j in 1:n_snapshots],
|
||||||
|
zeros(N, n_snapshots),
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function first_n_snapshots(bundle::Bundle, n::Int64)
|
||||||
|
return Bundle(bundle.t[1:n], bundle.c[:, 1:n], bundle.φ[:, 1:n])
|
||||||
end
|
end
|
||||||
|
|
||||||
function save_frame!(sol, frame, t, particles)
|
function save_snapshot!(
|
||||||
frame += 1
|
bundle::Bundle, n_snapshot::Int64, t::Float64, particles::Vector{Particle}
|
||||||
|
)
|
||||||
|
bundle.t[n_snapshot] = t
|
||||||
|
|
||||||
sol.t[frame] = t
|
bundle_c = bundle.c
|
||||||
|
bundle_φ = bundle.φ
|
||||||
|
|
||||||
@simd for p in particles
|
@simd for p in particles
|
||||||
p_id = p.id
|
p_id = p.id
|
||||||
|
p_c = p.c
|
||||||
|
|
||||||
pre_pos = sol.center[p_id, frame]
|
bundle_c_id = bundle_c[p_id, n_snapshot]
|
||||||
|
|
||||||
@turbo for i in 1:2
|
@turbo for j in 1:2
|
||||||
pre_pos[i] = p.c[i]
|
bundle_c_id[j] = p_c[j]
|
||||||
end
|
end
|
||||||
|
|
||||||
sol.φ[p_id, frame] = p.φ
|
bundle_φ[p_id, n_snapshot] = p.φ
|
||||||
end
|
end
|
||||||
|
|
||||||
return frame
|
|
||||||
end
|
|
||||||
|
|
||||||
function save_data_jld(directory::String; kwargs...)
|
|
||||||
path = "$directory/data.jld2"
|
|
||||||
JLD2.jldsave(path; kwargs...)
|
|
||||||
|
|
||||||
println("Data saved to $path.")
|
|
||||||
|
|
||||||
return nothing
|
return nothing
|
||||||
end
|
end
|
||||||
|
|
||||||
function save_variables(directory::String; kwargs...)
|
function set_status(dir::String, n_bundles::Int64, T::Float64)
|
||||||
path = "$directory/variables.json"
|
open("$dir/status.json", "w") do f
|
||||||
|
JSON3.write(f, Dict("n_bundles" => n_bundles, "T" => round(T; digits=3)))
|
||||||
open(path, "w") do io
|
|
||||||
JSON3.pretty(io, kwargs...)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
println("Variables saved to $path.")
|
return nothing
|
||||||
|
end
|
||||||
|
|
||||||
|
function save_bundle(dir::String, bundle::Bundle, n::Int64, T::Float64)
|
||||||
|
bundle_dir = "$dir/bundles/bundle$n"
|
||||||
|
mkpath(bundle_dir)
|
||||||
|
|
||||||
|
JLD2.save_object("$bundle_dir/bundle.jld2", bundle)
|
||||||
|
|
||||||
|
set_status(dir, n, T)
|
||||||
|
|
||||||
return nothing
|
return nothing
|
||||||
end
|
end
|
|
@ -1,23 +0,0 @@
|
||||||
function postprocess(sol, variables, save_data)
|
|
||||||
if !isdir("exports")
|
|
||||||
mkdir("exports")
|
|
||||||
end
|
|
||||||
|
|
||||||
directory = "exports/$(variables.end_time)_T=$(variables.T)_N=$(variables.N)_v=$(variables.v)"
|
|
||||||
|
|
||||||
if save_data || (variables.framerate > 0)
|
|
||||||
mkdir(directory)
|
|
||||||
|
|
||||||
save_variables(directory; variables=variables)
|
|
||||||
end
|
|
||||||
|
|
||||||
if save_data
|
|
||||||
save_data_jld(directory; sol=sol, variables=variables)
|
|
||||||
end
|
|
||||||
|
|
||||||
if variables.framerate > 0
|
|
||||||
animate(directory, sol, variables)
|
|
||||||
end
|
|
||||||
|
|
||||||
return nothing
|
|
||||||
end
|
|
156
src/run.jl
156
src/run.jl
|
@ -1,108 +1,110 @@
|
||||||
function run(;
|
function run_sim(
|
||||||
N::Int64,
|
dir::String;
|
||||||
T::Int64,
|
duration::Float64,
|
||||||
v::Float64,
|
|
||||||
δt::Float64=1e-5,
|
|
||||||
snapshot_at::Float64=0.1,
|
snapshot_at::Float64=0.1,
|
||||||
framerate::Int64=0,
|
|
||||||
save_data::Bool=true,
|
|
||||||
n_steps_before_verlet_list_update::Int64=1000,
|
n_steps_before_verlet_list_update::Int64=1000,
|
||||||
packing_ratio::Float64=0.5,
|
|
||||||
debug::Bool=false,
|
|
||||||
seed::Int64=42,
|
seed::Int64=42,
|
||||||
|
n_bundle_snapshots::Int64=100,
|
||||||
)
|
)
|
||||||
@assert N > 0
|
@assert length(dir) > 0
|
||||||
@assert T > 0
|
@assert duration > 0
|
||||||
@assert v >= 0
|
@assert snapshot_at in 0.01:0.01:duration
|
||||||
@assert δt > 0
|
|
||||||
@assert snapshot_at ∉ 0.01:0.01:T
|
|
||||||
@assert framerate >= 0
|
|
||||||
@assert n_steps_before_verlet_list_update >= 0
|
@assert n_steps_before_verlet_list_update >= 0
|
||||||
@assert packing_ratio > 0
|
|
||||||
@assert seed > 0
|
@assert seed > 0
|
||||||
|
@assert n_bundle_snapshots >= 0
|
||||||
|
|
||||||
Random.seed!(seed)
|
Random.seed!(seed)
|
||||||
|
|
||||||
μ = 1.0
|
sim_consts = JSON3.read(read("$dir/sim_consts.json", String))
|
||||||
D₀ = 1.0
|
|
||||||
particle_diameter = 1.0
|
|
||||||
Dᵣ = 3 * D₀ / (particle_diameter^2)
|
|
||||||
σ = 1.0
|
|
||||||
ϵ = 100.0
|
|
||||||
interaction_r = 2^(1 / 6) * σ
|
|
||||||
|
|
||||||
grid_n = round(Int64, ceil(sqrt(N)))
|
skin_r =
|
||||||
|
1.1 * (
|
||||||
|
2 * sim_consts.v * n_steps_before_verlet_list_update * sim_consts.δt +
|
||||||
|
2 * sim_consts.interaction_r
|
||||||
|
)
|
||||||
|
|
||||||
N = grid_n^2
|
integration_steps = floor(Int64, duration / sim_consts.δt) + 1
|
||||||
|
n_steps_before_snapshot = round(Int64, snapshot_at / sim_consts.δt)
|
||||||
|
|
||||||
l = sqrt(N * π / packing_ratio) * σ / 4
|
n_snapshots = floor(Int64, integration_steps / n_steps_before_snapshot) + 1
|
||||||
grid_box_width = 2 * l / grid_n
|
|
||||||
|
|
||||||
skin_r = 1.1 * (2 * v * n_steps_before_verlet_list_update * δt + 2 * interaction_r)
|
n_bundle_snapshots = min(n_snapshots, n_bundle_snapshots)
|
||||||
|
|
||||||
integration_steps = floor(Int64, T / δt) + 1
|
|
||||||
n_steps_before_save = round(Int64, snapshot_at / δt)
|
|
||||||
|
|
||||||
n_frames = floor(Int64, integration_steps / n_steps_before_save) + 1
|
|
||||||
|
|
||||||
args = (
|
args = (
|
||||||
v=v,
|
v=sim_consts.v,
|
||||||
c₁=4 * ϵ * 6 * σ^6 * δt * μ,
|
|
||||||
c₂=2 * σ^6,
|
|
||||||
c₃=sqrt(2 * D₀ * δt),
|
|
||||||
c₄=sqrt(2 * Dᵣ * δt),
|
|
||||||
vδt=v * δt,
|
|
||||||
μ=μ,
|
|
||||||
interaction_r=interaction_r,
|
|
||||||
interaction_r²=interaction_r^2,
|
|
||||||
N=N,
|
|
||||||
l=l,
|
|
||||||
particle_diameter=particle_diameter,
|
|
||||||
particles=generate_particles(grid_n, grid_box_width, l),
|
|
||||||
skin_r=skin_r,
|
skin_r=skin_r,
|
||||||
skin_r²=skin_r^2,
|
skin_r²=skin_r^2,
|
||||||
verlet_list=[PreVector(Int64, N - 1) for i in 1:(N - 1)],
|
n_snapshots=n_snapshots,
|
||||||
n_frames=n_frames,
|
c₁=4 * sim_consts.ϵ * 6 * sim_consts.σ^6 * sim_consts.δt * sim_consts.μ,
|
||||||
debug=debug,
|
c₂=2 * sim_consts.σ^6,
|
||||||
|
c₃=sqrt(2 * sim_consts.D₀ * sim_consts.δt),
|
||||||
|
c₄=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,
|
||||||
|
N=sim_consts.N,
|
||||||
|
l=sim_consts.l,
|
||||||
|
particle_diameter=sim_consts.particle_diameter,
|
||||||
|
particles=generate_particles(
|
||||||
|
sim_consts.grid_n, sim_consts.grid_box_width, sim_consts.l
|
||||||
|
),
|
||||||
|
verlet_list=[PreVector{Int64}(sim_consts.N - 1) for i in 1:(sim_consts.N - 1)],
|
||||||
|
n_bundle_snapshots=n_bundle_snapshots,
|
||||||
|
bundle=Bundle(sim_consts.N, n_bundle_snapshots),
|
||||||
)
|
)
|
||||||
|
|
||||||
sol, end_time = simulate(
|
status = JSON3.read(read("$dir/status.json", String))
|
||||||
args, δt, T, n_steps_before_verlet_list_update, n_steps_before_save
|
T0::Float64 = status.T
|
||||||
)
|
|
||||||
|
|
||||||
args = nothing
|
T = T0 + duration
|
||||||
|
|
||||||
variables = (;
|
start_datetime = now()
|
||||||
|
|
||||||
|
run_vars = (;
|
||||||
# Input
|
# Input
|
||||||
N,
|
duration,
|
||||||
T,
|
|
||||||
v,
|
|
||||||
δt,
|
|
||||||
snapshot_at,
|
snapshot_at,
|
||||||
framerate,
|
|
||||||
n_steps_before_verlet_list_update,
|
n_steps_before_verlet_list_update,
|
||||||
packing_ratio,
|
seed,
|
||||||
debug,
|
n_bundle_snapshots,
|
||||||
# Calculated
|
# Calculated
|
||||||
μ,
|
|
||||||
D₀,
|
|
||||||
particle_diameter,
|
|
||||||
Dᵣ,
|
|
||||||
σ,
|
|
||||||
ϵ,
|
|
||||||
interaction_r,
|
|
||||||
grid_n,
|
|
||||||
l,
|
|
||||||
grid_box_width,
|
|
||||||
skin_r,
|
skin_r,
|
||||||
integration_steps,
|
integration_steps,
|
||||||
n_steps_before_save,
|
n_steps_before_snapshot,
|
||||||
n_frames,
|
n_snapshots,
|
||||||
# Output
|
T,
|
||||||
end_time,
|
# Read
|
||||||
|
T0,
|
||||||
|
start_datetime,
|
||||||
)
|
)
|
||||||
|
|
||||||
postprocess(sol, variables, save_data)
|
n_bundles::Int64 = status.n_bundles
|
||||||
|
next_bundle = n_bundles + 1
|
||||||
|
next_bundle_path = "$dir/bundles/bundle$next_bundle"
|
||||||
|
mkpath(next_bundle_path)
|
||||||
|
|
||||||
return (; sol, variables)
|
if n_bundle_snapshots > 0
|
||||||
|
save_data = true
|
||||||
|
|
||||||
|
open("$next_bundle_path/run_vars.json", "w") do f
|
||||||
|
JSON3.pretty(f, run_vars)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
save_data = false
|
||||||
|
end
|
||||||
|
|
||||||
|
simulate(
|
||||||
|
args,
|
||||||
|
sim_consts.δt,
|
||||||
|
T0,
|
||||||
|
T,
|
||||||
|
n_steps_before_verlet_list_update,
|
||||||
|
n_steps_before_snapshot,
|
||||||
|
n_bundles,
|
||||||
|
dir,
|
||||||
|
save_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
return dir
|
||||||
end
|
end
|
65
src/setup.jl
65
src/setup.jl
|
@ -1,14 +1,11 @@
|
||||||
function initial_particle_grid_pos(i, j; grid_box_width, l)
|
function initial_particle_grid_pos(i, j; grid_box_width, l)
|
||||||
dim1_pos(x) = (x - 0.5) * grid_box_width - l
|
term = -0.5 * grid_box_width - l
|
||||||
|
return [k * grid_box_width + term for k in (i, j)]
|
||||||
return SVector(dim1_pos(i), dim1_pos(j))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function generate_particles(grid_n, grid_box_width, l)
|
function generate_particles(grid_n, grid_box_width, l)
|
||||||
particles = Vector{Particle}(undef, grid_n^2)
|
particles = Vector{Particle}(undef, grid_n^2)
|
||||||
|
|
||||||
particle_pos_in_grid_dim(i) = (i - 0.5) * grid_box_width - l
|
|
||||||
|
|
||||||
id = 1
|
id = 1
|
||||||
|
|
||||||
for i in 1:grid_n
|
for i in 1:grid_n
|
||||||
|
@ -25,3 +22,61 @@ function generate_particles(grid_n, grid_box_width, l)
|
||||||
|
|
||||||
return particles
|
return particles
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function init_sim(;
|
||||||
|
N::Int64, v::Float64, δt::Float64=1e-5, packing_ratio::Float64=0.5, comment::String=""
|
||||||
|
)
|
||||||
|
@assert N > 0
|
||||||
|
@assert v >= 0
|
||||||
|
@assert δt in 1e-7:1e-7:1e-4
|
||||||
|
@assert packing_ratio > 0
|
||||||
|
|
||||||
|
μ = 1.0
|
||||||
|
D₀ = 1.0
|
||||||
|
particle_diameter = 1.0
|
||||||
|
Dᵣ = 3 * D₀ / (particle_diameter^2)
|
||||||
|
σ = 1.0
|
||||||
|
ϵ = 100.0
|
||||||
|
interaction_r = 2^(1 / 6) * σ
|
||||||
|
|
||||||
|
grid_n = round(Int64, ceil(sqrt(N)))
|
||||||
|
|
||||||
|
N = grid_n^2
|
||||||
|
|
||||||
|
l = sqrt(N * π / packing_ratio) * σ / 4
|
||||||
|
grid_box_width = 2 * l / grid_n
|
||||||
|
|
||||||
|
sim_consts = (;
|
||||||
|
# Input
|
||||||
|
N,
|
||||||
|
v,
|
||||||
|
δt,
|
||||||
|
packing_ratio,
|
||||||
|
# Calculated
|
||||||
|
μ,
|
||||||
|
D₀,
|
||||||
|
particle_diameter,
|
||||||
|
Dᵣ,
|
||||||
|
σ,
|
||||||
|
ϵ,
|
||||||
|
interaction_r,
|
||||||
|
grid_n,
|
||||||
|
l,
|
||||||
|
grid_box_width,
|
||||||
|
)
|
||||||
|
|
||||||
|
particles = generate_particles(grid_n, grid_box_width, l)
|
||||||
|
bundle = Bundle(N, 1)
|
||||||
|
save_snapshot!(bundle, 1, 0.0, particles)
|
||||||
|
|
||||||
|
dir = "exports/$(now())_N=$(N)_v=$(v)_#$(rand(1000:9999))$comment"
|
||||||
|
mkpath(dir)
|
||||||
|
|
||||||
|
open("$dir/sim_consts.json", "w") do f
|
||||||
|
JSON3.pretty(f, sim_consts)
|
||||||
|
end
|
||||||
|
|
||||||
|
save_bundle(dir, bundle, 1, 0.0)
|
||||||
|
|
||||||
|
return dir
|
||||||
|
end
|
|
@ -66,22 +66,30 @@ end
|
||||||
function simulate(
|
function simulate(
|
||||||
args,
|
args,
|
||||||
δt::Float64,
|
δt::Float64,
|
||||||
T::Int64,
|
T0::Float64,
|
||||||
|
T::Float64,
|
||||||
n_steps_before_verlet_list_update::Int64,
|
n_steps_before_verlet_list_update::Int64,
|
||||||
n_steps_before_save::Int64,
|
n_steps_before_snapshot::Int64,
|
||||||
|
n_bundles::Int64,
|
||||||
|
dir::String,
|
||||||
|
save_data::Bool,
|
||||||
)
|
)
|
||||||
sol = Solution(args.N, args.n_frames)
|
bundle_snapshot_counter = 0
|
||||||
|
|
||||||
frame = 0
|
|
||||||
|
|
||||||
frame = save_frame!(sol, frame, 0.0, args.particles)
|
|
||||||
|
|
||||||
start_time = now()
|
start_time = now()
|
||||||
println("Started simulation at $start_time.")
|
println("Started simulation at $start_time.")
|
||||||
|
|
||||||
@showprogress 0.6 for (integration_step, t) in enumerate(0:δt:T)
|
@showprogress 0.6 for (integration_step, t) in enumerate(T0:δt:T)
|
||||||
if integration_step % n_steps_before_save == 0
|
if (integration_step % n_steps_before_snapshot == 0) && save_data
|
||||||
frame = save_frame!(sol, frame, t, args.particles)
|
bundle_snapshot_counter += 1
|
||||||
|
save_snapshot!(args.bundle, bundle_snapshot_counter, t, args.particles)
|
||||||
|
|
||||||
|
if bundle_snapshot_counter == args.n_bundle_snapshots
|
||||||
|
bundle_snapshot_counter = 0
|
||||||
|
n_bundles += 1
|
||||||
|
|
||||||
|
save_bundle(dir, args.bundle, n_bundles, t)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if integration_step % n_steps_before_verlet_list_update == 0
|
if integration_step % n_steps_before_verlet_list_update == 0
|
||||||
|
@ -91,9 +99,17 @@ function simulate(
|
||||||
euler!(args)
|
euler!(args)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if bundle_snapshot_counter > 0
|
||||||
|
bundle = first_n_snapshots(args.bundle, bundle_snapshot_counter)
|
||||||
|
|
||||||
|
n_bundles += 1
|
||||||
|
|
||||||
|
save_bundle(dir, bundle, n_bundles, T)
|
||||||
|
end
|
||||||
|
|
||||||
end_time = now()
|
end_time = now()
|
||||||
elapsed_time = canonicalize(CompoundPeriod(end_time - start_time))
|
elapsed_time = canonicalize(CompoundPeriod(end_time - start_time))
|
||||||
println("Simulation done at $end_time and took $elapsed_time.")
|
println("Simulation done at $end_time and took $elapsed_time.")
|
||||||
|
|
||||||
return (; sol, end_time)
|
return nothing
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue