Estuaryscape
Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)
PURPOSE
This model attempts to simulate spatial interaction of 2 flatfish and 3 prey types in an estuary, featuring two different habitats, simple prey population dynamics, reproduction and competition. The model has simplified bioenergetics governing the state of each agent.
Lots of monitors help parameterise, but there are a lot of parameters! Try to see how many days your species can survive!
I am aware the model still has bugs here and there, this was done in 3 days, so not much time to debug... but I will be improving the code in my spare time.
BACKGROUND
The common sole (Solea solea) and the Senegalese sole (Solea senegalensis) have come to share the same habitats, as climate change allows the latter species to move further North and overlap the habitat of the common sole. These very similar species now have to survive the fierce competition for similar resources. On the first year, they mostly eat zooplankton in the water column, but then they feed on both worms (polychaetes such as Hediste diversicolor) and bivalves (such as Scrobicularia plana).
AGENT TYPES
The only moving agents are 2 fish species acting as competing predators. Three prey types are mostly fixed to a patch, varying only in their population densities. These are worms, bivalves and zooplankton.
AGENT ATTRIBUTES
Both fish species have similar properties, which can be set equally or differently:
- age-at-maturity: age at which a fish becomes an adult and is fit for reproduction
- max age: maximum age
- maximum feeding rate: maximum total size of prey a fish can eat in a day
- energy reserve size: the size of the energy reserve, measured in arbitrary energy units, which limits feeding rates
- maintenance cost: energy required to support life
- small-movement cost: energy cost of staying in the same patch
- large-movement cost: energy cost of moving to another patch
- reproduction threshold: surplus energy level at which an adult fish becomes fit to produce gametes and starts to seek females
- cost-per-gamete: energy cost of producing one gamete. This is used to calculate the number of eggs to generate.
- Days until hatch: days from egg fecundation to hatch.
- Egg mortality: fraction of eggs that die during the days it takes to hatch
- Plankton eating period: amount of days post-settlement during which the fish only eats plankton.
Fish state variables include:
- coordinates of their current patch
- sex
- an energy reserve compartment that stores energy assimilated from consumed prey, minus the maintenance costs
- age (days)
- life stage: juvenile or adult
All three prey types have similar fixed properties, but they can be different between types:
- weight per prey: this impacts feeding rate, because larger prey occupy more volume in a stomach.
- energy gain from prey: this is the amount of energy contained in 1 gram of prey, minus the energy required to eat it (chase, chew, filter…).
- Growth rate, as in a fixed number of new individuals per day.
- Carrying capacity in mudflats: maximum number of prey in mudflats
- Carrying capacity in canals: maximum number of prey of this type in canals
ENVIRONMENT
The environment is a spatially explicit depiction of a generic estuary with patches representing 2 habitats, mudflats and sandy canals. A third patch color is used to represent land, where nothing happens.
A patch represents 4 square meters. Each habitat can better support different types of prey. By default, worms prefer mudflats, bivalves prefer the canals and free-swimming plankton have no preference. Depth and water currents are ignored.
AGENT BEHAVIOUR
Fish move by examining surrounding patches and deciding to stay or move to another patch based on the competition existing on the current patch, potential energy gains, current energy levels and whether or not they are ready to reproduce. Although there is a grid movement, fish are "jittered" for better visualisation (to avoid all fish in a patch being overlapped).
While on a patch, fish eat prey based on the energy requirements and feeding rate. Because fish can only pick one prey type per day, prey choice involves a decision process based on the potential energy gains.
Adults with enough energy reproduce if an adult of the opposite sex with enough energy to do so is present. Surviving fish eggs will remain in the patch of origin for the required time. Once they hatch, juveniles are randomly distributed across mudflat patches (less water flow, more protection) across the map. If they can eat given the current competition in the patch, they will be added as fish agents, if not the settlement is not successful and larvae die. Prey grow with a pre-defined fixed rate, limited by carrying capacities.
MODEL SCHEDULE
At the beggining, the map is loaded and fish are placed randomly on non-land patches, species and sexes are chosen randomly and ages are distributed normally around the middle of life expectancy.
Each model cycle represents one day, and events occur in this order:
- fish die if too old
- fish increase age, juveniles change to adults if they reach maturity, max energy, feeding rate and maintenance costs are proportional to age, until they reach the maximum at maturity.
- fish pay maintenance-costs or die!
- fish move or stay by scanning the environment
- fish eat-prey, larger fish get to eat first
- eggs age advances
- eggs that reach full development hatch
- fish reproduce
- prey grows back
INPUTS AND OUTPUTS
Inputs
The initial number of fish from each breed, the percentage cover of each habitat type and all the parameters described for fish and prey.
Outputs
The population of each fish species, the number of days/years until population collapses, the spatial distribution of species and sizes.
Ultimately, it serves to attempt if two competing predators can find a way to survive and avoid the heavy costs of competition, even if the preferences for a certain habitat or prey are not specifically stated.
WHAT TO DO
The mode has a lot of parameters, but it is still a very simplistic representation, so it can be hard to parameterise! Experimenting with species attributes and prey availabilities can lead to catastrophic outcomes very easily. Try to see how many days the populations can last. Try to give advantages to a species, such as faster maturity or more fecundity.
There is a map editor so you can draw your own estuary using the mouse! And then save the map as an .asc file to use later! See how the fish do in your estuary.
REFERENCES
Cabral, H. N., Costa, M. J. (1999) Differential use of nursery areas within the Tagus estuary by sympatric soles, Solea solea and Solea senegalensis. Environmental Biology of Fishes 56, 389–397.
Froese, R., Pauly, D. (Eds.) (2016) FishBase. World Wide Web electronic publication. www.fishbase.org, ( 06/2016 ).
Lagardère, J.P. (1987) Feeding ecology and daily food consumption of common sole, Solea vulgaris Quensel, juveniles on the French Atlantic coast. Journal of Fish Biology 30, 91-104.
Vinagre, C., Cabral, H. N. (2008) Prey consumption by the juvenile soles, Solea solea and Solea senegalensis, in the Tagus estuary, Portugal. Estuarine, Coastal and Shelf Science 78, 45–50.
COPYRIGHT AND LICENSE
Copyright 2017 Miguel P. Pais
This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-sa/4.0/
Comments and Questions
;;;;;;;;;;;;;;;;;;;;;; ;; ;; Created by Miguel Pessanha Pais as a final project for the intro to ABM MOOC 2016 ;;ESTUARYSCAPE MODEL;; by Bill Rand @ Complexity Explorer ;; ;; ;;;;;;;;;;;;;;;;;;;;;; Contact: mppais@fc.ul.pt extensions [gis] breed [fishes fish] globals[ the-map non-land-patches ; an agentset of patches that excludes land patches, to avoid unnecessary calculations happening in land ; other globals are on the interface ] fishes-own [ energy ; current energy level, limited by energy-reserve-size species ; green or red species sex ; male, female or undecided (joking, just male or female really) reserve-size ; maximum energy reserve size maintenance-cost ; energy cost to maintain bodily functions (metabolism,respiration, osmotic regulation, etc) age ; age (in days) stage ; juvenile or adult age-at-maturity ; age at which a fish becomes and adult (able to reproduce) (days) max-age ; maximum age for fish (instant death lies beyond this point) nr-gametes ; nr of gametes produced by adults feeding-rate ; max amount of prey grams per day reproduction-threshold ; energy amount over which an adult fish can produce and release gametes ] patches-own [ worms bivalves plankton habitat ; canal or mudflat green-newcomers red-newcomers red.eggs ; red fish eggs, coded as a list with the length equal to "days-until-hatch". The first item is the amount of eggs released on the present day, the last item is eggs who have been here for "days-until-hatch" days and are ready to hatch. green.eggs ; green fish eggs, see the description above ] ; Model setup and schedule to startup set map-file "map.asc" load-map end to setup clear-all load-map setup-environment setup-fishes reset-ticks end to go if not any? fishes [ stop ] ask fishes [ grow ; die if too old, increase age otherwise (also controls life stage change) pay-maintenance ; pay maintenance-costs or die! move-or-stay ; move or stay based on the scan decision ] fish-eat-prey ; fish eat prey, larger fish get to eat first egg-development ; eggs age advances hatch-eggs ; eggs that reach full development hatch fish-reproduction ; fish reproduce regrow-prey ; prey grows back tick end ; SETUP PROCEDURES to setup-fishes create-fishes initial-number-of-fishes [ move-to-and-jitter one-of non-land-patches ; place fishes on a random patch that is not land and jitter set color one-of [red green] set sex one-of ["male" "female"] set shape "fish" ] ask fishes with [color = red] [ ; setup red fish attributes set species "red" set age-at-maturity age-at-maturity-red * 365 ; convert age to days (ticks) set max-age max-age-red * 365 set feeding-rate max-feeding-rate-red set reproduction-threshold reproduction-threshold-red ] ask fishes with [color = green] [ ; setup green fish attributes set species "green" set age-at-maturity age-at-maturity-green * 365 ; convert age to days (ticks) set max-age max-age-green * 365 set feeding-rate max-feeding-rate-green set reproduction-threshold reproduction-threshold-green ] ask fishes [ set reserve-size max-energy-reserve set age floor random-normal (max-age / 2) ((max-age / 2) * 0.3) ; distribute ages with the mean as half the life expectancy and a CV of 30% if age < 0 [set age 0] ; correct fish with negative age ifelse age >= age-at-maturity [set stage "adult"] [set stage "juvenile"] ; assign life stages set size 0.3 + ((age / max-age) * 0.3) ; scale the size according to age scale-reserve-size scale-maintenance scale-feeding-rate set energy (0.7 * reserve-size) + (random-float 0.3 * reserve-size) ; initial energy varies randomly from 70 to 100% reserve size ] end ; setup the environment to load-map ;observer procedure carefully [ set the-map gis:load-dataset map-file gis:apply-raster the-map pcolor ask patches [ if pcolor = 96 [set habitat "canal"] if pcolor = 37 [set habitat "mudflat"] if pcolor = green [set habitat "land"] ] ] [create-map-file] set non-land-patches patches with [habitat != "land"] end to setup-environment ; observer procedure ask non-land-patches [ set green.eggs n-values days-until-hatch [0] ; eggs are initialized as lists of length "days-until-hatch" set red.eggs n-values days-until-hatch [0] ] ask non-land-patches with [habitat = "mudflat"] [ ; patches are populated with a random number of prey between half and total carrying capacity set worms random-between (floor max-worms-mudflat / 2) max-worms-mudflat set bivalves random-between (floor max-bivalves-mudflat / 2) max-bivalves-mudflat set plankton random-between (floor max-plankton-mudflat / 2) max-plankton-mudflat ] ask non-land-patches with [habitat = "canal"] [ set worms random-between (floor max-worms-canal / 2) max-worms-canal set bivalves random-between (floor max-bivalves-canal / 2) max-bivalves-canal set plankton random-between (floor max-plankton-canal / 2) max-plankton-canal ] end ; this startup procedure generates an example map and saves the map as a raster file in the model folder. This only happens if the file is not found. to create-map-file ; observer procedure set the-map [ 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 96 96 96 96 96 96 96 96 96 96 96 96 96 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 96 96 96 96 96 96 96 96 96 96 96 96 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 96 96 96 96 96 96 96 96 96 96 96 96 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 96 96 96 96 96 96 96 96 96 96 96 96 96 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 96 96 96 96 96 96 96 96 96 96 96 96 55 55 55 55 55 55 55 55 55 55 37 37 37 37 37 37 37 37 37 37 37 37 37 55 55 55 55 55 55 55 55 55 55 55 55 55 37 96 96 96 96 96 96 96 96 96 96 96 96 55 55 55 55 55 55 55 55 55 55 37 96 96 96 37 37 37 37 37 37 37 37 37 37 37 55 55 55 55 55 55 55 55 55 55 55 37 37 96 96 96 96 96 96 96 96 96 96 96 55 55 55 55 55 55 55 55 55 55 55 37 37 37 96 96 37 37 37 37 37 96 96 37 37 37 37 37 37 37 37 55 55 55 55 37 37 37 96 96 96 96 96 96 96 96 96 96 96 55 55 55 55 55 55 55 55 55 55 55 55 37 37 37 37 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 55 55 55 55 55 55 55 55 55 55 55 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 37 55 55 55 55 55 55 55 55 55 55 55 37 37 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 55 55 55 55 55 55 55 55 55 55 55 37 37 37 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 55 55 55 55 55 55 55 55 55 55 55 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 55 55 55 55 55 55 55 55 55 55 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 55 55 55 55 55 55 55 55 55 55 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 55 55 55 55 55 55 55 55 55 37 37 37 37 37 37 96 96 96 96 37 37 37 96 96 96 96 96 96 96 96 96 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 55 55 55 55 55 55 55 55 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 55 55 55 55 55 55 55 55 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 55 55 55 55 55 55 37 37 37 96 96 96 37 37 37 37 37 37 37 96 96 96 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 55 55 55 55 55 55 37 96 96 96 96 96 37 37 37 37 37 96 96 96 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 55 55 55 55 55 37 96 96 96 37 37 37 37 37 96 96 96 37 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 37 96 96 96 96 96 37 37 37 37 37 55 55 55 55 37 37 96 37 37 37 37 37 96 96 96 37 37 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 37 37 96 96 96 96 96 96 37 37 37 37 37 55 55 55 37 37 37 37 37 37 37 37 96 96 37 37 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 37 37 96 96 96 96 96 96 96 37 37 37 37 55 55 55 37 37 37 37 37 37 96 37 37 96 37 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 96 96 96 96 37 96 96 37 37 37 55 55 55 37 37 37 37 37 37 96 96 96 96 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 96 96 96 96 37 37 96 96 37 37 37 37 55 37 37 37 37 37 96 96 37 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 96 96 96 96 96 37 37 96 37 37 96 37 37 37 37 37 37 37 96 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 96 96 96 96 37 37 96 96 37 96 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 96 96 96 37 37 37 96 96 96 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 96 96 96 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 96 96 96 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 37 37 96 96 96 96 37 37 37 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 37 37 37 37 37 96 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 37 37 37 37 96 96 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 37 37 37 37 37 96 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 37 37 37 37 37 96 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 37 37 37 37 37 37 96 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 96 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 96 37 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 96 96 37 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 96 96 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 96 37 37 37 37 37 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 37 37 55 55 55 55 55 55 37 37 37 96 96 96 37 37 55 55 55 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 37 37 37 37 55 55 55 55 55 55 55 55 37 37 37 96 37 37 37 55 55 55 55 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 37 55 55 55 55 55 55 55 55 55 55 55 55 55 55 37 37 37 55 55 55 55 55 55 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 37 37 37 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 37 55 55 55 55 55 55 55 ] ask patches [set pcolor item (pxcor - ((pycor - 49) * 50)) the-map if pcolor = 96 [set habitat "canal"] if pcolor = 37 [set habitat "mudflat"] if pcolor = 55 [set habitat "land"] ] gis:set-world-envelope (list min-pxcor max-pxcor min-pycor max-pycor) set the-map gis:patch-dataset pcolor gis:store-dataset the-map "map" user-message "Welcome! The specified map file was not found or this is your first time here! The default map has been loaded and saved as a map.asc file in your model folder. This message will only appear again if you delete this file. If you are feeling creative, use the map editor to create maps and save them, but don't forget to give them a different name! Have fun exploring!" end ;; FISH-RELATED PROCEDURES to scale-reserve-size ; fish procedure ; reserve size starts at 10% max when age = 0 and increases until 100% at age-at-maturity set maintenance-cost (0.1 * reserve-size) + ((age / (age-at-maturity)) * (0.9 * reserve-size)) end to scale-maintenance ; fish procedure ; maintenance cost starts at 10% max when age = 0 and increases until 100% at age-at-maturity set maintenance-cost (0.1 * max-maintenance-cost) + ((age / (age-at-maturity)) * (0.9 * max-maintenance-cost)) end to scale-feeding-rate ; fish procedure ; feeding rate starts at 10% max when age = 0 and increases until 100% at age-at-maturity set feeding-rate (0.1 * feeding-rate) + ((age / (age-at-maturity)) * (0.9 * feeding-rate)) end to pay-maintenance ; fish procedure set energy energy - maintenance-cost if energy <= 0 [die] ; fish die if they can't pay maintenance end to move-to-and-jitter [p] ; fish procedure ; moves to a patch and jitters fish coordinates within patch for easier visualization let x [pxcor] of p let y [pycor] of p setxy (x + random-float-between -0.49 0.49) (y + random-float-between -0.49 0.49) end to grow ; fish procedure if age >= max-age [die] set age age + 1 if age = age-at-maturity [set stage "adult"] ; puberty... set size 0.3 + ((age / max-age) * 0.3) ; scale the size according to age scale-reserve-size scale-maintenance end ; fishes decide whether to stay or move based on the conditions of the current patch to move-or-stay ; fish procedure ifelse energy < (maintenance-cost + small-movement-cost) [stay] [ ; if really low on energy, just don't move. Else, it depends on who you are and what you need. if (stage = "adult") [ ifelse energy > reproduction-threshold [ ifelse any? fishes-here with [sex != [sex] of myself and species = [species] of myself] [stay] [move] ; if ready to reproduce, check for opposite sex and same species, leave if not found ] [ scan-prey ; if an adult, but not ready to reproduce, scan prey options ] ] if (age > plankton-eating-period and stage = "juvenile") [ ; if a juvenile has left plankton eating period, scan prey options scan-prey ] if (age <= plankton-eating-period) [ ; if in the plankton eating period let required-energy reserve-size - energy let potentially-available-energy 0 ifelse any? other fishes-here with [age <= plankton-eating-period] [ set potentially-available-energy energy-gain-from-plankton * ((plankton * weight-per-plankton) - sum [feeding-rate] of other fishes-here with [age <= plankton-eating-period]) ; if there are other young juveniles here, check energy gain from available plankton grams if everyone ate their max. ifelse potentially-available-energy < required-energy [move] [stay] ] [ set potentially-available-energy (plankton * plankton-value) ; if there are not any young juveniles here, just check if there is enough plankton for me ifelse potentially-available-energy < required-energy [move] [stay] ] ] ] end ; fish evaluate the amount of energy they need and the available energy at the current patch, and wether larger fish will likely eat everything to scan-prey ; fish procedure let required-energy 0 let worms-available-energy 0 let bivalves-available-energy 0 ifelse any? other fishes-here with [age > plankton-eating-period and size >= [size] of myself] [ set required-energy reserve-size - energy set worms-available-energy energy-gain-from-worms * ((worms * weight-per-worm) - sum [feeding-rate] of other fishes-here with [age > plankton-eating-period and size >= [size] of myself]) ; if there are other larger fish here, check energy gain from available worms grams if everyone ate worms (exclude very young plankton eaters) set bivalves-available-energy energy-gain-from-bivalves * ((bivalves * weight-per-bivalve) - sum [feeding-rate] of other fishes-here with [age > plankton-eating-period and size >= [size] of myself]) ; if there are other fish here, check energy gain from available worms grams if everyone ate worms (exclude very young plankton eaters) ifelse (worms-available-energy < required-energy or bivalves-available-energy < required-energy) [move] [stay] ] [ set required-energy reserve-size - energy set worms-available-energy (worms * worms-value) ; if there are not any other fish here, just check if there is enough food for me (exclude young plankton eaters) set bivalves-available-energy (bivalves * bivalves-value) ifelse (worms-available-energy < required-energy or bivalves-available-energy < required-energy) [move] [stay] ] end to move ; fish procedure ; fish move to a neighboring patch, spending more energy in locomotion set energy energy - large-movement-cost move-to-and-jitter one-of neighbors with [habitat != "land"] end to stay ; fish procedure ; fish just move within the patch, spending less energy set energy energy - small-movement-cost end ; The extremely complex thought process of fish as they pick which prey to eat based on their needs. to eat ; fish procedure ifelse age <= plankton-eating-period [ ; if you are a young plankton eater if plankton = 0 [stop] ; if there's no plankton here, I'm not eating today let required-amount ceiling ((reserve-size - energy) / (energy-gain-from-plankton)) ; required amount (in grams) if required-amount > feeding-rate [set required-amount feeding-rate] ; required amount is limited by feeding rate let available-amount (plankton * weight-per-plankton) ; available amount (in grams) let consumed-amount min list required-amount available-amount ; each fish consumes the minimum value among required and available ask patch-here [ set plankton plankton - ceiling (consumed-amount / weight-per-plankton) ; eat the number of plankton required ] set energy energy + ceiling (consumed-amount / weight-per-plankton) * plankton-value ; replenish energy ] [ ; else ; if you can eat big prey if worms = 0 and bivalves = 0 [stop] ; if there are no big prey, I'm not eating today let required-amount-worms ceiling ((reserve-size - energy) / (energy-gain-from-worms)) ; required amount of worms (in grams) let required-amount-bivalves ceiling ((reserve-size - energy) / (energy-gain-from-bivalves)) ; required amount of bivalves (in grams) if required-amount-worms > feeding-rate [set required-amount-worms feeding-rate] ; required amounts are limited by feeding rates if required-amount-bivalves > feeding-rate [set required-amount-bivalves feeding-rate] let available-amount-worms (worms * weight-per-worm) ; available amount (in grams) let available-amount-bivalves (bivalves * weight-per-bivalve) let chosen-prey "none" ; create local variable let consumed-amount 0 ; create local variable if ((required-amount-worms - available-amount-worms <= 0) and (required-amount-bivalves - available-amount-bivalves <= 0)) [ ; if any prey can fill up energy, pick the one that can do it with less quantity ifelse required-amount-worms < required-amount-bivalves [ set chosen-prey "worms" set consumed-amount required-amount-worms ] [ set chosen-prey "bivalves" set consumed-amount required-amount-bivalves ] ] if ((required-amount-worms - available-amount-worms <= 0) and (required-amount-bivalves - available-amount-bivalves > 0)) [ ; if only worms can fill up energy, eat worms set chosen-prey "worms" set consumed-amount required-amount-worms ] if ((required-amount-worms - available-amount-worms > 0) and (required-amount-bivalves - available-amount-bivalves <= 0)) [ ; if only bivalves can fill up energy, eat bivalves set chosen-prey "bivalves" set consumed-amount required-amount-bivalves ] if ((required-amount-worms - available-amount-worms > 0) and (required-amount-bivalves - available-amount-bivalves > 0)) [ ; if none of the prey can fill up energy, pick the one which can provide more energy that day and eat what's available ifelse (available-amount-worms * energy-gain-from-worms) > (available-amount-bivalves * energy-gain-from-bivalves) [ set chosen-prey "worms" set consumed-amount available-amount-worms ] [ set chosen-prey "bivalves" set consumed-amount available-amount-bivalves ] ] ask patch-here [ ifelse chosen-prey = "worms" [set worms worms - ceiling (consumed-amount / weight-per-worm) ; deplete worms or bivalves from the patch depending on chosen prey ] [ set bivalves bivalves - ceiling (consumed-amount / weight-per-bivalve) ] ] ifelse chosen-prey = "worms" [set energy energy + ceiling (consumed-amount / weight-per-worm) * worms-value ; gain energy from worms or bivalves depending on chosen prey ] [ set energy energy + ceiling (consumed-amount / weight-per-bivalve) * bivalves-value ] ] ; end ifelse end to fish-eat-prey ; observer procedure ask fishes with [not any? other fishes-here] [eat] ; fish who are alone eat the most valuable prey if there is enough quantity ask non-land-patches with [count fishes-here > 1] [sort-out-competition] ; when there are crowded patches, the patch handles prey distribution end to sort-out-competition ; patch procedure foreach sort-on [0 - size] fishes-here [ ?1 -> ; fishes eat in descending order of size (proxy of age) ask ?1 [eat] ] end ; If both sexes of adults ready for reproduction are present, they release gametes to the patch. Incubation is external, so it occurs on the patch, mixing up gametes from several males and females. to fish-reproduction ; observer procedure ask non-land-patches with [length (remove-duplicates [sex] of fishes-here with [species = "green" and stage = "adult" and energy > reproduction-threshold]) = 2] [ ; patches with both sexes of green adults fit for reproduction let green-reproductive-adults fishes-here with [species = "green" and stage = "adult" and energy > reproduction-threshold] ask green-reproductive-adults [ set nr-gametes floor (energy - reproduction-threshold) / cost-per-gamete ; the number of eggs procuced equals the surplus energy divided by the energetic cost per gamete set energy (energy - (nr-gametes * cost-per-gamete)) ; energy of the gametes produced is removed from the fish ] let green-female-gametes sum [nr-gametes] of green-reproductive-adults with [sex = "female"] let green-male-gametes sum [nr-gametes] of green-reproductive-adults with [sex = "male"] set green.eggs replace-item 0 green.eggs ((min list green-female-gametes green-male-gametes) * (1 - (egg-mortality-green / 100))) ; the minimum number between female and male gametes is picked as the nr of eggs (two are needed). The other gametes are wasted. ask green-reproductive-adults [set nr-gametes 0] ] ask non-land-patches with [length (remove-duplicates [sex] of fishes-here with [species = "red" and stage = "adult" and energy > reproduction-threshold]) = 2] [ ; patches with both sexes of red adults fit for reproduction let red-reproductive-adults fishes-here with [species = "red" and stage = "adult" and energy > reproduction-threshold] ask red-reproductive-adults [ set nr-gametes floor (energy - reproduction-threshold) / cost-per-gamete ; the number of eggs procuced equals the surplus energy divided by the energetic cost per gamete set energy (energy - (nr-gametes * cost-per-gamete)) ] let red-female-gametes sum [nr-gametes] of red-reproductive-adults with [sex = "female"] let red-male-gametes sum [nr-gametes] of red-reproductive-adults with [sex = "male"] set red.eggs replace-item 0 red.eggs ((min list red-female-gametes red-male-gametes) * (1 - (egg-mortality-red / 100))) ; the minimum number between female and male gametes is picked as the nr of eggs (two are needed). The other gametes are wasted. ask red-reproductive-adults [set nr-gametes 0] ] end ;; PATCH-RELATED PROCEDURES to egg-development ; observer procedure ask non-land-patches [ set green.eggs remove-item (days-until-hatch - 1) green.eggs ; the eggs list shifts one position to the right, the last item being the eggs ready to hatch on the current tick set red.eggs remove-item (days-until-hatch - 1) red.eggs set green.eggs fput 0 green.eggs set red.eggs fput 0 red.eggs ] end ; eggs that have reached "days-until-hatch" are sent to a random number of mudflat patches between half the total area and the total mudflat area to hatch-eggs ; observer procedure let mudflat-patches non-land-patches with [habitat = "mudflat"] ask non-land-patches with [last green.eggs > 0] [ ; hatch green eggs let nr-green-eggs last green.eggs set green.eggs replace-item (days-until-hatch - 1) green.eggs 0 ;eggs hatched, so they are removed from the patch variable let number-patches 0 ifelse nr-green-eggs > count mudflat-patches [ set number-patches random-between (floor count mudflat-patches / 2) (floor count mudflat-patches) ] [ set number-patches random-between 1 nr-green-eggs ; if small amount of eggs, max patches is nr of eggs (1 egg per patch) ] ask n-of number-patches mudflat-patches [ set green-newcomers green-newcomers + nr-green-eggs / number-patches ] ] ask non-land-patches with [last red.eggs > 0] [ ; hatch red eggs let nr-red-eggs last red.eggs set red.eggs replace-item (days-until-hatch - 1) red.eggs 0 ;eggs hatched, so they are removed from the patch variable let number-patches 0 ifelse nr-red-eggs > count mudflat-patches [ set number-patches random-between (floor count mudflat-patches / 2) (floor count mudflat-patches) ] [ set number-patches random-between 1 nr-red-eggs ] ask n-of number-patches mudflat-patches [ set red-newcomers red-newcomers + nr-red-eggs / number-patches ] ] ask mudflat-patches with [green-newcomers > 0 and red-newcomers > 0] [ ; patches with both species trying to settle. Each species scans 1/4 of the carrying capacity let carrying-capacity floor (plankton * weight-per-plankton) / (max-feeding-rate-green * 0.1) ; 10% feeding rate at age 0 let settled-greens min list (floor (carrying-capacity / 4)) green-newcomers ; number of settlers limited by carrying capacity let settled-reds min list (floor (carrying-capacity / 4)) red-newcomers settle-greens settled-greens settle-reds settled-reds set red-newcomers 0 set green-newcomers 0 ] ask mudflat-patches with [green-newcomers = 0 and red-newcomers > 0] [ ; patches with only red settlers, scan 1/2 of the carrying capacity let carrying-capacity (plankton * weight-per-plankton) / (max-feeding-rate-red * 0.1) let settled-reds min list (carrying-capacity / 2) red-newcomers settle-reds settled-reds set red-newcomers 0 ] ask mudflat-patches with [green-newcomers > 0 and red-newcomers = 0] [ ; patches with only green settlers, scan 1/2 of the carrying capacity let carrying-capacity (plankton * weight-per-plankton) / (max-feeding-rate-green * 0.1) let settled-greens min list (carrying-capacity / 2) green-newcomers settle-greens settled-greens set green-newcomers 0 ] end to settle-reds [nr] ; patch procedure sprout-fishes nr [ set reserve-size max-energy-reserve set sex one-of ["male" "female"] set shape "fish" set species "red" set color red set age 0 set size 0.3 set age-at-maturity age-at-maturity-red * 365 ; convert age to days (ticks) set max-age max-age-red * 365 set feeding-rate max-feeding-rate-red set reproduction-threshold reproduction-threshold-red scale-reserve-size scale-maintenance scale-feeding-rate set energy (0.7 * reserve-size) + (random-float 0.3 * reserve-size) ; initial energy varies randomly from 70 to 100% reserve size move-to-and-jitter patch-here ; jitter in the current patch ] end to settle-greens [nr] ; patch procedure sprout-fishes nr [ set reserve-size max-energy-reserve set sex one-of ["male" "female"] set shape "fish" set species "green" set color green set age 0 set size 0.3 set age-at-maturity age-at-maturity-green * 365 ; convert age to days (ticks) set max-age max-age-green * 365 set feeding-rate max-feeding-rate-green set reproduction-threshold reproduction-threshold-green scale-reserve-size scale-maintenance scale-feeding-rate set energy (0.7 * reserve-size) + (random-float 0.3 * reserve-size) ; initial energy varies randomly from 70 to 100% reserve size move-to-and-jitter patch-here ; jitter in the current patch ] end to regrow-prey ; obsever procedure ask non-land-patches [ if worms < 0 [set worms 0] if bivalves < 0 [set bivalves 0] if plankton < 0 [set plankton 0] set worms worms + worms-regrowth-rate set bivalves bivalves + bivalves-regrowth-rate set plankton plankton + plankton-regrowth-rate ; limit the amount of prey to the carrying capacity of the habitat if habitat = "mudflat" [ if worms > max-worms-mudflat [set worms max-worms-mudflat] if bivalves > max-bivalves-mudflat [set bivalves max-bivalves-mudflat] if plankton > max-plankton-mudflat [set plankton max-plankton-mudflat] ] if habitat = "canal" [ if worms > max-worms-canal [set worms max-worms-canal] if bivalves > max-bivalves-canal [set bivalves max-bivalves-canal] if plankton > max-plankton-canal [set plankton max-plankton-canal] ] ] end ;; PREY REPORTERS to-report worms-value report precision (energy-gain-from-worms * weight-per-worm) 3 end to-report bivalves-value report precision (energy-gain-from-bivalves * weight-per-bivalve) 3 end to-report plankton-value report precision (energy-gain-from-plankton * weight-per-plankton) 3 end ; FISH REPORTERS (these were not fully implemented, but are based on real data from Solea solea and can be used to estimate parameters.) to-report get-length [t] report 38 * (1 - exp(-0.43 * ((t / 365) + 0.1))) ; cm, t in days end to-report get-weight [L] ; g, L in cm report 0.0062 * (L ^ 3.13) end to-report get-feeding-rate [t] ; g / day, t in days let L get-length t let w get-weight L report 0.092 * w end ; PLOTTING AND OUTPUTS ; plot and monitor code is in the plots and monitors on the interface tap ; MAP EDITOR to draw-canals if mouse-down? ;; reports true or false to indicate whether mouse button is down [ ask patch mouse-xcor mouse-ycor [ set pcolor 96 set habitat "canal" display ] ] end to draw-mudflats if mouse-down? ;; reports true or false to indicate whether mouse button is down [ ask patch mouse-xcor mouse-ycor [ set pcolor 37 set habitat "mudflat" display ] ] end to erase-map if mouse-down? ;; reports true or false to indicate whether mouse button is down [ ask patch mouse-xcor mouse-ycor [ set pcolor black set habitat "" display ] ] end to fill-land ask patches with [pcolor = black] [ set pcolor green set habitat "land" ] end ;; USEFUL REPORTERS to-report random-float-between [a b] report a + random-float (b - a) end to-report random-between [a b] report a + random (b - a) end
There are 2 versions of this model.
Attached files
File | Type | Description | Last updated | |
---|---|---|---|---|
Estuaryscape.png | preview | Preview for 'Estuaryscape' | almost 9 years ago, by Miguel Pais | Download |
This model does not have any ancestors.
This model does not have any descendants.