Issue in collision count for a ball in 2d space using agent.jl

Hello everyone, I have made a MWE for collision problem (2d example) in Agent Based model this based on some of my previous questions. Im using interacting_pairs to find pairs in model and count collision if it finds an agent in some distance ‘d’. Issue at the moment is while increasing resolution of simulation so making dt smaller I see drastic change in collision number. My intuition say that shouldn’t be the case.

You can run this model and check number of collision for different dt values.

using Agents

@agent struct ball(ContinuousAgent{2, Float64})
    radius::Float64
    mass::Float64 
end

mutable struct prop

    dt::Float64
    collision_count::Int64  

 
end


function model_step!(model)

    d = 2*model[1].radius 

    for (a1, a2) in interacting_pairs(model, d, :nearest)

      
        model.collision_count += 1

        elastic_collision!(a1, a2, :mass)

    end

end

function agent_step!(agent, model)


    xx, xy = agent.pos
    vx, vy = agent.vel

    if xx  ≥ 9.99
        vx > 0.0 && (vx = -vx)
        xx = 9.99
    end

    if xx ≤  min_dim
        vx < 0.0 && (vx = -vx)
        xx = min_dim
    end

    if xy  ≥ 0.99 
        vy > 0.0 && (vy = -vy)
        xy = 0.99
    end

    if xy ≤  min_dim
        vy < 0.0 && (vy = -vy)
        xy = min_dim
    end

    agent.pos = SVector(xx, xy)
    agent.vel = SVector(vx, vy)

    move_agent!(agent, model, model.dt)
  
end

using Random: Xoshiro
rng = Xoshiro(42)



function ball_model(;
    number_of_particles=100,
    sides=SVector(10.0, 1.0),
    dt=dt,
    collision_count = 0,
    speed = speed
)
    # initial random positions
    positions = [sides  .* rand(SVector{2,Float64}) for _ in 1:number_of_particles]

    properties =  prop(dt, collision_count)
    # Space and agents
    space2d = ContinuousSpace(sides; periodic=true)


    model = StandardABM(ball, space2d, agent_step! = agent_step!,
                        model_step! = model_step!, properties = properties,
                        rng = rng)

    # Create active agents
    for id in 1:number_of_particles
        pos = positions[id]
        radius = 0.1
        vel = speed * randn(SVector{2}) # initial velocities)
        mass = 1
        add_agent!(pos,  model, vel, radius, mass)
    end

    return model
end

model = ball_model(speed =  0.2, dt = 0.01)
# abmqueue(model)

min_dim = 0.01
step = 5 / model.dt
adf, mdf = run!(model, step;  mdata = [:collision_count], init = true, when = (model, t) -> true,  showprogress = false)  



Isn’t the issue that “the same” collision is being counted multiple times, as the time-step gets smaller?

yes it seems like that. Is there a way to avoid it? because models consider particles as point objects so if d = 1 and speed for each step is 0.0006 then for particle to cross circle of interaction will take many steps and for all those steps it will be counted as interaction because particle is still inside interaction circle.

I was trying to avoid this but not successful yet.

one thing is noticed that for a given speed some specific dt gives ideal collision number if I compare it to theoretical expected coliisions. so for smaller speed value large dt and larger speed value small dt.

Situation was solved by placing agents in random positions which are out of interaction radius. so just checking if distance between two agents is more than interaction radius if not give new position to one of agent. All this can be done after initialisation.