Abelian Sandpile
using EasyABM
Step 1: Create Model
In this model, we work with patches only. We set grid_size
to (50,50), set space_type
to NPeriodic and define an additional model parameter threshold
whose value is set to 4.
model = create_2d_model(size = (50,50), space_type=NPeriodic, threshold = 4)
Step 2: Initialise the model
Initially, we set the amount of sand on all patches equal to 2 except for the patch (25,25) where we set the sand amount to value 2000. The color attribute of patches is set according to the amount of sand they carry. If the sand amound on a patch is >=4 then its color is blue, otherwise the color is set according to dictionary coldict.
const coldict = Dict(0=>cl"white", 1=>cl"yellow", 2=>cl"green", 3=> cl"orange", 4=>cl"red")
function initialiser!(model)
for j in 1:model.size[2]
for i in 1:model.size[1]
model.patches[i,j].sand = 2
model.patches[i,j].color= coldict[2]
end
end
model.patches[25,25].sand = 2000
model.patches[25,25].color= cl"blue"
end
init_model!(model, initialiser = initialiser!, props_to_record = Dict("patches" => Set([:color,:sand])))
Step 3: Defining the step_rule! and running the model
In the step function we loop over all the patches and if a patch has sand >= 4, we topple that patch which means that i) We reduce the amount of sand on that patch by 4 ii) We increase the amount of sand on its Von Neumann neighboring patches by 1.
function topple!(patch_loc, model, threshold)
nbr_patch_locs = neighbor_patches_neumann(patch_loc, model, 1)
for p in nbr_patch_locs
pth_patch = model.patches[p...]
sand = pth_patch.sand + 1
pth_patch.sand = sand
pth_patch.color = sand <= 4 ? coldict[sand] : cl"blue"
end
patch = model.patches[patch_loc...]
sand = patch.sand-threshold
patch.sand = sand
patch.color = sand <= 4 ? coldict[sand] : cl"blue"
end
function step_rule!(model)
threshold = model.properties.threshold
for j in 1:model.size[2]
for i in 1:model.size[1]
if model.patches[i,j].sand>=threshold
topple!((i,j),model, threshold)
end
end
end
end
run_model!(model, steps = 1000, step_rule = step_rule!)
Step 4: Visualisation
In order to draw the model at a specific frame, say 4th, one can use draw_frame(model, frame = 4 )
. If one wants to see the animation of the model run, it can be done as
animate_sim(model)
After defining the step_rule!
function we can also choose to create an interactive application (which currently works in Jupyter with WebIO installation) as shown below. It is recommended to define a fresh model and not initialise it with init_model!
or run with run_model!
before creating interactive app.
model = create_2d_model(size = (50,50), space_type=NPeriodic, threshold = 4)
create_interactive_app(model, initialiser= initialiser!,
props_to_record = Dict("patches" => Set([:color])),
model_controls = [(:threshold, "slider", 1:10)],
step_rule= step_rule!,frames=500, show_patches=true)
Step 5: Fetch Data
It is easy to fetch any recorded data after running the model. For example, the numbers of patches with different amounts of sand at all timesteps can be got as follows
df = get_nums_patches(model,
patch-> patch.sand == 0,
patch-> patch.sand == 1,
patch-> patch.sand == 2,
patch-> patch.sand == 3,
labels=["sand=0","sand=1","sand=2","sand=3"], plot_result=true)
References
1.) https://en.wikipedia.org/wiki/Abeliansandpilemodel