diff --git a/CHANGELOG.md b/CHANGELOG.md index 509ad8a93b98fa2f8f958afe2f7ebea813cde81c..7866172342322b2fc9b53f16d4493a3e6f5bccf4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## v0.3.12 + - bugfix: particletype for POLOContainers fixed + - bugfix: ParticleContainers can now safely return distinct objects on succesive calls of alldynamicobjects (as originally intended) + - bugfix: a default full serialization condition interval for the global RNG has been added (the condition is `false`) + - added convenience functions for data file handling + ## v0.3.11 - bugfix: boxing for 3D inverted DiskObstacles has been fixed - fallback constructors for obstacles with `inverted` field now work without having to specify type parameters diff --git a/Project.toml b/Project.toml index b3b97c01d1156629452aa4b370a71c5eadf7315c..507e18aa3b461c1ac55b36b718006ac3eaad02c0 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "InPartS" uuid = "f768f48f-0d8a-415b-80aa-7de5ff9b8474" authors = ["Lukas Hupe <lukas.hupe@ds.mpg.de>", "Jonas Isensee <jonas.isensee@ds.mpg.de>", "Philip Bittihn <philip.bittihn@ds.mpg.de>"] -version = "0.3.11" +version = "0.3.12" [deps] FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" diff --git a/src/evolve.jl b/src/evolve.jl index 3b6c385c89b3bcfb21f7d2cc7762c23836aacedd..69090c589d255d8a1322d886b5e78b577273fce3 100644 --- a/src/evolve.jl +++ b/src/evolve.jl @@ -113,13 +113,13 @@ function propagate!(sim::Simulation, dt) iter2 = alldynamicobjects(sim) if isthreaded(sim) Threads.@threads for n in eachindex(iter2) - particle = iter[n] + particle = iter2[n] fold_back!(particle, sim.domain) reset!(particle, sim) end else for n in eachindex(iter2) - particle = iter[n] + particle = iter2[n] fold_back!(particle, sim.domain) reset!(particle, sim) end diff --git a/src/export/generic.jl b/src/export/generic.jl index 176cb88c25cf8c3ad9722c4a39bab8a7bc8031bc..20da7757358f487d6896531d14e328e1783b966b 100644 --- a/src/export/generic.jl +++ b/src/export/generic.jl @@ -1,31 +1,37 @@ export SaveCallback, BackupCallback, readsim ## Datafile interface definitions -""" - dfopen(backend, filename; kwargs...) - dfopen(backend, filename, mode::String) -Open the data file at `filename`. -Mode specifications follow [`Base.open`](@ref). """ -dfopen(type::Type, filename::String, mode::String) = dfopen(type, filename; modetoflags(mode)...) -dfopen(@nospecialize(type::Type), filename::String; kwargs...) = error("Unknown export backend: $type") - -function dfopen(filename::String, mode::String="r") + exportbackend(filename) +A bit of sugar around `FileIO.query`. +""" +function backend(filename::String) s = FileIO.query(filename) modulename = typeof(s).parameters[1].parameters[1] if !isdefined(Main, modulename) error("File appears to be a $modulename file but library is not loaded.") end if modulename == :JLD2 - return dfopen(JLD2.JLDFile, filename, mode) + return JLD2.JLDFile elseif modulename == :HDF5 - return dfopen(H5Wrapper, filename, mode) + return H5Wrapper else error("This backend is not implemented") end end +""" + dfopen(backend, filename; kwargs...) + dfopen(backend, filename, mode::String) +Open the data file at `filename`. + +Mode specifications follow [`Base.open`](@ref). +""" +dfopen(type::Type, filename::String, mode::String) = dfopen(type, filename; modetoflags(mode)...) +dfopen(@nospecialize(type::Type), filename::String; kwargs...) = error("Unknown export backend: $type") +dfopen(filename::String, mode::String="r") = dfopen(backend(filename), filename, mode) + function dfopen(f::Function, args...; kwargs...) file = dfopen(args...; kwargs...) try @@ -88,7 +94,7 @@ mutable struct SaveCallback{FT, CB<:AbstractCallback, FN<:Function} <: AbstractC end """ - SaveCallback(backend, filename; [interval = 1.0], [offset = 0.0], [dumprng = (s, sim) -> (s.nextsnap % 10 == 0)], [warn = true]) + SaveCallback([backend], filename; [interval = 1.0], [offset = 0.0], [dumprng = (s, sim) -> (s.nextsnap % 10 == 0)], [warn = true]) Create a [`SaveCallback`](@ref) that periodically saves simulation snapshots to `filename`. Uses a [`PeriodicCallback`](@ref) with the given `interval` and `offset`. @@ -96,6 +102,7 @@ Uses a [`PeriodicCallback`](@ref) with the given `interval` and `offset`. SaveCallback(backend, filename; interval = 1.0, offset = 0.0, dumprng = (s, sim) -> _defaultdumprng(sim.rng, s), warn = true) = SaveCallback{backend}(PeriodicCallback(sim -> true, interval; offset = offset), filename, dumprng, warn) +SaveCallback(filename::String; kwargs...) = SaveCallback(backend(filename), filename; kwargs...) function (s::SaveCallback)(sim::Simulation) if !s.initialized @@ -111,6 +118,8 @@ function (s::SaveCallback)(sim::Simulation) end # Xoshiros are small and can be dumped every snapshot, MersenneTwisters are huge and shouldn't be written as often +# the GLOBAL_RNG can't be properly serialized anyway so we just give up +_defaultdumprng(::Random._GLOBAL_RNG) = false _defaultdumprng(::Random.Xoshiro, _) = true _defaultdumprng(::Random.MersenneTwister, s) = (s.nextsnap % 10 == 0) @@ -182,6 +191,8 @@ Uses a [`RealTimeCallback`](@ref) with the given `interval` and `offset`. """ BackupCallback(backend, filename; interval = 300.0, offset = 0.0, warn = true) = BackupCallback{backend}(RealTimeCallback(interval, sim -> true; offset = offset), filename, warn) +BackupCallback(filename::String; kwargs...) = + BackupCallback(backend(filename), filename; kwargs...) function(cb::BackupCallback{FT})(sim::Simulation) where FT @@ -403,7 +414,7 @@ end ## Convenience function for reading things """ - readsim(backend, filename; snap, [warn = true], [kwargs...]) + readsim(filename; snap, [warn = true], [kwargs...]) readsim(f; snap, [warn = true], [kwargs...]) Read a simulation from file and load the specified snapshot. @@ -420,8 +431,8 @@ function readsim(f; snap, warn = true, kwargs...) return sim end -function readsim(backend, filename; kwargs...) - f = dfopen(backend, filename, "r") +function readsim(filename::AbstractString; kwargs...) + f = dfopen(filename, "r") sim = missing try sim = readsim(f; kwargs...) @@ -649,6 +660,12 @@ function readsnap!(sim::Simulation, snapgroup; warn::Bool = true) return sim end +function readsnap!(sim::Simulation, filename::String, snap; kwargs...) + dfopen(filename) do f + readsnap!(sim, f, snap; kwargs...) + end +end + function readsnap!(sim::Simulation, f, snap; warn::Bool=true) if length(keys(f)) == 1 legacy_readsnap!(sim, f, snap; warn=warn) @@ -665,6 +682,7 @@ function numsnaps(f) length(keys(f[SNAPGROUPNAME])) end end +numsnaps(filename::String) = dfopen(numsnaps, filename) ## Stuff @@ -676,8 +694,11 @@ function nextsnapname(g) return snaps[end] + 1 end - -function latest_full_snap(f) +""" + lastfullsnap(f) +Returns the index of the last full snapshot (including RNG) in the file `f`. +""" +function lastfullsnap(f) for n = (numsnaps(f)-1):-1:0 if haskey(f[SNAPGROUPNAME][string(n)], "rng") return n @@ -685,6 +706,13 @@ function latest_full_snap(f) end return -1 end +lastfullsnap(filename::String) = dfopen(lastfullsnap, filename) + +function latest_full_snap(f) + Base.depwarn("`$(@__MODULE__).latest_full_snap` is deprecated. \ + Use `$(@__MODULE__).lastfullsnap` instead", :latest_full_snap) + return lastfullsnap(f) +end ## RNG stuff diff --git a/src/particlecontainers/polocontainer.jl b/src/particlecontainers/polocontainer.jl index a91d84059f6d83aedc45f9764f5b5d25351f6763..44202a2c775f3283c568d5cd2f361aef4cd5aeef 100644 --- a/src/particlecontainers/polocontainer.jl +++ b/src/particlecontainers/polocontainer.jl @@ -50,7 +50,7 @@ Base.append!(pc::POLOContainer, xs) = append!(pc.pv, xs) particles(sim::Simulation{<:POLOContainer}) = sim.particles.pv particles(pc::POLOContainer) = pc.pv -particletype(::POLOContainer{PT}) where PT = PT +particletype(::POLOContainer{<:Any, PT}) where PT = PT flushadditions!(pc::POLOContainer, ab::Vector) = flushadditions!(pc.pv, ab) flushdeletions!(pc::POLOContainer, db) = flushdeletions!(pc.pv, db) findbyid(pc::POLOContainer, id) = findbyid(pc.pv, id)