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

Implemented the functions needed for Agents.jl

This is a major commit, probably quite a bit too big...
However, all the pieces here depended on each other, so
I had to get it all working at the same time.

The model now includes:

	1. reading in map data
	2. creating an Agents.jl model object
	3. initialisation and stepping functions for the whole model
	4. a basic skeleton of nature.jl
	5. an example animal species (the Wolpertinger ;-) )
parent 86669024
Branches
Tags
No related merge requests found
...@@ -25,21 +25,23 @@ using ...@@ -25,21 +25,23 @@ using
## define exported functions and variables ## define exported functions and variables
export export
simulate, simulate,
initsim, initialise,
stepsim, stepsimulation!,
finalisesim finalise
## The file that stores all default parameters ## The file that stores all default parameters
const paramfile = "src/parameters.toml" const PARAMFILE = "src/parameters.toml"
## (DO NOT CHANGE THIS VALUE! Instead, specify simulation-specific configuration files ## (DO NOT CHANGE THIS VALUE! Instead, specify simulation-specific configuration files
## by using the "--configfile" commandline argument, or when invoking simulate().) ## by using the "--configfile" commandline argument, or when invoking simulate().)
## include all module files ## include all module files - note that the order matters
## (if file b references something from file a, it must be included later)
include("core/input.jl") include("core/input.jl")
include("core/output.jl") include("core/output.jl")
include("farm/farm.jl")
include("crop/crops.jl") include("crop/crops.jl")
include("nature/nature.jl") include("nature/nature.jl")
include("farm/farm.jl") include("nature/wolpertinger.jl")
include("core/simulation.jl") include("core/simulation.jl")
end end
...@@ -128,5 +128,7 @@ end ...@@ -128,5 +128,7 @@ end
Read in a TIFF map file and return it as an array. Read in a TIFF map file and return it as an array.
""" """
function readtiffmapfile(filename) function readtiffmapfile(filename)
tiff = GeoArrays.read(filename)
space = GridSpace(size(tiff)[1:2], periodic=false)
#TODO this requires GeoArrays #TODO this requires GeoArrays
end end
...@@ -3,29 +3,63 @@ ...@@ -3,29 +3,63 @@
### This file includes the core functions for initialising and running simulations. ### This file includes the core functions for initialising and running simulations.
### ###
function initsim(config::String) """
initialise(config)
Initialise the model: read in parameters, create the output data directory,
and instantiate the AgentBasedModel object.
"""
function initialise(config::String=PARAMFILE)
initsettings(config) initsettings(config)
Random.seed!(param("core.seed"))
setupdatadir() setupdatadir()
#TODO create world landcover = GeoArrays.read(param("core.mapfile"))
space = GridSpace(size(landcover)[1:2], periodic=false)
properties = Dict{Symbol,Any}(:day=>0,
:landcover=>landcover)
model = AgentBasedModel(Union{Farmer,Animal,CropPlot}, space, properties=properties,
rng=Random.Xoshiro(param("core.seed")))
initfarms!(model)
initfields!(model)
initnature!(model)
@info "Simulation initialised." @info "Simulation initialised."
model
end end
function stepsim()
@info "Simulating another day." """
stepsimulation!(model)
Execute one update of the model.
"""
function stepsimulation!(model::AgentBasedModel)
model.day += 1
@info "Simulating day $(model.day)."
for a in Schedulers.ByType((Farmer,Animal,CropPlot), true)(model)
stepagent!(getindex(model, a), model)
end
#TODO #TODO
end end
function finalisesim()
"""
finalise(model)
Wrap up the simulation. Output all remaining data and exit.
"""
function finalise(model::AgentBasedModel)
@info "Simulation ran. Nothing happened. But it will!" @info "Simulation ran. Nothing happened. But it will!"
#TODO #TODO
genocide!(model)
end end
function simulate(config::String=paramfile)
initsim(config) """
for day in 1:param("core.runtime") simulate(config)
stepsim()
end Carry out a complete simulation run.
finalisesim() """
#TODO function simulate(config::String=PARAMFILE)
model = initialise(config)
step!(model, dummystep, stepsimulation!, param("core.runtime"))
finalise(model)
end end
### Persephone - a socio-economic-ecological model of European agricultural landscapes.
###
### This file is responsible for managing the crop growth modules.
###
#XXX not sure whether it makes sense to have this as an agent type,
# or perhaps better a grid property?
@agent CropPlot GridAgent{2} begin
#TODO
end
"""
stepagent!(cropplot, model)
Update a crop plot by one day.
"""
function stepagent!(cropplot::CropPlot, model::AgentBasedModel)
#TODO
end
"""
initfields!(model)
Initialise the model with its crop plots.
"""
function initfields!(model::AgentBasedModel)
#TODO
end
### Persephone - a socio-economic-ecological model of European agricultural landscapes.
###
### This file is responsible for managing the farm module(s).
###
@agent Farmer GridAgent{2} begin
#TODO
end
"""
stepagent!(farmer, model)
Update a farmer by one day.
"""
function stepagent!(farmer::Farmer, model::AgentBasedModel)
#TODO
end
"""
initfarms!(model)
Initialise the model with a set of farm agents.
"""
function initfarms!(model::AgentBasedModel)
#TODO
end
### Persephone - a socio-economic-ecological model of European agricultural landscapes.
###
### This file is responsible for managing the animal modules.
###
@enum Sex hermaphrodite male female
"""
Species
Species are differentiated by their name, and the functions used to
initialise their population and update each individual.
"""
struct Species
name::String
initpop::Function # takes one argument: model
update::Function # takes two arguments: animal, model
end
"""
Animal
This is the generic agent type for all animals. Species are differentiated
by the `species` struct passed by them during initialisation.
"""
@agent Animal GridAgent{2} begin
species::Species
sex::Sex
age::Int32
energy::Int32
end
let specieslist = Dict{String, Species}()
"""
registerspecies(species)
This function has to be called by every species definition file
in order for the species to be used.
"""
global function registerspecies(s::Species)
specieslist[s.name] = s
end
"""
getspecies(name)
Returns the definition struct for the named species.
"""
global function getspecies(name::String)
specieslist[name]
end
end
"""
stepagent!(animal, model)
Update an animal by one day.
"""
function stepagent!(animal::Animal, model::AgentBasedModel)
animal.age += 1
animal.species.update(animal,model)
if animal.energy <= 0
kill_agent!(animal, model)
end
end
"""
initnature!(model)
Initialise the model with all simulated animal populations.
"""
function initnature!(model::AgentBasedModel)
for s in param("nature.targetspecies")
getspecies(s).initpop(model)
end
end
### Persephone - a socio-economic-ecological model of European agricultural landscapes.
###
### This file holds the code for the Wolpertinger (https://en.wikipedia.org/wiki/Wolpertinger).
### NOT FOR ACTUAL USE! This is of course only a test species ;-)
### Although I dare say the Wolpertinger is rather endangered...
###
"""
initwolpertinger!(model)
Initialise a population of Wolpertingers in random locations around the landscape.
"""
function initwolpertinger!(model::AgentBasedModel)
species = getspecies("Wolpertinger")
worldsize = size(model.landcover)[1:2]
popsize = round(worldsize[1]*worldsize[2]/1000)
for i in 1:popsize
add_agent!(Animal, model, species, hermaphrodite, 0, 100)
end
@debug "Hid $(popsize) Wolpertingers for gullible tourists to find."
end
"""
updatewolpertinger(animal, model)
Wolpertingers are rather stupid creatures, all they do is move around randomly
and occasionally reproduce by spontaneous parthogenesis...
"""
function updatewolpertinger!(w::Animal, model::AgentBasedModel)
#TODO
@debug "The Wolpertinger is a mysterious animal..." w.id
end
registerspecies(Species("Wolpertinger", initwolpertinger!, updatewolpertinger!))
...@@ -18,7 +18,7 @@ seed = 0 # seed value for the RNG (0 -> random value) ...@@ -18,7 +18,7 @@ seed = 0 # seed value for the RNG (0 -> random value)
[nature] [nature]
targetspecies = [] # list of target species to simulate targetspecies = ["Wolpertinger"] # list of target species to simulate
[crop] [crop]
cropmodel = "linear" # crop growth model to use, "linear" or "aquacrop" (not yet implemented) cropmodel = "linear" # crop growth model to use, "linear" or "aquacrop" (not yet implemented)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment