JuliaDynamics / Agents.jl

Agent-based modeling framework in Julia
https://juliadynamics.github.io/Agents.jl/stable/
MIT License
725 stars 117 forks source link

Crash when trying to create more than a thousand agents in a 3d space continous space #862

Closed mantzaris closed 1 year ago

mantzaris commented 1 year ago

Julia version v"1.9.3" Agents v5.17.1

code:

SEED = 123;
@agent HeliumAtom ContinuousAgent{3} begin
    momentum::Float64
    energy::Float64    
end

function initialize( ; extent=(10^(3),10^(3),10^(3)),
                            num_He_atoms=10^6, min_He_distance=0.1 )    

    volume = reduce(*, extent )
    inter_atomic_distance = cbrt( volume / num_He_atoms )
    spacing_model = 10^( floor( log10(inter_atomic_distance) ) ) * 0.1
    space3d = ContinuousSpace( extent; spacing=spacing_model )
    rng = Random.MersenneTwister(SEED)

    model = ABM( HeliumAtom, space3d; rng, scheduler = Schedulers.Randomly())

    function MakeRandomHeAgent(id)
        position = Tuple( rand( Uniform( 0 , extent[1] ) , 3 ) )
        velocity = (0,0,0)
        momentum = 1
        energy = 1
        return HeliumAtom(id, position, velocity, momentum, energy)
    end

    for id in 1:num_He_atoms

        new_agent = nothing
        for _ in 1:20
            new_agent = MakeRandomHeAgent(id)
            nn = nearest_neighbor(new_agent, model, min_He_distance)
            if(nn == nothing)
                break
            end

            new_agent = nothing
        end

        if(new_agent == nothing)
            println("not able to add all agents, too dense")
            println("last agent id = $(id)")
            break
        end        

        add_agent_pos!(new_agent, model)
    end    

    return model
end

I try to create 10 agents, 100, 1000, ok, but once I try to create 1001 agents, Crash!

model = initialize(extent=(10^(3),10^(3),10^(3)),num_He_atoms=10, min_He_distance=2)
sizeof(model)
136

model = initialize(extent=(10^(3),10^(3),10^(3)),num_He_atoms=100, min_He_distance=2)
sizeof(model)
136

model = initialize(extent=(10^(3),10^(3),10^(3)),num_He_atoms=1000, min_He_distance=2)
sizeof(model)
136

model = initialize(extent=(10^(3),10^(3),10^(3)),num_He_atoms=1001, min_He_distance=2)
CRASH!
Tortar commented 1 year ago

The crash is actually due to the size of the underlying grid, don't use sizeof since the function doesn't recursively sum the necessary memory involved, use Base.summarysize instead. In the latest case you are actually trying to do something like this:

function Grid(d::NTuple{D,Int}) where {D}
    stored_ids = Array{Vector{Int},D}(undef, d)
    for i in eachindex(stored_ids)
        stored_ids[i] = Int[]
     end
     return stored_ids
end

Grid((1000,1000,1000)) # on my computer this requires more than 12GB of RAM and takes a very long time

since the spacing in initialize(extent=(10^(3),10^(3),10^(3)),num_He_atoms=1001, min_He_distance=2) is equal to 1 while in the other cases the spacing is equal to 10 which creates under the hood a grid of 100x100x100, which is much more manageable. So you need to change this line spacing_model = 10^( floor( log10(inter_atomic_distance) ) ) * 0.1 to something else

Tortar commented 1 year ago

But you are actually posing another issue, so feel free to submit a new one related to this instead: Is it possible to use a sparse representation of the discrete spaces with SparseArrays? This way we coud manage with less RAM larger grids in some cases (at the expense of some speed)