Nplants

Nplants simulator implementing Bown et al 2007's ecological model.


powered by NetLogo

view/download model file: nplants.nlogo

WHAT IS IT?

This simulation implements the ecological model published in Bown et al 2007 ( http://dx.doi.org/10.1016/j.ecolmodel.2007.05.004 ), which studies the distribution and abundance of plant species, within a certain environment.

The aim of this work is to address the ecological "holy grail", meaning to study the relation between environmental properties, individual properties and community composition.


HOW IT WORKS

The environment is a square lattice with all boundaries fixed (not torroidal). Each lattice cell (patch) contains a resource substrate from which plants uptake resources.

A plant executs four biological processes: resource uptake, resource allocation, development and reproduction. In addition, death occurs either due to random events or from starvation.

The simulation starts with a number of unique individuals defined by the input 'species'. Each of this will undergo the biological processes which will eventually lead to verious species dissapear, while others will flourish.

The aim of the simulation is to observ the progress of the 'richness' barometer, and it's relation to the 'environment' size and other parameters.


HOW TO USE IT

Pressing the 'setup' button will initialise the environment, according to the parameters specified on the interface. You can vary:
- the initial number of species ('species' input)
- simulation length
- substrate value: each patch contains a resource substrate that is filled up to a given value

There are a couple of switches which alter the information displayed on the screen:
- links? controlls the display of links between plants and the seeds they disperse
- plotting? controlls the update of the plots. If it is on, plots will be updated according to the state of the simulation
- output? controlls standard output to the Command Center (not visible in applet mode).


THINGS TO NOTICE

This section could give some ideas of things for the user to notice while running the model.


THINGS TO TRY

This section could give some ideas of things for the user to try to do (move sliders, switches, etc.) with the model.


EXTENDING THE MODEL

This section could give some ideas of things to add or change in the procedures tab to make the model more complicated, detailed, accurate, etc.


NETLOGO FEATURES

This section could point out any especially interesting or unusual features of NetLogo that the model makes use of, particularly in the Procedures tab. It might also point out places where workarounds were needed because of missing features.


RELATED MODELS

This section could give the names of models in the NetLogo Models Library or elsewhere which are of related interest.


CREDITS AND REFERENCES

This section could contain a reference to the model's URL on the web if it has one, as well as any other necessary credits or references.


PROCEDURES

extensions [array]

;;;;;;;;;;;;;;;;;;;;;
;;; Data types    ;;;
;;;;;;;;;;;;;;;;;;;;;
breed [ plants plant ]
undirected-link-breed [plant-links plant-link]

plant-links-own [ time ]
plants-own [
  rcdt eu_y0 eu_b reur strr surr tdfv ps rsp rst pdp tref  ;; traits
  dvs age ss stl su ;; states
  csl ; cumulative resource requirement according to development stage  
  tot-aru tot-rqd 
  rsv ;; resource shortfall value ( rst * ( essential_uptake_trait i ) )
  tot-rhs ;; total resource in history
  rhs ;; resource history  
  ]
patches-own [
  ini cur sat rel rep ;; substrate
  req-id req-v ;; requests
  tot-req ;; total resource request over a timestep
  ]

;; Global vars
globals [ 
 richness 
 abundance 
 species-colors
 plc ;; index in resource history
 mpr ;; # of periods that resource history is considered 
 mdi ;; max distance reached by resource capture system 
 mdm ;; # of cells in the max res. capture syst.; related to mdi 
 mds ;; # of development stages
 sdp ;; # seed dispersal pattern
 epochs 
  ;; traits
 a_mean 
 y0_mean;
 y0_dev 
 b_mean 
 b_dev 
 x0_mean 
 reur_mean
 reur_dev 
 rca_defs 
 ps_mean
 tim_mean
 tim_dev 
 strr_mean 
 strr_dev 
 surr_mean
 surr_dev 
 rtp_mean 
 rtt_mean 
 pdp_mean    
 ;; statistics
 max-dvs
 max-age
 max-seeds
 max-seeds-px
 max-seeds-py 
 ;; movie 
 last-record?
 record? 
  ]


;;;;;;;;;;;;;;;;;;;;;;;;
;;; Setup procedures ;;;
;;;;;;;;;;;;;;;;;;;;;;;;

to setup
  clear-all  
  setup-globals
  setup-environment
  setup-population  
  if ( plotting? ) [ 
    set-current-plot "Development stage"
    set-plot-y-range 0 mds
    set-histogram-num-bars mds / 2
    
    set-current-plot "Ages"    
    set-histogram-num-bars mds / 2
    do-plotting 
    ]
  
  set last-record? false
end

to setup-globals
  set richness 0
  set plc 0
  set abundance array:from-list (n-values species [ 0 ])
  set species-colors array:from-list (n-values species [ 0 ])
    
  set mpr 6
  set mdi 1
  set mdm 49
  set mds 50
  set sdp 5
  set epochs 5
  
  ;; traits
  set a_mean 10.52 
  set y0_mean 0.24
  set y0_dev 0.31
  set b_mean 8.12  
  set b_dev 2.65  
  set x0_mean 29.09  
  
  set reur_mean  1.1 
  set reur_dev  0.58
  
  set rca_defs array:from-list [ 
    1 0.9 0.8 0.7 0.6 ;; 0/mdi 0
    0 0.1 0.2 0.3 0.4 ;; 0/mdi 1
    1 0.8 0.6 0.4 0.2 ;; 1/mdi 0
    0 0.2 0.4 0.6 0.8 ;; 1/mdi 1
    ] ;/rcdt/mdi/ep
  
  set ps_mean 0.8 ;;unusable_store_proportion_trait
  
  set tim_mean 45 ;; Rumex parabola fitting
  set tim_dev 8.6 ;; Rumex
  
  set strr_mean 0.28
  set strr_dev 0.143 
  set surr_mean 0.4
  set surr_dev 0.153
  
  set rtp_mean 5 ;; resource shortfall period trait (must be < mdr)
  set rtt_mean 0.1 ;;resource_shortfall_threshold_trait
  set pdp_mean 0.001    
  
  ;;statistics
  set max-dvs 0
  set max-age 0
  set max-seeds 0
  set max-seeds-px 0
  set max-seeds-py 0
end

to setup-environment
  resize-world 0 (environment - 1) 0 (environment - 1)
  if ( environment * environment < species ) [ set species environment * environment ]
  
  ask patches [ 
    ;; chessboard
    ;ifelse ( remainder ( pxcor + pycor * max-pxcor ) 2 = 0 )
    ;[ set pcolor white ]
    ;[ set pcolor black ]
    set pcolor white
    set ini substrate
    set cur substrate
    set sat substrate
    set rel substrate
    set rep substrate
    set req-id []
    set req-v []
    ]
end

to setup-population
  set-default-shape plants "leaf"
  ;; creation  
  create-plants species [ 
    ;; location
    setxy random-pxcor random-pycor
    while [ count turtles-here > 1 ] 
    [ setxy random-pxcor random-pycor 
      ;show (word "was placed on a occupied location")
      ]
    
    ;; color
    set color ( rgb random 256 random 256 random 256 )
    array:set species-colors who color 

    ;; sampling traits
    set rcdt (random 2)
    set eu_y0 y0_mean + (random-normal 0 1) * y0_dev
    if (eu_y0 < 0) [ set eu_y0 0 ]
    set eu_b b_mean + (random-normal 0 1) * b_dev
    set reur reur_mean + (random-normal 0 1) * reur_dev
    if ( reur < 1 ) [ set reur 1 ]
    set ps ps_mean 
    set tdfv floor ( tim_mean + (random-normal 0 1) * tim_dev )
    
    set strr strr_mean + (random-normal 0 1) * strr_dev
    ifelse ( strr < 0 ) [ set strr 0 ]
    [ if ( strr > 1 ) [ set strr 1 ] ]    
    set surr surr_mean + (random-normal 0 1) * surr_dev 
    ifelse ( surr < 0 ) [ set surr 0 ]
    [ if ( surr > 1 ) [ set surr 1 ] ]    
    
    set rsp rtp_mean 
    set rst rtt_mean 
    set pdp pdp_mean      

    if output? [
    show (word "rcdt=" rcdt
    " eu_y0=" eu_y0
    " eu_b=" eu_b
    " reur=" reur
    " tdfv=" tdfv
    " strr=" strr
    " surr=" surr) ;; states   
    ] 
    
    ;; states
    set rhs array:from-list n-values mpr [0]
    set dvs 0
    set age 0
    set stl 0
    set su 0
    set ss 0    
    
    set tref who
    array:set abundance who 1
    
    set csl (essential_uptake_trait 0)    
    ]     
  set richness species          
end

;;;;;;;;;;;;;;;;;;;;;
;;; Go procedures ;;;
;;;;;;;;;;;;;;;;;;;;;

to go-step
  go
end

to go
  if ticks >=  sim-length [ stop ]  
  if count plants =  0 [ stop ] 
    
  resource-acquisition
  resource-usage

  tick  
  if ( links? ) [
  ask plant-links [ set time time + 1
    if ( time > 10 ) [ die ] ]
  ]
  set plc ( remainder ticks mpr )
  if ( plotting? ) [ do-plotting ]
end

to resource-acquisition ;; observer
  ask plants [ request-resources ]
  ask patches [ normalise-requests ]
  ask plants [ uptake-resources ]
  ask patches [ replenish-substrate rep ]
end

to request-resources ;; a plant requests resources from its neighbours
  set tot-rqd 0
  ; for patch at distance 0
  let req ( resource_capture_proportion_trait 0 ) * requested_uptake_trait 
  set tot-rqd req
  ;show (word "resource-requests (0)=" req )
  let plant-id who
  ask patch-here [ receive-request req plant-id ]
  ;; for patches at distance 1
  set req ( resource_capture_proportion_trait 1 ) * requested_uptake_trait
  ;show (word "resource-requests (1)=" req )
  ask neighbors [ receive-request req plant-id ]
  set tot-rqd tot-rqd + 8 * req
  ;show (word "resource-requests=" tot-rqd )
end

to receive-request [ req plant-id] ;; a patch receives and stores a resource request
  set req-id ( fput plant-id req-id )
  set req-v ( fput req req-v )
end

to normalise-requests ;; a patch normalises the requests according to the resources it has
  set tot-req sum req-v
  ;set plabel precision req-sum 2  
  
  if (tot-req > 0 and tot-req > cur) [ ;* > 0 added and because cur becomes negative
    ;if (cur < 0 ) [ show (word "cur=" cur) ]
    let r cur / tot-req
    set req-v ( map [ r * ? ] req-v )
  ]
  
  if (substrate-color?) [
    ifelse (tot-req <= sat) 
    [ set pcolor 9.9999 - 5 * tot-req / sat ]
    [ set pcolor 4.9999 ]  
  ]
end

to uptake-resources ;; plant
  let aru 0
  let plant-id who
  ask patch-here [ set aru release-resource plant-id ]
  ask neighbors [ set aru aru + ( release-resource plant-id ) ]
  set tot-aru aru
  ;show (word "uptake-resources: aru=" aru)
  ;show (word "plc=" plc)  
  array:set rhs plc aru ;; memorise uptake
  ;; allocate resources
  let rqd ( essential_uptake_trait dvs )
  let sur ( surr * su )
  
  if ( aru > rqd) [
    set su su + ( aru - rqd )
    set aru rqd
  ]
  if ( aru < rqd ) [
    let dif rqd - aru
    ifelse ( dif <= sur ) [ ; take dif from Su
              set aru aru + dif
              set su su - dif
    ]
    [ ; take sur from Su
      set aru aru + sur
      set su su - sur
    ]
  ]
set ss ss + aru * ps
set stl ( stl + aru * ( 1 - ps) )
;show (word "ss=" ss " stl=" stl " su=" su)
;show rhs
end

to replenish-substrate [ res ] ;; patch
  if ( cur < 0 ) [ set cur 0 ]
  set cur cur + res
  if ( cur > sat ) [ set cur sat ]
end

to-report release-resource [ plant-id ] ;; a patch reports the resources a plant has been allocated
  let res 0
  let i 0
  foreach req-id [
    if (? = plant-id ) [      
      set res ( item i req-v)
      
      set req-v remove-item i req-v
      set req-id remove-item i req-id
      
      set cur cur - res ; depleting the substrate
      ; if (cur < 0) [ set cur 0 ] ; for float correction
      report res
    ]
    set i i + 1    
  ]  
end

to receive-resource [ res ] ;; a patch receives resources (from a plant that died)
  set cur cur + res
  if ( cur > sat ) [ set cur sat ]
end

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;; resource-usage

to resource-usage
  ask plants [ individual_development ]
  ask plants [ reproduce ]
end

to individual_development ;; a plant may die or develop
  ;; verifying death conditions
  if ( ( random-float 1 ) <= pdp ) [ 
    ;show (word " dieing because of random death")
    individual-death 
    ]
  ; resource shortfall
  set tot-rhs sum array:to-list rhs
  set rsv rst * (essential_uptake_trait dvs )
  if ( tot-rhs < rsv ) [ 
    if output? [ show (word " dieing because of resource shortfall") ]    
    individual-death 
    ]  
  
  ;; development
  set age age + 1 
  if ( age > max-age ) [ set max-age age ]  
  
  let dst csl + (essential_uptake_trait (dvs + 1)) ;developmental_storage_requirement_evaluation ; TODO: Use csl instead of this costly function
  let tls stl + ss
  if (tls > dst and (dvs < mds)) [
      set dvs dvs + 1 
      set csl dst;csl + (essential_uptake_trait dvs)
    ]
    ;if ( dvs > max-dvs ) [ set max-dvs dvs ]  
end

to individual-death ;; plant returns resources and dies
  ;; returning resources
  let tot-res stl + su + ss
  let rcpt ( resource_capture_proportion_trait 0 )
  ask patch-here [ receive-resource  rcpt * tot-res ]
  set rcpt ( resource_capture_proportion_trait 1 )
  ask neighbors [ receive-resource  rcpt * tot-res ]
  
  ; statistics update
  array:set abundance tref ( array:item abundance tref ) - 1
  if ( array:item abundance tref = 0 ) [ set richness richness - 1 ]
  
  if ( true ) [ die ]
end

to reproduce ;; plant
  let num 0  ; num seeds
  let sr 0.0 ; seed resource
  let fecund? false
  ;; check fecundity
  if ( ( remainder age tdfv ) = 0 ) [ set fecund? true ]
    
  if ( fecund? ) [
    ;show (word "is fecund")
    let tsl su + (stl * strr)
    set num floor ( tsl / ( essential_uptake_trait 1 ) )
    
    if (num > 0) [ 
      ;; max-seeds monitor
      if (num > max-seeds) [ 
        set max-seeds num 
        ask patch-here [ set pcolor black ]
        ask patch  max-seeds-px  max-seeds-py [ set pcolor white ]
        set max-seeds-px pxcor 
        set max-seeds-py pycor
        ]
      
      ;; calculate seed numbers
      set sr tsl / num
      ; allocate resources
      set stl stl - ( tsl - su )
      set su 0      

      ;; disperse offsprings
      repeat num [
        ; position
        let ver ( random ( 2 * sdp + 1 ) - sdp )
        let hor ( random ( 2 * sdp + 1 ) - sdp )
        let destination patch-at hor ver
        if not ( nobody = destination ) [ ; if destination is valid
          if ( ( count plants-on destination ) = 0 ) [ 
              ;show (word "hatched at " ver " " hor) 
              array:set abundance tref ( array:item abundance tref ) + 1
              let lcolor color
              
              hatch 1 [                
                move-to destination
                if links? [
                create-plant-link-with myself [ 
                  set time 0 
                  set color lcolor
                  ]
                ]
                set su 0
                set stl 0
                set ss 0
                set dvs 0
                set age 0                                
                
                set csl (essential_uptake_trait 0)
              ]
              ask destination [ replenish-substrate sr ]    
           ]        
         ]            
      ]
      
      ;; amend development stage
      set tsl (stl + ss)
      let fin 0
      if ( csl < tsl ) [ set fin 1 ] ; requirement is smaller than what already possessed
      
      while [(fin = 0) and (dvs > 0)] [ 
        set dvs dvs - 1        
        set csl csl - (essential_uptake_trait dvs)
        if (csl < tsl) [ set fin 1 ]
        
        ;show (word "dvs--")
      ]      
    ]    
  ]
end


;;;;;;;;;;;;;;;;;;;;;
;;; Traits        ;;;
;;;;;;;;;;;;;;;;;;;;;

to-report essential_uptake_trait [ i_dvs ] ;; essential uptake trait
let a a_mean
let x0 x0_mean

let rrr ( eu_y0 + a / ( 1 + exp (-( i_dvs - x0 ) / eu_b )) )
if (rrr < 0) [ 
show (word "rrr<0")
set rrr 0 ]

report rrr
end


to-report requested_uptake_trait ;; plant
report reur * (essential_uptake_trait dvs)
end

to-report resource_capture_proportion_trait [ rng ] ;; plant
let ep floor ( dvs * 5.0 / mds)
if (ep > 4) [ set ep 4 ]
let idx (rcdt * 10) +  ( rng * 5 ) + ep
;show (word "idx=" idx ", ep=" ep ", rng=" rng)
let rcp array:item rca_defs ( idx )
if (rng > 0) [ set rcp ( rcp / (8 * rng) ) ]

report rcp
end

to-report developmental_storage_requirement_evaluation
let dst 0
let i 0
while [ i <= ( dvs + 1 ) ]
[ set dst ( dst + (essential_uptake_trait i) ) 
  set i i + 1
  ]
report dst ; * reur
end

to do-plotting
  set-current-plot "Richness"
  set-current-plot-pen "richness"
  plot richness

  set-current-plot "Abundance"
  ;;let labundance array:to-list abundance
  ;;set-plot-x-range 0 max labundance
  ;;histogram labundance
  clear-plot
  set-plot-x-range 0 species
  set-plot-y-range 0 ( max array:to-list abundance + 1 )
  let i 0
  while [ i < species ] [
    ;set-plot-pen-color array:item species-colors i
    plotxy i array:item abundance i
    set i i + 1
  ]
  
  set-current-plot "Development stage"  
  histogram [dvs] of plants
  
  set-current-plot "Ages"  
  set-plot-x-range 0 ( max-age + 1 )
  set-histogram-num-bars 25  
  histogram [age] of plants    

end

to reset
  set max-dvs 0
  set max-age 0
  set max-seeds 0
  set max-seeds-px 0
  set max-seeds-py 0
end

to trim
  ask plants [
    if ( age > beyond-age ) [ individual-death ]
  ]
end