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

Added Makefile

This closes issue #50
parent b402c07f
No related branches found
No related tags found
No related merge requests found
Makefile 0 → 100644
SHELL = /bin/bash
.PHONY: run test docs release install
run:
# running example simulation
if [ -d "example_results" ]; then rm -r example_results; fi
./run.jl -o example_results
src/analysis/analyse_nature.R example_results
test:
# running test suite
cd test; julia runtests.jl
commit = $(shell git log --format="%cd (commit %h)" --date=short -1)
docs:
# building documentation
# include a date stamp with the latest commit
sed -i -e "s/\*Last updated:.*/\*Last updated: ${commit}\*/" docs/src/index.md
cd docs; julia builddocs.jl
release:
echo "Not yet implemented."
install:
echo: "Not relevant. Use `julia run.jl` to run Persephone."
......@@ -14,6 +14,8 @@ framework. It is currently in the very early stages of development.
## Usage
*For the full documentation, open `docs/documentation.html` in a browser.*
### Installation
Install the latest version of the [Julia](https://julialang.org/downloads/) programming
......@@ -24,10 +26,10 @@ To install package dependencies, open a Julia REPL in this folder and run
### Running from the commandline
This is the normal mode of operation. Simply execute `run.jl`, typically like so (in Linux):
This is the normal mode of operation. Simply execute `run.jl` in a terminal, typically like so:
```
> ./run.jl -c <config>
> julia run.jl -c <config>
```
where `<config>` specifies the configuration file to use. The recommended workflow is
......@@ -52,11 +54,15 @@ optional arguments:
-h, --help show this help message and exit
```
To run the test suite, do the following:
To run the test suite, switch to the `test` directory and execute `runtests.jl`.
If you are on Linux or MacOS, you can also use `make`:
```
> cd test
> julia runtests.jl
> make run # run a simulation with default values
> make test # run the test suite
> make docs # build the documentation
> make release # create a release
```
### Running from within Julia
......
......@@ -30,28 +30,34 @@ the `Animal`s in the model landscape.
!["the model object"](assets/model_object.png)
1. **The `model` object:** A cursory reading of the source code will quickly show that
most functions take an `AgentBasedModel` 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`](@ref) objects that store the local
land cover, amongst other things), and the current simulation date (`model.date`).
(See [`initmodel`](@ref) for details.)
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`](https://git.idiv.de/xo30xoqa/persephone/-/blob/master/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`](https://git.idiv.de/xo30xoqa/persephone/-/blob/master/src/core/input.jl)
for details.)
### The `model` object
A cursory reading of the source code will quickly show that most functions take an
`AgentBasedModel` 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`](@ref) objects that store the local
land cover, amongst other things), and the current simulation date (`model.date`).
(See [`initmodel`](@ref) for details.)
For more information about working with agent objects, see the
[Agents.jl API](https://juliadynamics.github.io/Agents.jl/stable/api/).
### 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`](https://git.idiv.de/xo30xoqa/persephone/-/blob/master/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`](@ref) macro can be used to access parameter values.
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`](https://git.idiv.de/xo30xoqa/persephone/-/blob/master/src/core/input.jl)
for details.)
!!! info "@param and other macros"
As `@param(parameter)` expands to `model.settings["parameter"]`, it can obviously
......@@ -60,28 +66,33 @@ the `Animal`s in the model landscape.
macros depend on specific variables being available where they are called, and can
therefore only be used in specific contexts (this is indicated in their documentation).
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!`](@ref) to plug into this system. For an example of how to use this,
see [`src/nature/ecologicaldata.jl`](https://git.idiv.de/xo30xoqa/persephone/-/blob/master/src/nature/ecologicaldata.jl).
(See [`src/core/output.jl`](https://git.idiv.de/xo30xoqa/persephone/-/blob/master/src/core/output.jl) for details.)
### Output data
4. **Farm events:** The [`FarmEvent`](@ref) struct is used to communicate farming-related
events between submodels. An event can be triggered with [`createevent!`](@ref) and affects
all pixels within a `FarmPlot`. (See [`src/core/landscape.jl`](https://git.idiv.de/xo30xoqa/persephone/-/blob/master/src/core/landscape.jl)
for details.)
Persephone can output model data into text files with a specified
frequency (daily, monthly, yearly, or at the simulation end). Submodels can use
[`newdataoutput!`](@ref) to plug into this system. For an example of how to use this, see
[`src/nature/ecologicaldata.jl`](https://git.idiv.de/xo30xoqa/persephone/-/blob/master/src/nature/ecologicaldata.jl).
(See [`src/core/output.jl`](https://git.idiv.de/xo30xoqa/persephone/-/blob/master/src/core/output.jl) for details.)
### Farm events
The [`FarmEvent`](@ref) struct is used to communicate farming-related events between
submodels. An event can be triggered with [`createevent!`](@ref) and affects all pixels
within a [`FarmPlot`](@ref). (See
[`src/core/landscape.jl`](https://git.idiv.de/xo30xoqa/persephone/-/blob/master/src/core/landscape.jl)
for details.)
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 reproducibility in parallel runs), the `model`
object stores a local logger and a local RNG. The local logger generally does not change the
way the model uses [log statements](https://docs.julialang.org/en/v1/stdlib/Logging/), it is
only relevant for some functions in [`src/core/simulation.jl`](https://git.idiv.de/xo30xoqa/persephone/-/blob/master/src/core/simulation.jl).
### Random numbers and logging
By default in Julia, the [random number generator](https://docs.julialang.org/en/v1/stdlib/Random/)
(RNG) and the [system logger](https://docs.julialang.org/en/v1/stdlib/Logging/#Logging.global_logger)
are two globally accessible variables. As Persephone needs to avoid all global data (since
this would interfere with reproducibility in parallel runs), the `model` object stores a
local logger and a local RNG. The local logger generally does not change the way the
model uses [log statements](https://docs.julialang.org/en/v1/stdlib/Logging/), it is
only relevant for some functions in [`src/core/simulation.jl`](https://git.idiv.de/xo30xoqa/persephone/-/blob/master/src/core/simulation.jl).
!!! info "Using the model RNG"
Whenever you need to use a [random number](https://docs.julialang.org/en/v1/stdlib/Random/#Base.rand),
you must use the `model.rng`. The easiest way to do this is with the [`@rand`](@ref)
and [`@shuffle!`](@ref) macros. (Note that these, too, require access to the `model` object.)
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/).
......@@ -2,16 +2,16 @@
## Workflow
1. Pull the current development version from the master branch on Gitlab:
1. Pull the current version from the master branch on Gitlab:
[https://git.idiv.de/xo30xoqa/persephone](https://git.idiv.de/xo30xoqa/persephone).
2. If you are working on a new feature, create a new branch to avoid breaking the `master` branch.
(The `master` branch should always be in a runnable and (as far as possible) error-free state.)
(The `master` branch on Github should always be in a runnable and error-free state.)
3. Implement your changes.
4. Run `example.sh` to make sure the model executes without crashing. Also run the test suite
(`cd test; julia runtests.jl`).
4. Run an example simulation and the test suite to make sure everything works without crashing
(`make run` and `make test` on Linux, or execute `run.jl` and `test/runtests.jl` manually.)
5. Commit your work frequently, and try to keep each commit small. Don't forget to add
relevant tests to the test suite.
......@@ -22,11 +22,13 @@
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/).
The Gitlab [issue tracker](https://git.idiv.de/xo30xoqa/persephone/-/boards/373) 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
## Libraries
### Agents.jl
Our model uses [Agents.jl](https://juliadynamics.github.io/Agents.jl/stable/) as a framework.
Their [repository](https://github.com/JuliaDynamics/Agents.jl) can be used to inspect the source
......@@ -36,6 +38,29 @@ code or submit bug reports (the authors are quick to respond). Questions can be
*Tutorial on collaborating on Julia packages:
[https://www.matecdev.com/posts/julia-package-collaboration.html](https://www.matecdev.com/posts/julia-package-collaboration.html).*
### Revise.jl
[`Revise.jl`](https://timholy.github.io/Revise.jl/stable/) allows one to reload code
without restarting the Julia interpreter. Get it with `Pkg.add("Revise")`, then
add `using Revise` to `.julia/config/startup.jl` to have it automatically available.
### Test
Persephone uses the inbuilt Julia [testing framework](https://docs.julialang.org/en/v1/stdlib/Test/).
All new functions should have appropriate tests written for them in the appropriate
file in the `test` directory. (See [`test/runtests.jl`](https://git.idiv.de/xo30xoqa/persephone/-/blob/master/test/runtests.jl)
for details.) There are three ways to run the test suite: in the terminal, executing
`make test` or `cd test; julia runtests.jl`; or in the Julia REPL,
`Pkg.activate("."); Pkg.test()`.
### Documenter.jl
The HTML documentation is generated using [Documenter.jl](https://documenter.juliadocs.org).
Therefore, all new functions should have docstrings attached. New files need to be integrated
into the relevant documentation source files in `docs/src`, and if necessary into
[`docs/builddocs.jl`](https://git.idiv.de/xo30xoqa/persephone/-/blob/master/docs/builddocs.jl).
To build the documentation, run `make docs`, or `cd docs; julia builddocs.jl`
(if using the latter, don't forget to update the date and commit in `docs/src/index.md`).
## Julia editors
......@@ -68,16 +93,3 @@ See [here](https://www.julia-vscode.org/).
*TODO: add more detail.*
### Other useful stuff
1. [`Revise.jl`](https://timholy.github.io/Revise.jl/stable/) allows one to reload code
without restarting the Julia interpreter. Get it with `Pkg.add("Revise")`, then
add `using Revise` to `.julia/config/startup.jl` to have it automatically available.
2. [`git-bug`](https://github.com/MichaelMure/git-bug) is a commandline bug tracker that
integrates directly with git. It can also be used as a local interface to Gitlab issues.
To install on Linux, download the [binary](https://github.com/MichaelMure/git-bug/releases/tag/v0.8.0),
copy it to `/usr/local/bin/git-bug`, and set it as executable with `chmod +x
/usr/local/bin/git-bug`. To set up Gitlab integration, run `git bug bridge configure`
from within the relevant repository.
......@@ -13,7 +13,7 @@ an ecological submodels.
## Running the model
To run a single experiment, execute:
To run a single experiment, execute `run.jl`:
```
julia run.jl -c <CONFIG>
......@@ -74,10 +74,10 @@ indoutfreq = "end" # output frequency individual-level data, daily/monthly/yearl
cropmodel = "linear" # crop growth model to use, "linear" or "aquacrop" (not yet implemented)
```
!!! tip "Parameter scanning"
!!! info "Parameter scanning"
You can set any parameter to a list of different values, e.g. `seed = [1,2,3]`.
Persephone will then set up and run multiple simulations, one for every possible
combination of parameters that you entered (i.e. do a full-factorial simulation
experiment).
*Last updated: 2023-02-07 (commit 600bbd3)*
*Last updated: 2023-02-07 (commit b402c07)*
......@@ -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.phase(animal,model)
animal.traits[animal.phase](animal,model) #FIXME
end
"""
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment