SandPile
Model#
The SandPile
model simulates the development of a sand pile to which a grain of sand is added at each time step. At a critical slope level, the sandpile relaxes and distributes grains onto the surrounding cells.
The model is initialized with a random distribution of sand, with the slope exceeding the critical value everywhere. It is then relaxed (sand topples) such that the model ends the initial iteration step with a slope below the critical slope everywhere. In each further iteration, a grain of sand is added at a random position. If the slope exceeds the critical value, sand topples to the neighboring positions. If this leads to a neighboring position exceeding the critical slope, the sand topples again. This goes on during each timestep until the slope is below the critical value everywhere. The borders of the model’s grid are fixed at a given (sub-critical) slope value, such that each sand may “fall off” the borders of the grid.
In each timestep, the rearrangement of grains can affect any number of positions. It is possible that the slope only changes in one position, or that a single grain added causes an avalanche that affects almost the entire grid. These features of unpredictability and lack of characteristic scale make the model interesting.
Default Model Configuration#
Below are the default configuration parameters for the SandPile
model:
# --- Space parameters --------------------------------------------------------
# The physical space this model is embedded in
space:
periodic: false
# --- CellManager -------------------------------------------------------------
cell_manager:
grid:
structure: square
resolution: 32 # in cells per unit length of physical space
neighborhood:
mode: vonNeumann
cell_params:
# Cells are randomly initialized using a uniform distribution in the given
# closed range.
# Choose values such that this is supercritical
initial_slope_lower_limit: !is-unsigned 5
initial_slope_upper_limit: !is-unsigned 6
# --- Dynamics ----------------------------------------------------------------
# The critical slope; beyond this value, sand topples
critical_slope: !is-unsigned 4
# --- Data writing ------------------------------------------------------------
# If true, will only store the avalanche size, not the spatially resolved data
write_only_avalanche_size: !is-bool false
Available Plots#
The following plot configurations are available for the SandPile
model:
Default Plot Configuration#
# -- A plot of the slope (mean - critical_slope) ------------------------------
mean_slope:
based_on: mean_slope
# -- Plot the avalanche area fraction time series -----------------------------
area_fraction:
based_on: area_fraction
# -- Cluster size distribution plots ------------------------------------------
cluster_size_distribution:
enabled: false
based_on: cluster_size_distribution
# The complementary cumulative cluster size distribution
# ... for each universe
compl_cum_cluster_size_dist:
based_on: compl_cum_cluster_size_dist.universe
# ... for a multiverse sweep, using auto-encoding
compl_cum_cluster_size_dist_facet_grid:
enabled: false
based_on: compl_cum_cluster_size_dist.multiverse
# -- CA plots -----------------------------------------------------------------
# An animation of the slope
ca/slope:
based_on: ca/slope
enabled: false
# An animation of the avalanche
ca/avalanche:
based_on: ca/avalanche
enabled: false
# Combined
ca/slope_and_avalanche:
based_on: ca/slope_and_avalanche
Base Plot Configuration#
.variables:
base_path: &base_path data/SandPile
# Colors used throughout the plots, mapping to state values
cmap: &cmap
static: &color_static black # 0
mobile: &color_mobile sandybrown # 1
# =============================================================================
# ╔╦╗╔═╗╔╦╗╔═╗╦ ╔═╗╔╦╗╔═╗╔═╗
# ║ ║╣ ║║║╠═╝║ ╠═╣ ║ ║╣ ╚═╗
# ╩ ╚═╝╩ ╩╩ ╩═╝╩ ╩ ╩ ╚═╝╚═╝
# =============================================================================
# -- Overloads ----------------------------------------------------------------
# Overload some configs to insert model-specific settings
# Model-specific defaults
.defaults:
based_on: .defaults
# Can define something here ...
# .. Creators .................................................................
.creator.universe:
based_on:
- .creator.universe
- .defaults
dag_options:
select_path_prefix: *base_path
.creator.multiverse:
based_on:
- .creator.multiverse
- .defaults
select_and_combine:
base_path: *base_path
# -- Plot functions -----------------------------------------------------------
# .. A plot of the slope (mean - critical_slope) ..............................
.plot.mean_slope:
based_on:
- .defaults
# This plot only works with the universe plot creator, does not support DAG
creator: universe
universes: all
# Use the SandPile-specific plot functions
module: model_plots.SandPile
plot_func: mean_slope
# =============================================================================
# ╔═╗╦ ╔═╗╔╦╗╔═╗
# ╠═╝║ ║ ║ ║ ╚═╗
# ╩ ╩═╝╚═╝ ╩ ╚═╝
# =============================================================================
# -- Mean slope ---------------------------------------------------------------
mean_slope:
based_on:
- .plot.mean_slope
# Specify that the critical slope value should be added to the plot
show_critical_slope_value: true
# Add a title
helpers:
set_title:
title: Mean Slope
# Arguments passed to plt.plot
linestyle: 'None'
marker: '.'
# -- Avalanche area fraction time series --------------------------------------
area_fraction:
based_on:
- .creator.universe
- .plot.facet_grid.scatter
- .hlpr.kind.time_series
select:
avalanche_size:
path: avalanche_size
transform:
- .data
num_cells:
path: avalanche_size
transform:
- .attrs: [!dag_prev , num_cells]
transform:
- div: [!dag_tag avalanche_size, !dag_tag num_cells]
tag: area_fraction
# Compute the marker sizes such that larger area fractions are larger
- mul: [!dag_tag area_fraction, 100]
- add: [!dag_prev , 2]
tag: sizes
# Combine into a dataset
- xr.Dataset:
- area_fraction: !dag_tag area_fraction
sizes: !dag_tag sizes
tag: data
x: time
y: area_fraction
s: !dag_result sizes
# Arguments passed on to plt.scatter ...
# Need to adjust scatter points such that they don't have an edge
marker: '.'
alpha: .8
edgecolor: none
linewidths: 0.
# Adjust helpers
helpers:
set_labels:
y: Rel. Area $[1/A]$
set_limits:
y: [0., 1.]
set_title:
title: Avalanche Size Area Fraction
# -- Cluster size distribution ------------------------------------------------
cluster_size_distribution:
based_on:
- .creator.universe
- .plot.facet_grid.hist # wraps xarray.plot.hist
# Specify which data to calculate the histogram of
select:
avalanche_size: avalanche_size
transform:
# We are interested in the log-scaled avalanche sizes
- log10: !dag_tag avalanche_size
tag: data
# Generate a title which includes the number of avalanches
- len: !dag_tag data
- .format:
- "Cluster Size Distribution ($N={}$)"
- !dag_prev
tag: title_str
# Set scales, limits, and title
helpers:
set_title:
title: !dag_result title_str
set_labels:
x: $\log_{10}(A)$
y: $N_A$
set_scales:
y: log
set_limits:
x: [0, max]
y: [0.7, ~]
# Configure the histogram
bins: 36
range: [0, 6]
# ... further arguments here are passed to np.histogram (via matplotlib)
# -- Complementary Cumulative Cluster Size Distribution -----------------------
# ... for individual universes
compl_cum_cluster_size_dist.universe:
based_on:
- .creator.universe
- .plot.facet_grid.line
select:
cluster_size: avalanche_size
transform:
# Use a custom operation to compute the complementary cluster size
# distribution. Repeated counts need to be masked because (in a cumulative
# distribution) they represent bins with zero counts; masking these makes
# the plot visually simpler ...
- complementary_cumulative_distribution: !dag_tag cluster_size
kwargs:
mask_repeated: true
tag: data
helpers: &compl_cum_helpers
set_title:
title: &compl_cum_title Compl. Cum. Cluster Size Distribution
set_labels:
x: Cluster Size $[A]$
y: $N_A$
set_scales:
x: log
y: log
linestyle: "None"
marker: "."
# ... more generically: for sweeps
compl_cum_cluster_size_dist.multiverse:
based_on:
- .creator.multiverse
- .skip.if_more_than_4D
- .plot.facet_grid.with_auto_encoding
- .plot.facet_grid.line
select_and_combine:
fields:
data:
path: avalanche_size
transform:
- complementary_cumulative_distribution: !dag_prev
kwargs:
mask_repeated: true
- .rename: [!dag_prev , {bin_pos: "cluster size"}]
x: cluster size
helpers:
<<: *compl_cum_helpers
set_title:
enabled: false
set_suptitle:
title: *compl_cum_title
linestyle: "None"
marker: "."
# -- CA Plots -----------------------------------------------------------------
# START --- ca/slope
ca/slope:
based_on:
- .creator.universe
- .plot.ca
select:
slope: slope
to_plot:
slope:
title: Slope
cmap: copper
# END --- ca/slope
ca/avalanche:
based_on:
- .creator.universe
- .plot.ca
select:
avalanche: avalanche
to_plot:
avalanche:
title: Avalanche
cmap: *cmap
ca/slope_and_avalanche:
based_on:
- ca/slope
- ca/avalanche
For available base plots, see Base Plot Configuration Pool.
References#
Bak, P., K. Chen and C. Tang, 1990: Self-organized criticality: An explanation of the 1/f noise, Phys. Rev. Lett., 59, 4, 381–384, doi: 10.1103/PhysRevLett.59.381.
Kurt Roth: Complex, Chaotic and Evolving Environmental Systems (Lecture Notes). Chapter 7.2 (Discrete Complex Systems - Contact Processes)