Nplants simulator implementing Bown et al 2007's ecological model.
powered by NetLogo
view/download model file: nplants.nlogo
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.
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.
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).
This section could give some ideas of things for the user to notice while running the model.
This section could give some ideas of things for the user to try to do (move sliders, switches, etc.) with 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.
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.
This section could give the names of models in the NetLogo Models Library or elsewhere which are of related interest.
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.
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