diff --git a/docs/src/architecture.md b/docs/src/architecture.md index cd717e39a782e199d11fd477f808b11130d42c1f..822d572a8281e523ec6fc061d8c517238c0f5c4a 100644 --- a/docs/src/architecture.md +++ b/docs/src/architecture.md @@ -1,22 +1,59 @@ # Source code architecture -*TODO* - # Model components -1. core - -2. farm +Persephone is divided into four components, three of which are semi-independent submodels: -3. nature +1. `core`: This is the foundation of the model software, which sets up and executes + simulation runs. It also reads in the configuration file and landscape maps, and + provides data output functionality. -4. crop +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 + 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. -# Important implementation details +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 + extent and crop type. -1. configuration/`param()` +Conceptually, `core` provides functionality that is needed by all of the submodels. +Decisions made by `Farmer`s affect the `FarmPlot`s they own, and (directly or indirectly) +the `Animal`s in the model landscape. -2. output data +# Important implementation details -3. Agents.jl +1. **The `model` object:** A cursory reading of the source code will quickly show that + most functions take an `AgentBaseModel` object as one of their arguments. This is the + key data structure of [Agents.jl](https://juliadynamics.github.io/Agents.jl/stable/tutorial/#.-The-model-1), + and holds all state that is in any way relevant to a simulation run. (Persephone has + 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`). + +2. **Model configuration/the `param()` 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). + During a model run, the `@param(parameter)` macro can be used as a short-hand for + `model.settings["parameter"]`. Note that parameter names are prepended with the name + of the component they are associated with. For example, the `outdir` parameter belongs + to the `[core]` section of the TOML file, and must therefore be referenced as + `@param(core.outdir)`. (See `src/core/input.jl` for details.) + +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.) + +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.) + +5. **Working with agents:** For more information about working with agent objects, see the + [Agents.jl API](https://juliadynamics.github.io/Agents.jl/stable/api/). diff --git a/docs/src/developing.md b/docs/src/developing.md index 40f0ffdc172124559541d18041ed7a67aaecdfe9..4e42cf72c8776fcdf10b38c13355a10bba434d5d 100644 --- a/docs/src/developing.md +++ b/docs/src/developing.md @@ -10,7 +10,7 @@ 3. Implement your changes. -4. Run `run.sh` to make sure the model executes without crashing. Also run the test suite +4. Run `example.sh` to make sure the model executes without crashing. Also run the test suite (`cd test; julia runtests.jl`). 5. Commit your work frequently, and try to keep each commit small. Don't forget to add @@ -22,6 +22,9 @@ 8. Repeat :-) +The Gitlab issue tracker can be used to create, discuss, and assign tasks, as well as to monitor +progress towards milestones/releases. Once we have a first release, we will start using +[semantic versioning](https://semver.org/). ## Agents.jl diff --git a/docs/src/index.md b/docs/src/index.md index ec4bb9c2326c0e1834bb6059873f004d7ac8ca71..2c1f722ed4f9a1d056b0e6a89854dd5ecb400dea 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -40,4 +40,4 @@ optional arguments: *TODO: describe config & map files* -*Last updated: 2023-01-20 (commit 4954227)* +*Last updated: 2023-02-02 (commit 577ff86)* diff --git a/src/nature/nature.jl b/src/nature/nature.jl index 01cf3df255219157cda25f680328f35fdda141f7..a02f984c68f959c3040b337a4198de4aca0ee556 100644 --- a/src/nature/nature.jl +++ b/src/nature/nature.jl @@ -22,6 +22,7 @@ i.e. the trait `phase` can be accessed and modified with `animal.phase`.) # Doesn't that rather obviate the point of having an agent struct? # If I could move the mutable traits to the struct, I wouldn't need # to deepcopy the speciesdict. + #XXX add `phase` and `species` (rather than `name`) directly to the struct? traits::Dict{String,Any} sex::Sex age::Int @@ -115,7 +116,7 @@ First comes a call to `@initialise!()`, 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` and `@phase` for details). Code in a species definition block can access the rest of the model using the `model` variable (an object of type `AgentBasedModel`).