Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
simulation.jl 5.57 KiB
### Persefone - a socio-economic-ecological model of European agricultural landscapes.
###
### This file includes the core functions for initialising and running simulations.
###

#XXX How can I make the model output during a parallel run clearer?

"""
    simulate(config=PARAMFILE, seed=nothing)

Initialise one or more model objects and carry out a full simulation experiment,
optionally specifying a configuration file and a seed for the RNG.

This is the default way to run a Persefone simulation.
"""
function simulate(config::String=PARAMFILE, seed::Union{Int64,Nothing}=nothing)
    models = initialise(config, seed)
    isa(models, Vector) ? 
        map(simulate!, models) : #TODO parallelise
        simulate!(models)
end

"""
    simulate!(model)

Carry out a complete simulation run using a pre-initialised model object.
"""
function simulate!(model::AgentBasedModel)
    runtime = Dates.value(@param(core.enddate)-@param(core.startdate))+1
    step!(model, dummystep, stepsimulation!, runtime)
    finalise!(model)
end

"""
    initialise(config=PARAMFILE, seed=nothing)

Initialise the model: read in parameters, create the output data directory,
and instantiate the AgentBasedModel object(s). Optionally allows specifying the
configuration file and overriding the `seed` parameter. This returns a single
model object, unless the config file contains multiple values for one or more
parameters, in which case it creates a full-factorial simulation experiment
and returns a vector of model objects.
"""
function initialise(config::String=PARAMFILE, seed::Union{Int64,Nothing}=nothing)
    @info "Simulation run started at $(Dates.now())."
    settings = getsettings(config, seed)
    scanparams = settings["internal.scanparams"]
    delete!(settings, "internal.scanparams")
    isempty(scanparams) ?
        initmodel(settings) :
        map(initmodel, paramscan(settings, scanparams)) #TODO parallelise
end

"""
    initmodel(settings)

Initialise a model object using a ready-made settings dict. This is
a helper function for `initialise()`.
"""
function initmodel(settings::Dict{String, Any})
    @debug "Initialising model object."
    createdatadir(settings["core.outdir"], settings["core.overwrite"])
    logger = modellogger(settings["core.loglevel"], settings["core.outdir"])
    with_logger(logger) do
        events = Vector{FarmEvent}()
        dataoutputs = Vector{DataOutput}()
        landscape = initlandscape(settings["world.landcovermap"],
                                  settings["world.farmfieldsmap"])
        weather = initweather(settings["world.weatherfile"],
                              settings["core.startdate"],