Skip to content
Snippets Groups Projects
Commit b77f0c23 authored by xo30xoqa's avatar xo30xoqa
Browse files

Updated documentation

parent 092c7694
Branches
Tags
No related merge requests found
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>Simulation · Persephone</title><script data-outdated-warner src="../assets/warner.js"></script><link href="https://cdnjs.cloudflare.com/ajax/libs/lato-font/3.0.0/css/lato-font.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/juliamono/0.045/juliamono.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/fontawesome.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/solid.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/brands.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.13.24/katex.min.css" rel="stylesheet" type="text/css"/><script>documenterBaseURL=".."</script><script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js" data-main="../assets/documenter.js"></script><script src="../siteinfo.js"></script><script src="../../versions.js"></script><link class="docs-theme-link" rel="stylesheet" type="text/css" href="../assets/themes/documenter-dark.css" data-theme-name="documenter-dark" data-theme-primary-dark/><link class="docs-theme-link" rel="stylesheet" type="text/css" href="../assets/themes/documenter-light.css" data-theme-name="documenter-light" data-theme-primary/><script src="../assets/themeswap.js"></script></head><body><div id="documenter"><nav class="docs-sidebar"><a class="docs-logo" href="../index.html"><img src="../assets/logo.png" alt="Persephone logo"/></a><div class="docs-package-name"><span class="docs-autofit"><a href="../index.html">Persephone</a></span></div><form class="docs-search" action="../search/index.html"><input class="docs-search-query" id="documenter-search-query" name="q" type="text" placeholder="Search docs"/></form><ul class="docs-menu"><li><a class="tocitem" href="../index.html">Introduction</a></li><li><span class="tocitem">Developing</span><ul><li><a class="tocitem" href="../developing/index.html">Developing Persephone</a></li><li><a class="tocitem" href="../architecture/index.html">Source code architecture</a></li><li><a class="tocitem" href="../species-dsl/index.html">Defining new species</a></li></ul></li><li><span class="tocitem">Core</span><ul><li class="is-active"><a class="tocitem" href>Simulation</a><ul class="internal"><li><a class="tocitem" href="#simulation.jl"><span>simulation.jl</span></a></li><li><a class="tocitem" href="#landscape.jl"><span>landscape.jl</span></a></li></ul></li><li><a class="tocitem" href="../io/index.html">Input, Output, and Settings</a></li></ul></li><li><span class="tocitem">Nature</span><ul><li><a class="tocitem" href="../nature/index.html">Nature</a></li><li><a class="tocitem" href="../species/index.html">Species</a></li></ul></li><li><a class="tocitem" href="../crops/index.html">Crop submodel</a></li><li><a class="tocitem" href="../farm/index.html">Farm submodel</a></li></ul><div class="docs-version-selector field has-addons"><div class="control"><span class="docs-label button is-static is-size-7">Version</span></div><div class="docs-selector control is-expanded"><div class="select is-fullwidth is-size-7"><select id="documenter-version-selector"></select></div></div></div></nav><div class="docs-main"><header class="docs-navbar"><nav class="breadcrumb"><ul class="is-hidden-mobile"><li><a class="is-disabled">Core</a></li><li class="is-active"><a href>Simulation</a></li></ul><ul class="is-hidden-tablet"><li class="is-active"><a href>Simulation</a></li></ul></nav><div class="docs-right"><a class="docs-edit-link" href="https://git.idiv.de/xo30xoqa/persephone/blob/master/docs/src/simulation.md#" title="Edit source"><span class="docs-icon fa"></span><span class="docs-label is-hidden-touch">Edit source</span></a><a class="docs-settings-button fas fa-cog" id="documenter-settings-button" href="#" title="Settings"></a><a class="docs-sidebar-button fa fa-bars is-hidden-desktop" id="documenter-sidebar-button" href="#"></a></div></header><article class="content" id="documenter-page"><h1 id="Simulation"><a class="docs-heading-anchor" href="#Simulation">Simulation</a><a id="Simulation-1"></a><a class="docs-heading-anchor-permalink" href="#Simulation" title="Permalink"></a></h1><p>The <code>core</code> directory holds source files that are important for all submodels, including scheduling, landscape, and input/output functions.</p><h2 id="simulation.jl"><a class="docs-heading-anchor" href="#simulation.jl">simulation.jl</a><a id="simulation.jl-1"></a><a class="docs-heading-anchor-permalink" href="#simulation.jl" title="Permalink"></a></h2><p>This file includes the basal functions for initialising and running simulations.</p><article class="docstring"><header><a class="docstring-binding" id="Persephone.PARAMFILE" href="#Persephone.PARAMFILE"><code>Persephone.PARAMFILE</code></a><span class="docstring-category">Constant</span></header><section><div><p>The file that stores all default parameters.</p></div><a class="docs-sourcelink" target="_blank" href="https://git.idiv.de/xo30xoqa/persephone/blob/4954227da853bdb7bd242d937841a008cca9e54b/src/core/simulation.jl#L6-L8">source</a></section></article><article class="docstring"><header><a class="docstring-binding" id="Persephone.finalise-Tuple{Agents.AgentBasedModel}" href="#Persephone.finalise-Tuple{Agents.AgentBasedModel}"><code>Persephone.finalise</code></a><span class="docstring-category">Method</span></header><section><div><pre><code class="language-julia hljs">finalise(model)</code></pre><p>Wrap up the simulation. Currently doesn&#39;t do anything except print some information.</p></div><a class="docs-sourcelink" target="_blank" href="https://git.idiv.de/xo30xoqa/persephone/blob/4954227da853bdb7bd242d937841a008cca9e54b/src/core/simulation.jl#L63-L67">source</a></section></article><article class="docstring"><header><a class="docstring-binding" id="Persephone.initialise" href="#Persephone.initialise"><code>Persephone.initialise</code></a><span class="docstring-category">Function</span></header><section><div><pre><code class="language-julia hljs">initialise(config=PARAMFILE, seed=nothing)</code></pre><p>Initialise the model: read in parameters, create the output data directory, and instantiate the AgentBasedModel object. Optionally allows specifying the configuration file and overriding the <code>seed</code> parameter.</p></div><a class="docs-sourcelink" target="_blank" href="https://git.idiv.de/xo30xoqa/persephone/blob/4954227da853bdb7bd242d937841a008cca9e54b/src/core/simulation.jl#L13-L19">source</a></section></article><article class="docstring"><header><a class="docstring-binding" id="Persephone.simulate" href="#Persephone.simulate"><code>Persephone.simulate</code></a><span class="docstring-category">Function</span></header><section><div><pre><code class="language-julia hljs">simulate(config=PARAMFILE, seed=nothing)</code></pre><p>Carry out a complete simulation run, optionally specifying a configuration file and a seed for the RNG.</p></div><a class="docs-sourcelink" target="_blank" href="https://git.idiv.de/xo30xoqa/persephone/blob/4954227da853bdb7bd242d937841a008cca9e54b/src/core/simulation.jl#L75-L80">source</a></section></article><article class="docstring"><header><a class="docstring-binding" id="Persephone.stepsimulation!-Tuple{Agents.AgentBasedModel}" href="#Persephone.stepsimulation!-Tuple{Agents.AgentBasedModel}"><code>Persephone.stepsimulation!</code></a><span class="docstring-category">Method</span></header><section><div><pre><code class="language-julia hljs">stepsimulation!(model)</code></pre><p>Execute one update of the model.</p></div><a class="docs-sourcelink" target="_blank" href="https://git.idiv.de/xo30xoqa/persephone/blob/4954227da853bdb7bd242d937841a008cca9e54b/src/core/simulation.jl#L43-L47">source</a></section></article><h2 id="landscape.jl"><a class="docs-heading-anchor" href="#landscape.jl">landscape.jl</a><a id="landscape.jl-1"></a><a class="docs-heading-anchor-permalink" href="#landscape.jl" title="Permalink"></a></h2><p>This file manages the landscape maps that underlie the model.</p><article class="docstring"><header><a class="docstring-binding" id="Persephone.EventType" href="#Persephone.EventType"><code>Persephone.EventType</code></a><span class="docstring-category">Type</span></header><section><div><p>The types of landscape event that can be simulated</p></div><a class="docs-sourcelink" target="_blank" href="https://git.idiv.de/xo30xoqa/persephone/blob/4954227da853bdb7bd242d937841a008cca9e54b/src/core/landscape.jl#L10">source</a></section></article><article class="docstring"><header><a class="docstring-binding" id="Persephone.FarmEvent" href="#Persephone.FarmEvent"><code>Persephone.FarmEvent</code></a><span class="docstring-category">Type</span></header><section><div><pre><code class="language-julia hljs">FarmEvent</code></pre><p>A data structure to define a landscape event, giving its type, spatial extent, and duration.</p></div><a class="docs-sourcelink" target="_blank" href="https://git.idiv.de/xo30xoqa/persephone/blob/4954227da853bdb7bd242d937841a008cca9e54b/src/core/landscape.jl#L26-L31">source</a></section></article><article class="docstring"><header><a class="docstring-binding" id="Persephone.LandCover" href="#Persephone.LandCover"><code>Persephone.LandCover</code></a><span class="docstring-category">Type</span></header><section><div><p>The land cover classes encoded in the Mundialis Sentinel data.</p></div><a class="docs-sourcelink" target="_blank" href="https://git.idiv.de/xo30xoqa/persephone/blob/4954227da853bdb7bd242d937841a008cca9e54b/src/core/landscape.jl#L6">source</a></section></article><article class="docstring"><header><a class="docstring-binding" id="Persephone.Pixel" href="#Persephone.Pixel"><code>Persephone.Pixel</code></a><span class="docstring-category">Type</span></header><section><div><pre><code class="language-julia hljs">Pixel</code></pre><p>A pixel is a simple data structure to combine land use and ownership information in a single object. The model landscape consists of a matrix of pixels. (Note: further landscape information may be added here in future.)</p></div><a class="docs-sourcelink" target="_blank" href="https://git.idiv.de/xo30xoqa/persephone/blob/4954227da853bdb7bd242d937841a008cca9e54b/src/core/landscape.jl#L13-L19">source</a></section></article><article class="docstring"><header><a class="docstring-binding" id="Persephone.createevent!" href="#Persephone.createevent!"><code>Persephone.createevent!</code></a><span class="docstring-category">Function</span></header><section><div><pre><code class="language-julia hljs">createevent!(model, pixels, name, duration=1)</code></pre><p>Add a farm event to the specified pixels (a vector of position tuples) for a given duration.</p></div><a class="docs-sourcelink" target="_blank" href="https://git.idiv.de/xo30xoqa/persephone/blob/4954227da853bdb7bd242d937841a008cca9e54b/src/core/landscape.jl#L86-L90">source</a></section></article><article class="docstring"><header><a class="docstring-binding" id="Persephone.distanceto-Tuple{Tuple{Int64, Int64}, Agents.AgentBasedModel, Function}" href="#Persephone.distanceto-Tuple{Tuple{Int64, Int64}, Agents.AgentBasedModel, Function}"><code>Persephone.distanceto</code></a><span class="docstring-category">Method</span></header><section><div><pre><code class="language-julia hljs">distanceto(pos, model, habitatdescriptor)</code></pre><p>Calculate the distance from the given location to the closest location matching the habitat descriptor function. Caution: can be computationally expensive!</p></div><a class="docs-sourcelink" target="_blank" href="https://git.idiv.de/xo30xoqa/persephone/blob/4954227da853bdb7bd242d937841a008cca9e54b/src/core/landscape.jl#L119-L124">source</a></section></article><article class="docstring"><header><a class="docstring-binding" id="Persephone.distanceto-Tuple{Tuple{Int64, Int64}, Agents.AgentBasedModel, Persephone.LandCover}" href="#Persephone.distanceto-Tuple{Tuple{Int64, Int64}, Agents.AgentBasedModel, Persephone.LandCover}"><code>Persephone.distanceto</code></a><span class="docstring-category">Method</span></header><section><div><pre><code class="language-julia hljs">distanceto(pos, model, habitattype)</code></pre><p>Calculate the distance from the given location to the closest habitat of the specified type. Caution: can be computationally expensive!</p></div><a class="docs-sourcelink" target="_blank" href="https://git.idiv.de/xo30xoqa/persephone/blob/4954227da853bdb7bd242d937841a008cca9e54b/src/core/landscape.jl#L153-L158">source</a></section></article><article class="docstring"><header><a class="docstring-binding" id="Persephone.distancetoedge-Tuple{Tuple{Int64, Int64}, Agents.AgentBasedModel}" href="#Persephone.distancetoedge-Tuple{Tuple{Int64, Int64}, Agents.AgentBasedModel}"><code>Persephone.distancetoedge</code></a><span class="docstring-category">Method</span></header><section><div><pre><code class="language-julia hljs">distancetoedge(pos, model)</code></pre><p>Calculate the distance from the given location to the closest neighbouring habitat. Caution: can be computationally expensive!</p></div><a class="docs-sourcelink" target="_blank" href="https://git.idiv.de/xo30xoqa/persephone/blob/4954227da853bdb7bd242d937841a008cca9e54b/src/core/landscape.jl#L164-L169">source</a></section></article><article class="docstring"><header><a class="docstring-binding" id="Persephone.farmplot-Tuple{Tuple{Int64, Int64}, Agents.AgentBasedModel}" href="#Persephone.farmplot-Tuple{Tuple{Int64, Int64}, Agents.AgentBasedModel}"><code>Persephone.farmplot</code></a><span class="docstring-category">Method</span></header><section><div><pre><code class="language-julia hljs">farmplot(position, model)</code></pre><p>Return the farm plot at this position, or nothing if there is none (utility wrapper).</p></div><a class="docs-sourcelink" target="_blank" href="https://git.idiv.de/xo30xoqa/persephone/blob/4954227da853bdb7bd242d937841a008cca9e54b/src/core/landscape.jl#L108-L112">source</a></section></article><article class="docstring"><header><a class="docstring-binding" id="Persephone.initlandscape-Tuple{String, String}" href="#Persephone.initlandscape-Tuple{String, String}"><code>Persephone.initlandscape</code></a><span class="docstring-category">Method</span></header><section><div><pre><code class="language-julia hljs">initlandscape(landcovermap, farmfieldsmap)</code></pre><p>Initialise the model landscape based on the map files specified in the configuration. Returns a matrix of pixels.</p></div><a class="docs-sourcelink" target="_blank" href="https://git.idiv.de/xo30xoqa/persephone/blob/4954227da853bdb7bd242d937841a008cca9e54b/src/core/landscape.jl#L38-L43">source</a></section></article><article class="docstring"><header><a class="docstring-binding" id="Persephone.landcover-Tuple{Tuple{Int64, Int64}, Agents.AgentBasedModel}" href="#Persephone.landcover-Tuple{Tuple{Int64, Int64}, Agents.AgentBasedModel}"><code>Persephone.landcover</code></a><span class="docstring-category">Method</span></header><section><div><pre><code class="language-julia hljs">landcover(position, model)</code></pre><p>Return the land cover class at this position (utility wrapper).</p></div><a class="docs-sourcelink" target="_blank" href="https://git.idiv.de/xo30xoqa/persephone/blob/4954227da853bdb7bd242d937841a008cca9e54b/src/core/landscape.jl#L99-L103">source</a></section></article><article class="docstring"><header><a class="docstring-binding" id="Persephone.updateevents!-Tuple{Agents.AgentBasedModel}" href="#Persephone.updateevents!-Tuple{Agents.AgentBasedModel}"><code>Persephone.updateevents!</code></a><span class="docstring-category">Method</span></header><section><div><pre><code class="language-julia hljs">updateevents!(model)</code></pre><p>Cycle through the list of events, removing those that have expired.</p></div><a class="docs-sourcelink" target="_blank" href="https://git.idiv.de/xo30xoqa/persephone/blob/4954227da853bdb7bd242d937841a008cca9e54b/src/core/landscape.jl#L65-L69">source</a></section></article></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../species-dsl/index.html">« Defining new species</a><a class="docs-footer-nextpage" href="../io/index.html">Input, Output, and Settings »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 0.27.23 on <span class="colophon-date" title="Friday 20 January 2023 11:33">Friday 20 January 2023</span>. Using Julia version 1.9.0-alpha1.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>Defining new species · Persephone</title><script data-outdated-warner src="assets/warner.js"></script><link href="https://cdnjs.cloudflare.com/ajax/libs/lato-font/3.0.0/css/lato-font.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/juliamono/0.045/juliamono.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/fontawesome.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/solid.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/brands.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.13.24/katex.min.css" rel="stylesheet" type="text/css"/><script>documenterBaseURL="."</script><script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js" data-main="assets/documenter.js"></script><script src="siteinfo.js"></script><script src="../versions.js"></script><link class="docs-theme-link" rel="stylesheet" type="text/css" href="assets/themes/documenter-dark.css" data-theme-name="documenter-dark" data-theme-primary-dark/><link class="docs-theme-link" rel="stylesheet" type="text/css" href="assets/themes/documenter-light.css" data-theme-name="documenter-light" data-theme-primary/><script src="assets/themeswap.js"></script></head><body><div id="documenter"><nav class="docs-sidebar"><a class="docs-logo" href="index.html"><img src="assets/logo.png" alt="Persephone logo"/></a><div class="docs-package-name"><span class="docs-autofit"><a href="index.html">Persephone</a></span></div><form class="docs-search" action="search.html"><input class="docs-search-query" id="documenter-search-query" name="q" type="text" placeholder="Search docs"/></form><ul class="docs-menu"><li><a class="tocitem" href="index.html">Introduction</a></li><li><a class="tocitem" href="odd.html">Overview, Design, Details (ODD)</a></li><li><span class="tocitem">Developing</span><ul><li><a class="tocitem" href="developing.html">Developing Persephone</a></li><li><a class="tocitem" href="architecture.html">Source code architecture</a></li><li><a class="tocitem" href="gis.html">GIS data</a></li><li class="is-active"><a class="tocitem" href="species-dsl.html">Defining new species</a><ul class="internal"><li><a class="tocitem" href="#The-Persephone-species-DSL"><span>The Persephone species DSL</span></a></li><li><a class="tocitem" href="#Implementation-details"><span>Implementation details</span></a></li></ul></li></ul></li><li><span class="tocitem">Core</span><ul><li><a class="tocitem" href="simulation.html">Simulation</a></li><li><a class="tocitem" href="io.html">Input, Output, and Settings</a></li></ul></li><li><span class="tocitem">Nature</span><ul><li><a class="tocitem" href="nature.html">Nature</a></li><li><a class="tocitem" href="species.html">Species</a></li></ul></li><li><a class="tocitem" href="crops.html">Crop submodel</a></li><li><a class="tocitem" href="farm.html">Farm submodel</a></li></ul><div class="docs-version-selector field has-addons"><div class="control"><span class="docs-label button is-static is-size-7">Version</span></div><div class="docs-selector control is-expanded"><div class="select is-fullwidth is-size-7"><select id="documenter-version-selector"></select></div></div></div></nav><div class="docs-main"><header class="docs-navbar"><nav class="breadcrumb"><ul class="is-hidden-mobile"><li><a class="is-disabled">Developing</a></li><li class="is-active"><a href="species-dsl.html">Defining new species</a></li></ul><ul class="is-hidden-tablet"><li class="is-active"><a href="species-dsl.html">Defining new species</a></li></ul></nav><div class="docs-right"><a class="docs-edit-link" href="https://git.idiv.de/xo30xoqa/persephone/-/blob/master//docs/src/species-dsl.md#" title="Edit source"><span class="docs-icon fa"></span><span class="docs-label is-hidden-touch">Edit source</span></a><a class="docs-settings-button fas fa-cog" id="documenter-settings-button" href="#" title="Settings"></a><a class="docs-sidebar-button fa fa-bars is-hidden-desktop" id="documenter-sidebar-button" href="#"></a></div></header><article class="content" id="documenter-page"><h1 id="Defining-new-species"><a class="docs-heading-anchor" href="#Defining-new-species">Defining new species</a><a id="Defining-new-species-1"></a><a class="docs-heading-anchor-permalink" href="#Defining-new-species" title="Permalink"></a></h1><h2 id="The-Persephone-species-DSL"><a class="docs-heading-anchor" href="#The-Persephone-species-DSL">The Persephone species DSL</a><a id="The-Persephone-species-DSL-1"></a><a class="docs-heading-anchor-permalink" href="#The-Persephone-species-DSL" title="Permalink"></a></h2><p>In order to make implementing new species as easy as possible, Persephone includes a <a href="https://doi.org/10.1016/j.ecoinf.2015.02.005">domain-specific language (DSL)</a> built from a collection of macros and functions.</p><p>Here is an example of what this looks like, using a hypothetical mermaid species:</p><pre><code class="language-julia hljs">@species Mermaid begin
ageofmaturity = 2
pesticidemortality = 1.0
@initialise(@habitat(@landcover() == water), pairs=true)
@phase life begin
@debug &quot;$(animalid(animal)) is swimming happily in its pond.&quot;
@respond pesticide @kill(@trait(pesticidemortality), &quot;poisoning&quot;)
@respond harvest @setphase(drought)
@debug &quot;Animal: $animal&quot;
if @trait(sex) == female &amp;&amp; @countanimals() &lt; 3 &amp;&amp;
@trait(age) &gt;= @trait(ageofmaturity) &amp;&amp; @landcover() == water
@reproduce()
end
end
@phase drought begin
n = sum(1 for a in @neighbours(0))
@debug &quot;$(animalid(animal)) is experiencing drought with $n neighbour(s).&quot;
@respond sowing @setphase(life)
end
end</code></pre><p>The two most important macros are <a href="nature.html#Persephone.@species-Tuple{Any, Any}"><code>@species</code></a> and <a href="nature.html#Persephone.@phase-Tuple{Any, Any}"><code>@phase</code></a>, followed by <a href="nature.html#Persephone.@initialise-Tuple{Any, Vararg{Any}}"><code>@initialise</code></a>, <a href="nature.html#Persephone.@trait-Tuple{Any}"><code>@trait</code></a>, <a href="nature.html#Persephone.@respond-Tuple{Any, Any}"><code>@respond</code></a>, and <a href="nature.html#Persephone.@habitat-Tuple{Any}"><code>@habitat</code></a>. Other macros provide convenience wrappers for common functions. (See <code>src/nature/nature.jl</code> for details.)</p><p>The top-level macro is <a href="nature.html#Persephone.@species-Tuple{Any, Any}"><code>@species</code></a>. This takes two arguments: a species name and a definition block (enclosed in <code>begin</code> and <code>end</code> tags). At the start of the definition block, species-specific variables can be defined that should be available throughout a species&#39; lifetime. Code in this section has access to the <code>model</code> object and can thus reference the current model state. In this section, the user also has to call the <a href="nature.html#Persephone.@initialise-Tuple{Any, Vararg{Any}}"><code>@initialise</code></a> macro. This wraps the <a href="@ref"><code>initpopulation</code></a> function, and takes a habitat descriptor (see <a href="nature.html#Persephone.@habitat-Tuple{Any}"><code>@habitat</code></a> below) and several options to specify how the species&#39; population should be distributed in the landscape during model initialisation.</p><p>Following this section, each species must define one or more <a href="nature.html#Persephone.@phase-Tuple{Any, Any}"><code>@phase</code></a> blocks. The concept behind this is that species show different behaviours at different phases of their lifecycle. Each <code>@phase</code> block defines the behaviour in one of these phases. (Technically, it defines a function that will be called daily, so long as the species&#39; <code>phase</code> variable is set to the name of this phase.) Code in this section has access to the <code>model</code> object as well as an <code>animal</code> object, which is the currently active animal agent. Properties of the <code>animal</code> agent, regardless of whether they were defined by the user or by Persephone, can be accessed using the <a href="nature.html#Persephone.@trait-Tuple{Any}"><code>@trait</code></a> macro. Within a phase block, <a href="nature.html#Persephone.@respond-Tuple{Any, Any}"><code>@respond</code></a> can be used to define the species&#39; response to a <a href="simulation.html#Persephone.FarmEvent"><code>FarmEvent</code></a> that affects the species&#39; current location, while a variety of other macros provide wrappers to ecological process functions from <code>src/nature/populations.jl</code>.</p><p>Another important macro is <a href="nature.html#Persephone.@habitat-Tuple{Any}"><code>@habitat</code></a>. This defines a &quot;habitat descriptor&quot;, i.e. a predicate function that tests whether or not a given landscape pixel is suitable for a specified purpose. Such habitat descriptors are used as arguments to various functions, for example for population initialisation or movement. The argument to <code>@habitat</code> consists of a logical expression, which has access to the animal&#39;s current position (the <code>pos</code> tuple variable) and the <code>model</code>. Various macros are available to easily reference information about the current location, such as <a href="nature.html#Persephone.@landcover-Tuple{}"><code>@landcover</code></a> or <a href="nature.html#Persephone.@distancetoedge-Tuple{}"><code>@distancetoedge</code></a>.</p><h2 id="Implementation-details"><a class="docs-heading-anchor" href="#Implementation-details">Implementation details</a><a id="Implementation-details-1"></a><a class="docs-heading-anchor-permalink" href="#Implementation-details" title="Permalink"></a></h2><p>Due to a known <a href="https://juliadynamics.github.io/Agents.jl/stable/performance_tips/#Avoid-Unions-of-many-different-agent-types-(temporary!)-1">performance problem</a> with multi-agent models, the underlying implementation of species is rather complicated (see <code>src/nature/nature.jl</code> for details.)</p><p>Rather than creating a new type/struct for each species, all <a href="@ref">Animal</a> agents have the same type. Instead, they are differentiated by a <code>traits</code> dict, which stores both species-specific parameters and run-time variables. Note that due to a redefinition of the <code>getproperty()/setproperty!()</code> methods, variables from the trait dict can be accessed and modified just like normal struct fields (i.e. although <code>phase</code> is defined in the dict, not the struct, <code>animal.phase = &quot;newphase&quot;</code> works just fine - one does not have to use <code>animal.traits[&quot;phase&quot;] = &quot;newphase&quot;</code>.)</p><p>Under the hood, the <a href="nature.html#Persephone.@species-Tuple{Any, Any}"><code>@species</code></a> macro generates a function (with the name of the species), which in turn creates the trait dict when called. Thus, adding a new animal agent to the model involves instantiating an <a href="nature.html#Persephone.Animal"><code>Animal</code></a> object, then calling the relevant species function and attaching the returned dict to the agent object.</p><p>Similarly, the <a href="nature.html#Persephone.@phase-Tuple{Any, Any}"><code>@phase</code></a> macro too works by defining a new function, which is stored in the species&#39; trait dict. These functions take an animal object and the model object as input, and define what the species does during its daily update.</p><p>Once again, <a href="nature.html#Persephone.@habitat-Tuple{Any}"><code>@habitat</code></a> creates a function that takes <code>model</code> and <code>pos</code> as input and returns a boolean response. Functions that require a habitat descriptor thus take in this (anonymous) function and call it internally.</p><p>Finally, the <a href="nature.html#Persephone.@initialise-Tuple{Any, Vararg{Any}}"><code>@initialise</code></a> macro is a wrapper around <a href="@ref"><code>initpopulation</code></a>, which (yet again) creates a function that specifies how a species&#39; population is to be initialised at the beginning of a simulation run. This function is stored in the species trait dict and accessed during model setup.</p></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="gis.html">« GIS data</a><a class="docs-footer-nextpage" href="simulation.html">Simulation »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 0.27.23 on <span class="colophon-date" title="Friday 3 February 2023 15:43">Friday 3 February 2023</span>. Using Julia version 1.9.0-alpha1.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>Defining new species · Persephone</title><script data-outdated-warner src="../assets/warner.js"></script><link href="https://cdnjs.cloudflare.com/ajax/libs/lato-font/3.0.0/css/lato-font.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/juliamono/0.045/juliamono.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/fontawesome.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/solid.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/brands.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.13.24/katex.min.css" rel="stylesheet" type="text/css"/><script>documenterBaseURL=".."</script><script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js" data-main="../assets/documenter.js"></script><script src="../siteinfo.js"></script><script src="../../versions.js"></script><link class="docs-theme-link" rel="stylesheet" type="text/css" href="../assets/themes/documenter-dark.css" data-theme-name="documenter-dark" data-theme-primary-dark/><link class="docs-theme-link" rel="stylesheet" type="text/css" href="../assets/themes/documenter-light.css" data-theme-name="documenter-light" data-theme-primary/><script src="../assets/themeswap.js"></script></head><body><div id="documenter"><nav class="docs-sidebar"><a class="docs-logo" href="../index.html"><img src="../assets/logo.png" alt="Persephone logo"/></a><div class="docs-package-name"><span class="docs-autofit"><a href="../index.html">Persephone</a></span></div><form class="docs-search" action="../search/index.html"><input class="docs-search-query" id="documenter-search-query" name="q" type="text" placeholder="Search docs"/></form><ul class="docs-menu"><li><a class="tocitem" href="../index.html">Introduction</a></li><li><span class="tocitem">Developing</span><ul><li><a class="tocitem" href="../developing/index.html">Developing Persephone</a></li><li><a class="tocitem" href="../architecture/index.html">Source code architecture</a></li><li class="is-active"><a class="tocitem" href>Defining new species</a><ul class="internal"><li><a class="tocitem" href="#The-Persephone-species-DSL"><span>The Persephone species DSL</span></a></li><li><a class="tocitem" href="#Implementation-details"><span>Implementation details</span></a></li></ul></li></ul></li><li><span class="tocitem">Core</span><ul><li><a class="tocitem" href="../simulation/index.html">Simulation</a></li><li><a class="tocitem" href="../io/index.html">Input, Output, and Settings</a></li></ul></li><li><span class="tocitem">Nature</span><ul><li><a class="tocitem" href="../nature/index.html">Nature</a></li><li><a class="tocitem" href="../species/index.html">Species</a></li></ul></li><li><a class="tocitem" href="../crops/index.html">Crop submodel</a></li><li><a class="tocitem" href="../farm/index.html">Farm submodel</a></li></ul><div class="docs-version-selector field has-addons"><div class="control"><span class="docs-label button is-static is-size-7">Version</span></div><div class="docs-selector control is-expanded"><div class="select is-fullwidth is-size-7"><select id="documenter-version-selector"></select></div></div></div></nav><div class="docs-main"><header class="docs-navbar"><nav class="breadcrumb"><ul class="is-hidden-mobile"><li><a class="is-disabled">Developing</a></li><li class="is-active"><a href>Defining new species</a></li></ul><ul class="is-hidden-tablet"><li class="is-active"><a href>Defining new species</a></li></ul></nav><div class="docs-right"><a class="docs-edit-link" href="https://git.idiv.de/xo30xoqa/persephone/blob/master/docs/src/species-dsl.md#" title="Edit source"><span class="docs-icon fa"></span><span class="docs-label is-hidden-touch">Edit source</span></a><a class="docs-settings-button fas fa-cog" id="documenter-settings-button" href="#" title="Settings"></a><a class="docs-sidebar-button fa fa-bars is-hidden-desktop" id="documenter-sidebar-button" href="#"></a></div></header><article class="content" id="documenter-page"><h1 id="Defining-new-species"><a class="docs-heading-anchor" href="#Defining-new-species">Defining new species</a><a id="Defining-new-species-1"></a><a class="docs-heading-anchor-permalink" href="#Defining-new-species" title="Permalink"></a></h1><p><em>TODO</em></p><h2 id="The-Persephone-species-DSL"><a class="docs-heading-anchor" href="#The-Persephone-species-DSL">The Persephone species DSL</a><a id="The-Persephone-species-DSL-1"></a><a class="docs-heading-anchor-permalink" href="#The-Persephone-species-DSL" title="Permalink"></a></h2><h2 id="Implementation-details"><a class="docs-heading-anchor" href="#Implementation-details">Implementation details</a><a id="Implementation-details-1"></a><a class="docs-heading-anchor-permalink" href="#Implementation-details" title="Permalink"></a></h2></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../architecture/index.html">« Source code architecture</a><a class="docs-footer-nextpage" href="../simulation/index.html">Simulation »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 0.27.23 on <span class="colophon-date" title="Friday 20 January 2023 11:33">Friday 20 January 2023</span>. Using Julia version 1.9.0-alpha1.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>Species · Persephone</title><script data-outdated-warner src="assets/warner.js"></script><link href="https://cdnjs.cloudflare.com/ajax/libs/lato-font/3.0.0/css/lato-font.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/juliamono/0.045/juliamono.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/fontawesome.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/solid.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/brands.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.13.24/katex.min.css" rel="stylesheet" type="text/css"/><script>documenterBaseURL="."</script><script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js" data-main="assets/documenter.js"></script><script src="siteinfo.js"></script><script src="../versions.js"></script><link class="docs-theme-link" rel="stylesheet" type="text/css" href="assets/themes/documenter-dark.css" data-theme-name="documenter-dark" data-theme-primary-dark/><link class="docs-theme-link" rel="stylesheet" type="text/css" href="assets/themes/documenter-light.css" data-theme-name="documenter-light" data-theme-primary/><script src="assets/themeswap.js"></script></head><body><div id="documenter"><nav class="docs-sidebar"><a class="docs-logo" href="index.html"><img src="assets/logo.png" alt="Persephone logo"/></a><div class="docs-package-name"><span class="docs-autofit"><a href="index.html">Persephone</a></span></div><form class="docs-search" action="search.html"><input class="docs-search-query" id="documenter-search-query" name="q" type="text" placeholder="Search docs"/></form><ul class="docs-menu"><li><a class="tocitem" href="index.html">Introduction</a></li><li><a class="tocitem" href="odd.html">Overview, Design, Details (ODD)</a></li><li><span class="tocitem">Developing</span><ul><li><a class="tocitem" href="developing.html">Developing Persephone</a></li><li><a class="tocitem" href="architecture.html">Source code architecture</a></li><li><a class="tocitem" href="gis.html">GIS data</a></li><li><a class="tocitem" href="species-dsl.html">Defining new species</a></li></ul></li><li><span class="tocitem">Core</span><ul><li><a class="tocitem" href="simulation.html">Simulation</a></li><li><a class="tocitem" href="io.html">Input, Output, and Settings</a></li></ul></li><li><span class="tocitem">Nature</span><ul><li><a class="tocitem" href="nature.html">Nature</a></li><li class="is-active"><a class="tocitem" href="species.html">Species</a><ul class="internal"><li><a class="tocitem" href="#Skylark"><span>Skylark</span></a></li></ul></li></ul></li><li><a class="tocitem" href="crops.html">Crop submodel</a></li><li><a class="tocitem" href="farm.html">Farm submodel</a></li></ul><div class="docs-version-selector field has-addons"><div class="control"><span class="docs-label button is-static is-size-7">Version</span></div><div class="docs-selector control is-expanded"><div class="select is-fullwidth is-size-7"><select id="documenter-version-selector"></select></div></div></div></nav><div class="docs-main"><header class="docs-navbar"><nav class="breadcrumb"><ul class="is-hidden-mobile"><li><a class="is-disabled">Nature</a></li><li class="is-active"><a href="species.html">Species</a></li></ul><ul class="is-hidden-tablet"><li class="is-active"><a href="species.html">Species</a></li></ul></nav><div class="docs-right"><a class="docs-edit-link" href="https://git.idiv.de/xo30xoqa/persephone/-/blob/master//docs/src/species.md#" title="Edit source"><span class="docs-icon fa"></span><span class="docs-label is-hidden-touch">Edit source</span></a><a class="docs-settings-button fas fa-cog" id="documenter-settings-button" href="#" title="Settings"></a><a class="docs-sidebar-button fa fa-bars is-hidden-desktop" id="documenter-sidebar-button" href="#"></a></div></header><article class="content" id="documenter-page"><h1 id="Species"><a class="docs-heading-anchor" href="#Species">Species</a><a id="Species-1"></a><a class="docs-heading-anchor-permalink" href="#Species" title="Permalink"></a></h1><p>The ecological submodel in Persephone simulates a range of species in agricultural landscapes.</p><h2 id="Skylark"><a class="docs-heading-anchor" href="#Skylark">Skylark</a><a id="Skylark-1"></a><a class="docs-heading-anchor-permalink" href="#Skylark" title="Permalink"></a></h2></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="nature.html">« Nature</a><a class="docs-footer-nextpage" href="crops.html">Crop submodel »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 0.27.23 on <span class="colophon-date" title="Friday 3 February 2023 15:43">Friday 3 February 2023</span>. Using Julia version 1.9.0-alpha1.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
......@@ -5,15 +5,17 @@ push!(LOAD_PATH, "../src/")
using Documenter, Persephone
#TODO add ODD
#FIXME links to source code don't work
makedocs(sitename="Persephone",
modules = [Persephone],
repo = "https://git.idiv.de/xo30xoqa/persephone/blob/{commit}{path}#{line}",
repo = "https://git.idiv.de/xo30xoqa/persephone/-/blob/master/{path}#{line}",
format = Documenter.HTML(prettyurls = false),
pages = ["index.md",
"odd.md",
"Developing" => [
"developing.md",
"architecture.md",
"gis.md",
"species-dsl.md"],
"Core" => [
"simulation.md",
......
......@@ -9,15 +9,15 @@ Persephone is divided into four components, three of which are semi-independent
provides data output functionality.
2. `nature`: This is an individual-based model of species in agricultural landscapes.
It defines the `Animal` agent type, and a set of macros that can be used to rapidly
It defines the [`Animal`](@ref) agent type, and a set of macros that can be used to rapidly
create new species. It also includes ecological process functions that are useful
for all species.
3. `farm`: This is an agent-based model of farmer decision making. It is not yet implemented,
but will provide the `Farmer` agent type.
but will provide the [`Farmer`](@ref) agent type.
4. `crop`: This is a mathematical growth model for various crops. It is not yet implemented,
but already provides the agent type `FarmPlot`, representing one field and its associated
but already provides the agent type [`FarmPlot`](@ref), representing one field and its associated
extent and crop type.
Conceptually, `core` provides functionality that is needed by all of the submodels.
......@@ -33,10 +33,10 @@ the `Animal`s in the model landscape.
a strict "no global state" policy to avoid state-dependent bugs and allow parallelisation.)
The model object gives access to all agent instances (via `model[id]`, where `id` is the
unique identifier of this agent). It also stores the configuration (`model.settings`),
the landscape (`model.landscape`, a matrix of `Pixel` objects that store the local land
cover, amongst other things), and the current simulation date (`model.date`).
the landscape (`model.landscape`, a matrix of [`Pixel`](@ref) objects that store the local
land cover, amongst other things), and the current simulation date (`model.date`).
2. **Model configuration/the `param()` macro:** The model is configured via a
2. **Model configuration/the [`@param`](@ref) macro:** The model is configured via a
[TOML](https://toml.io/en/) file, the default version of which is at `src/parameters.toml`.
An individual run can be configured using a user-defined configuration file, commandline
arguments, or function calls (when Persephone is used as a package rather than an application).
......@@ -48,12 +48,21 @@ the `Animal`s in the model landscape.
3. **Output data:** Persephone can output model data into text files with a specified
frequency (daily, monthly, yearly, or at the simulation end). Submodels can use
`newdataoutput!()` to plug into this system. For an example of how to use this, see
`src/nature/ecologicaldata.jl`. (See `src/core/output.jl` for details.)
[`newdataoutput!`](@ref) to plug into this system. For an example of how to use this,
see `src/nature/ecologicaldata.jl`. (See `src/core/output.jl` for details.)
4. **Farm events:** The `FarmEvent` struct is used to communicate farming-related events
between submodels. An event can be triggered with `createevent!()` and affects all
pixels within a `FarmPlot`. (See `src/core/landscape.jl` for details.)
4. **Farm events:** The [`FarmEvent`](@ref) struct is used to communicate farming-related
events between submodels. An event can be triggered with `createevent!()` and affects
all pixels within a `FarmPlot`. (See `src/core/landscape.jl` for details.)
5. **Working with agents:** For more information about working with agent objects, see the
5. **Random numbers and logging:** By default in Julia, the random number generator (RNG)
and the system logger are two globally accessible variables. As Persephone needs to avoid
all global data (as this would interfere with parallel runs), the `model` object stores
a local logger and a local RNG. *Whenever you need to use a random number, you must
use the `model.rng`! The easiest way to do this is with the [`@rand`](@ref) and
[`@shuffle!`](@ref) macros.* The local logger generally does not change the way the model
uses [log statements](https://docs.julialang.org/en/v1/stdlib/Logging/), this is only
important in some functions in `src/core/simulation.jl`.
6. **Working with agents:** For more information about working with agent objects, see the
[Agents.jl API](https://juliadynamics.github.io/Agents.jl/stable/api/).
# GIS data in Persephone
# GIS data
Persephone currently requires two separate map input files: one for land cover,
the other for field geometry. This documents describe how to obtain and process
......
......@@ -38,6 +38,40 @@ optional arguments:
## Model input
*TODO: describe config & map files*
Persephone requires three input files: a configuration file and two map files. How to generate
the map files is documented [elsewhere](gis.html). The [configuration file](io.html)
defines parameter values and looks like this (see `src/parameters.toml` for a complete list
of parameters):
*Last updated: 2023-02-02 (commit 6bcd56b)*
```TOML
### Persephone - a socio-economic-ecological model of European agricultural landscapes.
###
### This is the default configuration file for Persephone, containing all model parameters.
### The syntax is described here: https://toml.io/en/
[core]
configfile = "src/parameters.toml" # location of the configuration file
landcovermap = "data/landcover_jena.tif" # location of the landcover map
farmfieldsmap = "data/fields_jena.tif" # location of the field geometry map
outdir = "results" # location and name of the output folder
overwrite = "ask" # overwrite the output directory? (true/false/"ask")
loglevel = "debug" # verbosity level: "debug", "info", "warn"
processors = 2 # number of processors to use on parallel runs
seed = 2 # seed value for the RNG (0 -> random value)
# dates to start and end the simulation
startdate = 2022-01-01
enddate = 2022-12-31
[farm]
farmmodel = "FieldManager" # which version of the farm model to use (not yet implemented)
[nature]
targetspecies = ["Wolpertinger", "Wyvern"] # list of target species to simulate
popoutfreq = "daily" # output frequency population-level data, daily/monthly/yearly/end/never
indoutfreq = "end" # output frequency individual-level data, daily/monthly/yearly/end/never
[crop]
cropmodel = "linear" # crop growth model to use, "linear" or "aquacrop" (not yet implemented)
```
*Last updated: 2023-02-03 (commit 092c769)*
......@@ -7,7 +7,7 @@ any output.
## parameters.toml
This is the default configuration file for Persephone, containing all model parameters.
The syntax is described here: https://toml.io/en/
The syntax is described here: [https://toml.io/en/](https://toml.io/en/)
DO NOT MODIFY THIS FILE FOR SIMULATION EXPERIMENTS! Instead, copy it to another directory,
modify the copy, and then pass it to the model using the `--config` parameter.
......
# Overview, Design, Details (ODD)
*TODO*
......@@ -3,9 +3,10 @@
## The Persephone species DSL
In order to make implementing new species as easy as possible, Persephone includes
a domain-specific language (DSL) built from a collection of macros and functions.
a [domain-specific language (DSL)](https://doi.org/10.1016/j.ecoinf.2015.02.005)
built from a collection of macros and functions.
Here is an example (using a hypothetical mermaid species) of what this looks like:
Here is an example of what this looks like, using a hypothetical mermaid species:
```julia
@species Mermaid begin
......@@ -32,21 +33,22 @@ Here is an example (using a hypothetical mermaid species) of what this looks lik
end
```
The two most important macros are `@species` and `@phase`, followed `@initialise`,
`@trait`, `@respond`, and `@habitat`. Other macros provide convenience wrappers
for common functions. (See `src/nature/nature.jl` for details.)
The two most important macros are [`@species`](@ref) and [`@phase`](@ref),
followed by [`@initialise`](@ref), [`@trait`](@ref), [`@respond`](@ref),
and [`@habitat`](@ref). Other macros provide convenience wrappers for common
functions. (See `src/nature/nature.jl` for details.)
The top-level macro is `@species`. This takes two arguments: a species name and
a definition block (enclosed in `begin` and `end` tags). At the start of the
The top-level macro is [`@species`](@ref). This takes two arguments: a species
name and a definition block (enclosed in `begin` and `end` tags). At the start of the
definition block, species-specific variables can be defined that should be available
throughout a species' lifetime. Code in this section has access to the `model`
object and can thus reference the current model state. In this section, the user
also has to call the `@initialise` macro. This wraps the `initpopulation()`
function, and takes a habitat descriptor (see `@habitat` below) and several options
to specify how the species' population should be distributed in the landscape
also has to call the [`@initialise`](@ref) macro. This wraps the [`initpopulation`](@ref)
function, and takes a habitat descriptor (see [`@habitat`](@ref) below) and several
options to specify how the species' population should be distributed in the landscape
during model initialisation.
Following this section, each species must define one or more `@phase` blocks.
Following this section, each species must define one or more [`@phase`](@ref) blocks.
The concept behind this is that species show different behaviours at different
phases of their lifecycle. Each `@phase` block defines the behaviour in one of
these phases. (Technically, it defines a function that will be called daily, so
......@@ -54,19 +56,19 @@ long as the species' `phase` variable is set to the name of this phase.) Code
in this section has access to the `model` object as well as an `animal` object,
which is the currently active animal agent. Properties of the `animal` agent,
regardless of whether they were defined by the user or by Persephone, can be
accessed using the `@trait` macro. Within a phase block, `@respond` can be used
to define the species' response to a `FarmEvent` that affects the species'
current location, while a variety of other macros provide wrappers to ecological
process functions from `src/nature/populations.jl`.
accessed using the [`@trait`](@ref) macro. Within a phase block, [`@respond`](@ref)
can be used to define the species' response to a [`FarmEvent`](@ref) that affects
the species' current location, while a variety of other macros provide wrappers to
ecological process functions from `src/nature/populations.jl`.
Another important macro is `@habitat`. This defines a "habitat descriptor",
Another important macro is [`@habitat`](@ref). This defines a "habitat descriptor",
i.e. a predicate function that tests whether or not a given landscape pixel is
suitable for a specified purpose. Such habitat descriptors are used as arguments
to various functions, for example for population initialisation or movement.
The argument to `@habitat` consists of a logical expression, which has access
to the animal's current position (the `pos` tuple variable) and the `model`.
Various macros are available to easily reference information about the current
location, such as `@landcover` or `@distancetoedge`.
location, such as [`@landcover`](@ref) or [`@distancetoedge`](@ref).
## Implementation details
......@@ -74,31 +76,31 @@ Due to a known [performance problem](https://juliadynamics.github.io/Agents.jl/s
with multi-agent models, the underlying implementation of species is
rather complicated (see `src/nature/nature.jl` for details.)
Rather than creating a new type/struct for each species, all animal agents
have the same type. Instead, they are differentiated by a `traits` dict,
which stores both species-specific parameters and run-time variables.
Rather than creating a new type/struct for each species, all [Animal](@ref)
agents have the same type. Instead, they are differentiated by a `traits`
dict, which stores both species-specific parameters and run-time variables.
Note that due to a redefinition of the `getproperty()/setproperty!()`
methods, variables from the trait dict can be accessed and modified just
like normal struct fields (i.e. although `phase` is defined in the dict,
not the struct, `animal.phase = "newphase"` works just fine - one does
not have to use `animal.traits["phase"] = "newphase"`.)
Under the hood, the `@species` macro generates a function (with the name
of the species), which in turn creates the trait dict when called. Thus,
adding a new animal agent to the model involves instantiating an `Animal`
Under the hood, the [`@species`](@ref) macro generates a function (with the
name of the species), which in turn creates the trait dict when called. Thus,
adding a new animal agent to the model involves instantiating an [`Animal`](@ref)
object, then calling the relevant species function and attaching the returned
dict to the agent object.
Similarly, the `@phase` macro too works by defining a new function, which
Similarly, the [`@phase`](@ref) macro too works by defining a new function, which
is stored in the species' trait dict. These functions take an animal object
and the model object as input, and define what the species does during its
daily update.
Once again, `@habitat` creates a function that takes `model` and `pos`
Once again, [`@habitat`](@ref) creates a function that takes `model` and `pos`
as input and returns a boolean response. Functions that require a habitat
descriptor thus take in this (anonymous) function and call it internally.
Finally, the `@initialise` macro is a wrapper around `initpopulation()`,
Finally, the [`@initialise`](@ref) macro is a wrapper around [`initpopulation`](@ref),
which (yet again) creates a function that specifies how a species' population
is to be initialised at the beginning of a simulation run. This function is
stored in the species trait dict and accessed during model setup.
......@@ -73,7 +73,7 @@ end
preprocessparameters(settings)
Take the raw input parameters and process them (convert types, perform checks, etc.).
This is a helper function for `getsettings()`.
This is a helper function for [`getsettings`](@ref).
"""
function preprocessparameters(settings::Dict{String,Any}, defaultoutdir::String)
(settings["core.seed"] == 0) && (settings["core.seed"] = abs(rand(RandomDevice(), Int32)))
......@@ -100,7 +100,7 @@ end
An internal utility function to convert the two-dimensional dict returned
by `TOML.parsefile()` into a one-dimensional dict, so that instead of
writing `settings["domain"]["param"]` one can use `settings["domain.param"]`.
Can be reversed with `prepareTOML()`.
Can be reversed with [`prepareTOML`](@ref).
"""
function flattenTOML(tomldict)
flatdict = Dict{String, Any}()
......
......@@ -34,7 +34,7 @@ end
Create a logger object that writes output both to screen and to a logfile.
This object is stored as `model.logger` and can then be used with `with_logger()`.
Note: requires `createdatadir()` to be run first.
Note: requires [`createdatadir`](@ref) to be run first.
"""
function modellogger(loglevel::String, outdir::String)
!isdir(outdir) && #TODO replace with exception
......@@ -52,9 +52,9 @@ end
"""
withtestlogger(model)
Replace the model logger with the currently active logger. This is intended to be
used in the testsuite to circumvent a Julia issue, where @test_logs doesn't work
with local loggers (https://github.com/JuliaLang/julia/issues/48456).
Replace the model logger with the currently active logger. This is intended to be used
in the testsuite to circumvent a [Julia issue](https://github.com/JuliaLang/julia/issues/48456),
where `@test_logs` doesn't work with local loggers.
"""
function withtestlogger(model::AgentBasedModel)
# copied together from https://github.com/JuliaLang/julia/blob/master/base/logging.jl
......@@ -101,7 +101,7 @@ end
prepareTOML(dict)
An internal utility function to re-convert the one-dimensional dict created
by `flattenTOML()` into the two-dimensional dict needed by `TOML.print()`,
by [`flattenTOML`](@ref) into the two-dimensional dict needed by `TOML.print`,
and convert any data types into TOML-compatible types where necessary.
"""
function prepareTOML(settings)
......@@ -124,7 +124,7 @@ end
A struct for organising model output. This is designed for text-based data output
that is updated more or less regularly (e.g. population data in csv files).
Submodels can register their own output functions using `newdataoutput()`.
Submodels can register their own output functions using [`newdataoutput!`](@ref).
Struct fields:
- filename: the name of the file to be created in the user-specified output directory
......@@ -140,7 +140,7 @@ struct DataOutput
end
"""
newdataoutput(model, filename, header, outputfunction, frequency)
newdataoutput!(model, filename, header, outputfunction, frequency)
Create and register a new data output. This function must be called by all submodels
that want to have their output functions called regularly.
......
......@@ -3,6 +3,11 @@
### This file is responsible for managing the farm module(s).
###
"""
Farmer
This is the agent type for the farm ABM. (Not yet implemented.)
"""
@agent Farmer GridAgent{2} begin
#TODO
end
......
......@@ -65,7 +65,7 @@ Update an animal by one day, executing it's currently active phase function.
"""
function stepagent!(animal::Animal, model::AgentBasedModel)
animal.age += 1
animal.traits[animal.phase](animal,model)
animal.phase(animal,model)
end
"""
......@@ -112,11 +112,11 @@ end
```
The definition body (enclosed in the begin/end block) has two sections.
First comes a call to `@initialise!()`, and optionally a list of
First comes a call to [`@initialise`](@ref), and optionally a list of
species-specific parameters, which are assigned just like normal variables.
Second come one or more phase definitions, that describe the behaviour
of the species during various parts of its life cycle. (See the documentation
to `@initialise` and `@phase` for details).
to [`@initialise`](@ref) and [`@phase`](@ref) for details).
Code in a species definition block can access the rest of the model using
the `model` variable (an object of type `AgentBasedModel`).
......@@ -147,8 +147,8 @@ end
"""
@initialise(habitatdescriptor; kwargs...)
Call this macro within the body of `@species`. It passes the given habitat descriptor
function and keyword arguments on to `initpopulation()` when setting up the simulation.
Call this macro within the body of [`@species`](@ref). It passes the given habitat descriptor
function and keyword arguments on to [`initpopulation`](@ref) when setting up the simulation.
Note: if this macro is not used, the variable `initialise!` must be set manually in the
species definition.
......@@ -161,7 +161,7 @@ end
@phase(name, body)
This macro is designed to be used within a species definition block (i.e. within
the body of a call to `@species`).
the body of a call to [`@species`](@ref)).
The idea behind this is that species show very different behaviour during different
phases of their lives. Therefore, `@phase` can be used define the behaviour for one
......@@ -180,8 +180,9 @@ variables:
information).
Several utility macros can be used within the body of `@phase` as a short-hand for
common expressions: `@trait`, `@setphase`, `@respond`, `@kill`, `@reproduce`,
`@neighbours`, `@rand`.
common expressions: [`@trait`](@ref), [`@setphase`](@ref), [`@respond`](@ref),
[`@kill`](@ref), [`@reproduce`](@ref), [`@neighbours`](@ref), [`@rand`](@ref),
[`@shuffle!`](@ref).
Note that the first phase that is defined in a species definition block will be
the phase that animals are assigned at birth, unless the variable `phase` is
......@@ -202,7 +203,7 @@ end
@trait(traitname)
A utility macro to quickly access an animal's trait value.
This can only be used nested within `@phase`.
This can only be used nested within [`@phase`](@ref).
"""
macro trait(traitname)
#XXX This would error if called in the first part of a species definition block
......@@ -215,7 +216,7 @@ end
"""
@setphase(newphase)
Switch this animal over to a different phase. This can only be used nested within `@phase`.
Switch this animal over to a different phase. This can only be used nested within [`@phase`](@ref).
"""
macro setphase(newphase)
#XXX make this usable in the top part of a species definition?
......@@ -226,7 +227,7 @@ end
@respond(eventname, body)
Define how an animal responds to a landscape event that affects its current position.
This can only be used nested within `@phase`.
This can only be used nested within [`@phase`](@ref).
"""
macro respond(eventname, body)
quote
......@@ -240,7 +241,8 @@ end
@kill
Kill this animal (and immediately abort its current update). This is a thin wrapper
around `kill!()`, and passes on any arguments. This can only be used nested within `@phase`.
around [`kill!`](@ref), and passes on any arguments. This can only be used nested within
[`@phase`](@ref).
"""
macro kill(args...)
quote
......@@ -252,8 +254,8 @@ end
"""
@reproduce
Let this animal reproduce. This is a thin wrapper around `reproduce!()`, and passes on
any arguments. This can only be used nested within `@phase`.
Let this animal reproduce. This is a thin wrapper around [`reproduce!`](@ref), and passes on
any arguments. This can only be used nested within [`@phase`](@ref).
"""
macro reproduce(args...)
:(reproduce!($(esc(:animal)), $(esc(:model)), $(map(esc, args)...)))
......@@ -263,7 +265,7 @@ end
@neighbours(radius)
Return an iterator over all animals in the given radius around this animal, excluding itself.
This can only be used nested within `@phase`.
This can only be used nested within [`@phase`](@ref).
"""
macro neighbours(radius)
#TODO enable filtering by species
......@@ -280,9 +282,9 @@ and a position, and returns `true` or `false` depending on the conditions
specified in the macro body.
Several utility macros can be used within the body of `@habitat` as a short-hand for
common expressions: `@landcover`, `@croptype`, `@cropheight`, `@distanceto`,
`@distancetoedge`, `@countanimals`. The variables `model` and `pos` can be used
for checks that don't have a macro available.
common expressions: [`@landcover`](@ref), [`@croptype`](@ref), [`@cropheight`](@ref),
[`@distanceto`](@ref), [`@distancetoedge`](@ref), [`@countanimals`](@ref).
The variables `model` and `pos` can be used for checks that don't have a macro available.
Two example uses of `@habitat` might look like this:
......@@ -319,7 +321,7 @@ end
@landcover
Returns the local landcover. This is a utility wrapper that can only be used
nested within `@phase` or `@habitat`.
nested within [`@phase`](@ref) or [`@habitat`](@ref).
"""
macro landcover()
:(landcover($(esc(:pos)), $(esc(:model))))
......@@ -329,7 +331,8 @@ end
@croptype
Return the local croptype, or nothing if there is no crop here.
This is a utility wrapper that can only be used nested within `@phase` or `@habitat`.
This is a utility wrapper that can only be used nested within [`@phase`](@ref)
or [`@habitat`](@ref).
"""
macro croptype()
:(croptype($(esc(:pos)), $(esc(:model))))
......@@ -339,7 +342,8 @@ end
@cropheight
Return the height of the crop at this position, or 0 if there is no crop here.
This is a utility wrapper that can only be used nested within `@phase` or `@habitat`.
This is a utility wrapper that can only be used nested within [`@phase`](@ref)
or [`@habitat`](@ref).
"""
macro cropheight()
:(cropheight($(esc(:pos)), $(esc(:model))))
......@@ -349,7 +353,8 @@ end
@distanceto(habitat)
Calculate the distance to the closest habitat of the specified type or descriptor.
This is a utility wrapper that can only be used nested within `@phase` or `@habitat`.
This is a utility wrapper that can only be used nested within [`@phase`](@ref)
or [`@habitat`](@ref).
"""
macro distanceto(habitat)
:(distanceto($(esc(:pos)), $(esc(:model)), $(esc(habitat))))
......@@ -359,7 +364,8 @@ end
@distancetoedge
Calculate the distance to the closest neighbouring habitat.
This is a utility wrapper that can only be used nested within `@phase` or `@habitat`.
This is a utility wrapper that can only be used nested within [`@phase`](@ref)
or [`@habitat`](@ref).
"""
macro distancetoedge()
:(distancetoedge($(esc(:pos)), $(esc(:model))))
......@@ -369,7 +375,8 @@ end
@countanimals(species="", radius=0)
Count the number of animals of the given species in this location.
This is a utility wrapper that can only be used nested within `@phase` or `@habitat`.
This is a utility wrapper that can only be used nested within [`@phase`](@ref)
or [`@habitat`](@ref).
"""
macro countanimals(args...)
:(countanimals($(esc(:pos)), $(esc(:model)); $(map(esc, args)...)))
......
......@@ -11,7 +11,7 @@ Creates a function that initialises individuals at random locations across the l
This can be used to create the `initialise!` variable in a species definition block.
- `habitatdescriptor` is a function that determines whether a given location is suitable
or not (create this using `@habitat`).
or not (create this using [`@habitat`](@ref)).
- `phase` determines which life phase individuals will be assigned to. If this is `nothing`,
the species' default post-natal life stage will be used (although note that this is
......@@ -21,7 +21,7 @@ This can be used to create the `initialise!` variable in a species definition bl
negative, one individual will be created in every suitable location in the landscape.
If `popsize` is greater than the number of suitable locations, multiple individuals
will be created in one place. (Maximum population density can be set in the habitat
descriptor using the `@countanimals` macro.)
descriptor using the [`@countanimals`](@ref) macro.)
- If `pairs` is true, a male and a female individual will be created in each selected
location, otherwise, only one individual will be created at a time.
......@@ -70,7 +70,7 @@ end
"""
initrandompopulation(popsize; kwargs...)
A simplified version of `initpopulation()`. Creates a function that initialises
A simplified version of [`initpopulation`](@ref). Creates a function that initialises
`popsize` individuals, spread at random across the landscape.
"""
function initrandompopulation(popsize::Int64; kwargs...)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment