ForestFire Model

The ForestFire model simulates the development of a forest under influence of fires and was first proposed by P. Bak, K. Chen, and C. Tang in 1990. Trees grow on a random basis and lightning causes them and the trees in the same cluster to burn down instantaneously; this is the so-called “two state model”.


Implementation

The forest is modelled as a cellular automaton where each cell has can be in one of two states: empty or tree.

The update procedure is as follows: in each iteration step, iterate over all cells in a random order. For each cell, one of two actions can take place, depending on the current state of the cell:

  • An empty cell becomes a tree with probability p_growth.

  • A tree ignites with a probability p_lightning and ignites all cells indirectly connected to it. The cluster burns down instantaneously and all cells transition to state empty.

The new state of a cell is applied directly after it was iterated over, i.e. cell states are updated sequentially.

Heterogeneities

There is the possibility to introduce heterogeneities into the grid, which are implemented as two additional possible cell states: source and stone:

  • A cell can be a constantly ignited fire source, instantly burning down a cluster that comes into contact with it.

  • A cell can be a stone, being immune to fire and not taking part in any model dynamics.

These heterogeneities are controlled via the ignite_permanantly and stones entries of the model configuration, which both make use of the entity selection interface.

Data Output

The following data is stored alongside the simulation:

  • kind: the state of each cell. Possible values:

    • 0: empty

    • 1: tree

    • 2: (not used)

    • 3: source, is constantly ignited

    • 4: stone, does not take part in any interaction

  • age: the age of each tree, reset after lightning strikes

  • cluster_id: a number identifying to which cluster a cell belongs; 0 for non-tree cells

  • tree_density: the global tree density

Simulation Results

Below, some example simulation results are shown. If not marked otherwise, the default values (see below) were used and the grid was chosen to have 1024x1024 cells.

Spatial Representation

Snapshots of the forest state, its age, and the identified clusters after 223 iteration steps:

https://ts-gitlab.iup.uni-heidelberg.de/utopia/doc_resources/raw/master/models/ForestFire/forest_snapshot.png https://ts-gitlab.iup.uni-heidelberg.de/utopia/doc_resources/raw/master/models/ForestFire/forest_age_snapshot.png https://ts-gitlab.iup.uni-heidelberg.de/utopia/doc_resources/raw/master/models/ForestFire/clusters_snapshot.png

Tree Density

The time development of the tree density shows how the system relaxes into its quasi-stable equilibrium state.

https://ts-gitlab.iup.uni-heidelberg.de/utopia/doc_resources/raw/master/models/ForestFire/tree_density.png

Cluster Size Analysis

In a complementary cumulative cluster size distribution plot, the scale-free nature of the system can be deduced by observing those parts of the plot that appear linear in a log-log representation.

https://ts-gitlab.iup.uni-heidelberg.de/utopia/doc_resources/raw/master/models/ForestFire/compl_cum_cluster_size_dist.png

Default Configuration Parameters

Below are the default configuration parameters for the ForestFire model:

# --- Space -------------------------------------------------------------------
space:
  periodic: !is-bool true


# --- CellManager and cell initialization -------------------------------------
cell_manager:
  grid:
    structure: square
    resolution: !is-positive 64

  neighborhood:
    mode: !param
      default: Moore
      is_any_of: [empty, vonNeumann, Moore, hexagonal]

  # Initialization parameters for each cell
  cell_params:
    # With this probability, a cell is initialized as tree (instead of empty)
    p_tree: !is-probability 0.2
    # NOTE Macroscopically, this is equivalent to the initial tree density


# --- Model Dynamics ----------------------------------------------------------
# Probability per site and time step to transition from state empty to tree
p_growth: !is-probability 7.5e-3

# Probability per site and time step to transition to burning state, burning
# down the whole cluster
p_lightning: !is-probability 1e-05

# Probability (per neighbor) to _not_ catch fire from a burning neighbor
p_immunity: !is-probability 0.


# --- Heterogeneities ---------------------------------------------------------
# Some cells can be permanently ignited or turned into stones.
# Both these features are using the `select_entities` interface; consult the
# documentation regarding information on available selection modes.

# Turn some cells into stones: these do not take part in any of the processes
stones:
  enabled: !is-bool false
  mode: !param
    name: selection mode for stones
    default: clustered_simple
    is_any_of: &selection_modes
      - sample
      - probability
      - position
      - boundary
      - lanes
      - clustered_simple

  # Clustering parameters
  p_seed: !is-probability .02     # Probability for a cell being a cluster seed
  p_attach: !is-probability .1    # Attachment probability (per neighbor)
  num_passes: !is-unsigned 5      # How many attachment procedures to perform

  # Depending on mode, can pass additional parameters here.

# Set some cells on fire permanently (invoked after stones are set)
ignite_permanently:
  enabled: !is-bool false
  mode: !param
    name: selection mode for permanently ignited cells
    default: boundary
    is_any_of: *selection_modes

  # Boundary selection parameters (requires space to be set to NON-periodic!)
  boundary: !param
    default: bottom
    is_any_of: [bottom, top, left, right, all]


# --- Output Configuration ----------------------------------------------------
# Whether to only write out the tree density; useful for runs on large grids
# where spatial information is not needed.
write_only_tree_density: !is-bool false

Available Plots

The following plot configurations are available for the ForestFire model:

Default Plot Configuration

# --- A plot of the cluster size distribution ---------------------------------
cluster_size_distribution:
  based_on: cluster_size_distribution


# --- The complementary cumulative cluster size distribution ------------------
compl_cum_cluster_size_dist:
  based_on: compl_cum_cluster_size_dist


# --- Tree density ------------------------------------------------------------
# ... Of the single universes .................................................
tree_density:
  based_on: tree_density


# ... Of a sweep over p_lightning and seed ....................................
tree_density_over_p_lightning:
  based_on: tree_density_over_p_lightning
  enabled: false  # Can enable this when sweeping over `p_lightning`

# ... Tree density facet-grid example: 1D line plots ..........................
tree_density_facet_grid_lineplots:
  based_on: tree_density_facet_grid
  enabled: false  # Can enable this when sweeping over any dimension
  col: p_lightning

# ... Tree density facet-grid example: 2D imshow plot .........................
tree_density_facet_grid_imshow:
  based_on: tree_density_facet_grid
  enabled: false  # Can enable this when sweeping over any dimension
  col: p_lightning
  row: seed

# ... Asymptotic tree density .................................................
tree_density_asymptotic_over_p_lightning:
  based_on: tree_density_asymptotic
  enabled: false  # Can enable this when sweeping over any dimension

  # Specialization for p_lightning
  helpers:
    set_labels:
      y: $p_{lightning}$
    set_scales:
      y: log
    set_limits:
      y: [min, ~]

  # Select the time steps to average over
  average_fraction: .06

  # Passed to plt.errorbar
  color: tab:blue


# --- Tree age ----------------------------------------------------------------
mean_tree_age:
  based_on: mean_tree_age


# --- Snapshots and animations of the spatial grid ----------------------------
# NOTE These are both based on the snapshot base plots and add the remaining
#      parameters: For snapshots, the time index that is to be plotted; for
#      animations, the animation parameters (using multiple inheritance).

# ... The forest ..............................................................
forest_snapshot:
  based_on: forest_snapshot
  enabled: false
  time_idx: -1

forest:
  based_on: [forest_snapshot, .ca.state.anim_ffmpeg]

# ... The forest age ..........................................................
forest_age_snapshot:
  based_on: forest_age_snapshot
  enabled: false
  time_idx: -1

forest_age:
  based_on: [forest_age_snapshot, .ca.state.anim_ffmpeg]

# ... The clusters ............................................................
clusters_snapshot:
  based_on: clusters_snapshot
  enabled: false
  time_idx: -1

clusters:
  based_on: [clusters_snapshot, .ca.state.anim_ffmpeg]

# --- Miscellaneous -----------------------------------------------------------
# ... Combined plot of forest states and clusters .............................
forest_and_clusters:
  based_on: [forest_snapshot, clusters_snapshot, .ca.state.anim_ffmpeg]
  enabled: false

Base Plot Configuration

# --- A plot of the cluster size distribution ---------------------------------
cluster_size_distribution:
  based_on: .distribution.histogram

  # Specify which data to calculate the histogram of
  model_name: ForestFire
  path_to_data: cluster_id

  # Set scales, limits, and title
  helpers:
    set_title:
      title: Cluster Size Distribution
    set_labels:
      x: $\log_{10}(A)$
      y: $N_A$
    set_scales:
      y: log
    set_limits:
      x: [0, max]
      y: [0.8, ~]

  # Perform dimensionality reduction of the given data
  preprocess:
    # This is a sequence of operations to carry out. Each entry is either the
    # name of an operation (if there are no arguments needed for the
    # operation) or a dict where the only key refers to the name of the
    # operation and the content of the dict is passed to that function
  
    # First, Select the last index along the time dimension
    - isel:
        time: -1
    # Then, count unique cluster IDs, i.e.: the cluster sizes
    - count_unique
    # Now apply a base-10 logarithm; histogram makes no sense otherwise
    - log10

  # Configure the histogram
  histogram_kwargs:
    bins: 30
    range: [0, ~]  # None is resolved to data.min() or data.max()

  # Arguments passed to plt.bar
  # ...

# --- Complementary Cumulative Cluster Size Distribution ----------------------
compl_cum_cluster_size_dist:
  based_on: .distribution.histogram.complementary_cumulative

  # Specify which data to calculate the histogram of
  model_name: ForestFire
  path_to_data: cluster_id

  # Set scales, limits, and title
  helpers:
    set_title:
      title: Compl. Cum. Cluster Size Distribution
    set_labels:
      x: Cluster Size $[A]$
      y: $N_A$
    set_scales:
      x: log
      y: log

  # Configure dimensionality reduction of the given data
  preprocess:
    # First, Select the last index along the time dimension
    - isel:
        time: -1
    # Then, count unique cluster IDs, i.e.: the cluster sizes
    - count_unique

  # Adjust postprocessing to not normalize
  postprocess:
    - cumulate_complementary


# --- Tree age plots ----------------------------------------------------------
mean_tree_age:
  based_on: .basic_uni.errorbar

  model_name: ForestFire

  to_plot:
    age:
      label: Tree Age
      plot_std: true
      transform_data:
        - where: ['>', 0]
        - mean: [x, y]
      transform_std:
        - where: ['>', 0]
        - std: [x, y]

  helpers:
    set_title:
      title: Mean Tree Age
    set_labels:
      x: Time [Iteration Steps]
      y: Mean Age [Iteration Steps]
    set_limits:
      x: [0., max]

  # Passed on to errorbar plot
  # ...


# --- Tree density plots ------------------------------------------------------
# ... Time series for each universe ...........................................
tree_density:
  based_on: .basic_uni.lineplot

  model_name: ForestFire
  path_to_data: tree_density

  helpers:
    set_title:
      title: Tree Density
    set_labels:
      x: Time [Iteration Steps]
      y: Tree Density $[1/A]$
    set_limits:
      x: [0., max]
      y: [0., 1.]

  # Passed on to plt.plot
  # ...

# ... For a parameter sweep over seed and p_lightning .........................
tree_density_over_p_lightning:
  based_on: .basic_mv.errorbar
  select:
    field: data/ForestFire/tree_density

  # Specify which data to plot and which data to use for std
  to_plot: tree_density
  plot_std: true

  # Apply some transformations, e.g. calculate a mean over the seed
  transform_data:
    - mean: [seed]
      _may_fail: true

  # Same transformations needed for std
  transform_std:
    - std: [seed]
      _may_fail: true

  # Specify over which sweep to create lines
  lines_from: p_lightning

  # Adjust helpers
  helpers:
    set_title:
      title: Tree Density
    set_labels:
      x: Time [Iteration Steps]
      y: Tree Density $[1/A]$
    set_limits:
      x: [0., max]
      y: [0., 1.]
    set_legend:
      loc: upper left

  # Use a custom color map for lines
  cmap: viridis

  # Passed on to errorbar plot
  # ...


# ... Asymptotic tree density .................................................
tree_density_asymptotic:
  based_on: .basic_mv.asymptotic_average

  select:
    fields:
      data: data/ForestFire/tree_density

  # Make this a time-averaged tree density
  average_dim: time
  average_fraction: .01

  # Average over seed, if available
  transform_data:
    - mean: [seed]
      _may_fail: true

  # Don't plot std
  plot_std: false

  # Adjust helpers
  helpers:
    set_title:
      title: Asymptotic Tree Density
    set_labels:
      x: Tree Density $[1/A]$
    set_limits:
      x: [0., ~]


# --- Grid Snapshots ----------------------------------------------------------
# NOTE These can also be used as basis for grid animations.
# ... The forest ..............................................................
forest_snapshot:
  based_on: .ca.state
  model_name: ForestFire
  
  to_plot:
    kind:
      title: Forest State
      limits: [0, 4]
      cmap:
        empty: darkkhaki
        tree: forestgreen
        ' ': none  # not used in FFM
        source: orange
        stone: slategrey

# ... The forest age ..........................................................
forest_age_snapshot:
  based_on: .ca.state
  model_name: ForestFire

  to_plot:
    age:
      title: Forest Age
      cmap: YlGn

# ... The clusters ............................................................
clusters_snapshot:
  based_on: .ca.state
  model_name: ForestFire

  to_plot:
    cluster_id:
      title: Clusters
      limits: [0, 20]
      cmap: tab20
      no_cbar_markings: true

  transform_data:
    cluster_id:
      - where: ['!=', 0]       # 0 is masked: not part of a cluster
      - mod: 20                # ... to match the tab20 color map


# --- Generic Multidimensional Plotting ---------------------------------------
# ... Facet Grid Plot .........................................................
tree_density_facet_grid:
  based_on: .dag.generic.facet_grid
  creator: multiverse
  
  select_and_combine:
    fields:
      data: tree_density
    base_path: data/ForestFire

For the utopya base plots, see Multiverse Base Configuration.

References

  • Bak, P., K. Chen and C. Tang, 1990: A forest-fire model and some thoughts on turbulence, Phys. Lett. A, 147, (5-6), 297–300, doi: 10.1016/0375–9601(90)90451–S (PDF).

  • Kurt Roth: Complex, Chaotic and Evolving Environmental Systems (Lecture Notes). Chapter: Discrete Complex Systems — Contact Processes