diff --git a/src/core/input.jl b/src/core/input.jl index cb1c9f9297011868862425f17e9ebcb9de3e982b..ada3f58551cef1441004b4874663cf3e0d243116 100644 --- a/src/core/input.jl +++ b/src/core/input.jl @@ -6,55 +6,32 @@ ## Note: much of this code was adapted from the GeMM model by Leidinger et al. ## (https://github.com/CCTB-Ecomods/gemm/blob/master/src/input.jl) -##XXX Does it make sense to move the settings dict into the model object itself? -## (It could be integrated into the properties dict.) Advantage: we have less -## global state lying around, and serialising becomes easier (if we want to do -## that). Also, during testing we often need to change individual parameters, -## which is currently impossible. Disadvantage: immutability of parameters at -## runtime is intended, and some start-up functions may have problems if they need -## access to parameters before the model object has been created. -##TODO -> yes, changing this is probably sensible -let settings::Dict{String, Dict{String, Any}} - """ - initsettings(configfile) - - Initialise the global model settings for this run. - """ - global function initsettings(configfile::String) - settings = getsettings(configfile) - end - - """ - param(domainparam) - - Return a configuration parameter from the global settings. - The argument should be in the form `"<domain>.<parameter>"`, - for example `param("core.outdir")`. Possible values for - <domain> are "core", "nature", "farm", or "crop". For a full - list of parameters, see `src/parameters.toml`. - """ - global function param(domainparam::String) - domain, paramname = split(domainparam, ".") - settings[domain][paramname] - end +""" + @param(domainparam) - """ - printparameters(io) +Return a configuration parameter from the global settings. +The argument should be in the form `<domain>.<parameter>`, +for example `@param(core.outdir)`. Possible values for +<domain> are `core`, `nature`, `farm`, or `crop`. For a full +list of parameters, see `src/parameters.toml`. - Print all settings in TOML format to the given output stream. - """ - global function printparameters(stream::IO=stdout) - TOML.print(stream, settings) - end +Note that this macro only works in a context where the `model` +object is available. +""" +macro param(domainparam) + domain = String(domainparam.args[1]) + paramname = String(domainparam.args[2].value) + #domain, paramname = split(domainparam, ".") + :($(esc(:model)).settings[$domain][$paramname]) end """ - getsettings(configfile) + getsettings(configfile, seed=nothing) Combines all configuration options to produce a single settings dict. Precedence: commandline parameters - user config file - default values """ -function getsettings(configfile::String) +function getsettings(configfile::String, seed::Union{Int64,Nothing)=nothing) # read in and merge configurations from the commandline, the default config file # and a user-supplied config file defaults = TOML.parsefile(configfile) @@ -75,7 +52,9 @@ function getsettings(configfile::String) end end # pre-process certain parameters - if settings["core"]["seed"] == 0 + if !isnothing(seed) + settings["core"]["seed"] = seed + elseif settings["core"]["seed"] == 0 settings["core"]["seed"] = abs(rand(RandomDevice(), Int32)) end defaultoutdir = defaults["core"]["outdir"] diff --git a/src/core/output.jl b/src/core/output.jl index db3ce30049822823c1f7499f3069293aa1711528..e34feb2694f24936593c6f1cd4a73bd1a1da62e9 100644 --- a/src/core/output.jl +++ b/src/core/output.jl @@ -51,7 +51,7 @@ function setupdatadir() println(f, "# This file was generated automatically.") println(f, "# Simulation run on $(string(Dates.format(Dates.now(), "d u Y HH:MM:SS"))),") println(f, "# with git commit $(read(`git rev-parse HEAD`, String))#\n") - printparameters(f) + TOML.print(f, settings) end # Copy the map files to the output folder lcmap = param("core.landcovermap") diff --git a/src/core/simulation.jl b/src/core/simulation.jl index e9b96631ede6d79cadac3742215eb5112d54ebe4..d36aefa191471c8037ad28436e745a5b5181f7a0 100644 --- a/src/core/simulation.jl +++ b/src/core/simulation.jl @@ -4,23 +4,25 @@ ### """ - initialise(config, seed) + initialise(config, seed=nothing) Initialise the model: read in parameters, create the output data directory, -and instantiate the AgentBasedModel object. +and instantiate the AgentBasedModel object. Optionally allows overriding the +`seed` parameter. """ -function initialise(config::String=PARAMFILE) +function initialise(config::String=PARAMFILE, seed::Union{Int64,Nothing)=nothing) @info "Simulation run started at $(Dates.now())." #TODO add a seed parameter - requires mutable parameters # do some housekeeping - initsettings(config) - Random.seed!(param("core.seed")) + settings = initsettings(config, seed) + Random.seed!(settings["core"]["seed"]) setupdatadir() # initialise world-level properties landscape = initlandscape() events = Vector{FarmEvent}() space = GridSpace(size(landscape), periodic=false) - properties = Dict{Symbol,Any}(:date=>param("core.startdate"), + properties = Dict{Symbol,Any}(:settings=>settings, + :date=>settings["core"]["startdate"], :landscape=>landscape, :events=>events) @debug "Setting up model."