From f3a82bb7555b8f1838a2858af457c41bf991a86a Mon Sep 17 00:00:00 2001 From: Marco Matthies <71844+marcom@users.noreply.github.com> Date: Thu, 25 Jul 2024 11:49:08 +0200 Subject: [PATCH] Rework `initfields!()`, remove `initfields_fill_with!()` New `make_cropstate` helper function for switchable crop models. --- src/crop/almass.jl | 19 ++------------- src/crop/cropmodels.jl | 54 ++++++++++++++++++++++++++++++++++++++--- src/crop/farmplot.jl | 34 -------------------------- src/crop/simplecrop.jl | 15 ++---------- test/landscape_tests.jl | 3 ++- 5 files changed, 56 insertions(+), 69 deletions(-) diff --git a/src/crop/almass.jl b/src/crop/almass.jl index 4c7dff6..dbc316b 100644 --- a/src/crop/almass.jl +++ b/src/crop/almass.jl @@ -14,9 +14,9 @@ using Persefone: m, SimulationModel, fertiliser, - initfields_fill_with!, maxtemp, mintemp + import Persefone: stepagent!, croptype, @@ -24,6 +24,7 @@ import Persefone: cropheight, cropcover, cropyield + using Dates: Date, month, monthday using CSV: CSV @@ -166,22 +167,6 @@ function readcropparameters(generalcropfile::String, growthfile::String) croptypes end -""" - initfields!(model) - -Initialise the model with its farm plots. -""" -function initfields!(model::SimulationModel) - initfields_fill_with!(model) do model, x, y - month(model.date) < 3 ? phase = ALMaSS.janfirst : phase = ALMaSS.marchfirst - FarmPlot(length(model.farmplots) + 1, [(x,y)], - CropState(model.crops["natural grass"], - phase, - 0.0, 0.0m, 0.0, 0.0, Vector{EventType}()) - ) - end -end - """ stepagent!(farmplot, model) diff --git a/src/crop/cropmodels.jl b/src/crop/cropmodels.jl index 6b47594..0a16bc5 100644 --- a/src/crop/cropmodels.jl +++ b/src/crop/cropmodels.jl @@ -1,6 +1,6 @@ ### Persefone.jl - a model of agricultural landscapes and ecosystems in Europe. ### -### Crop model helper functions. +### Functions for switchable crop models. ### function initcropmodel(cropmodel::AbstractString, cropfile::AbstractString, growthfile::AbstractString) @@ -19,12 +19,58 @@ function initcropmodel(cropmodel::AbstractString, cropfile::AbstractString, grow return crops, Tcroptype, Tcropstate end +""" + initfields!(model) + +Initialise the model with its farm plots. +""" function initfields!(model::SimulationModel, cropmodel::AbstractString) + n = 0 + convertid = Dict{Int64,Int64}() + width, height = size(model.landscape) + for x in 1:width + for y in 1:height + # for each pixel, we need to extract the field ID given by the map input + # file, and convert it into the internal object ID used by Agents.jl, + # creating a new agent object if necessary + rawid = model.landscape[x,y].fieldid + (ismissing(rawid)) && continue + if rawid in keys(convertid) + objectid = convertid[rawid] + model.landscape[x,y].fieldid = objectid + push!(model.farmplots[objectid].pixels, (x,y)) + else + cropstate = make_cropstate(model, cropmodel) + fp = FarmPlot( + length(model.farmplots) + 1, + [(x, y)], + cropstate + ) + push!(model.farmplots, fp) + model.landscape[x,y].fieldid = fp.id + convertid[rawid] = fp.id + n += 1 + end + end + end + @info "Initialised $n farm plots." +end + +function make_cropstate(model::SimulationModel, cropmodel::AbstractString) if cropmodel == "almass" - ALMaSS.initfields!(model) + phase = (month(model.date) < 3 ? ALMaSS.janfirst : ALMaSS.marchfirst) + cs = ALMaSS.CropState( + model.crops["natural grass"], + phase, + 0.0, 0.0m, 0.0, 0.0, Vector{EventType}() + ) elseif cropmodel == "simple" - SimpleCrop.initfields!(model) + cs = SimpleCrop.CropState( + model.crops["natural grass"], + 0.0m + ) else - error("initfields! for crop model '$cropmodel'") + error("Unhandled crop model '$cropmodel' in make_cropstate") end + return cs end diff --git a/src/crop/farmplot.jl b/src/crop/farmplot.jl index 0758219..49a100d 100644 --- a/src/crop/farmplot.jl +++ b/src/crop/farmplot.jl @@ -15,40 +15,6 @@ cropheight(f::FarmPlot{T}) where {T} = cropheight(f.crop_state) cropcover(f::FarmPlot{T}) where {T} = cropcover(f.crop_state) cropyield(f::FarmPlot{T}) where {T} = cropyield(f.crop_state) -""" - initfields_fill_with!(make_farmplot_fn, model) - -Initialise the model with its farm plots, using the -`make_farmplot_fn(model, x, y)` function to create new farmplots. -""" -function initfields_fill_with!(make_farmplot_fn::Function, model::SimulationModel) - n = 0 - convertid = Dict{Int64,Int64}() - width, height = size(model.landscape) - for x in 1:width - for y in 1:height - # for each pixel, we need to extract the field ID given by the map input - # file, and convert it into the internal object ID used by Agents.jl, - # creating a new agent object if necessary - rawid = model.landscape[x,y].fieldid - (ismissing(rawid)) && continue - if rawid in keys(convertid) - objectid = convertid[rawid] - model.landscape[x,y].fieldid = objectid - push!(model.farmplots[objectid].pixels, (x,y)) - else - fp = make_farmplot_fn(model, x, y) - push!(model.farmplots, fp) - model.landscape[x,y].fieldid = fp.id - convertid[rawid] = fp.id - n += 1 - end - end - end - @info "Initialised $n farm plots." -end - - ## UTILITY FUNCTIONS """ diff --git a/src/crop/simplecrop.jl b/src/crop/simplecrop.jl index c653390..dead41f 100644 --- a/src/crop/simplecrop.jl +++ b/src/crop/simplecrop.jl @@ -4,8 +4,8 @@ using Persefone: FarmPlot, Length, m, - SimulationModel, - initfields_fill_with! + SimulationModel + import Persefone: stepagent!, croptype, @@ -41,15 +41,4 @@ function stepagent!(farmplot::FarmPlot{CropState}, model::SimulationModel) # TODO: do something simple end -""" - initfields!(model) - -Initialise the model with its farm plots. -""" -function initfields!(model::SimulationModel) - initfields_fill_with!(model) do model, x, y - FarmPlot(length(model.farmplots) + 1, [(x,y)], CropState(model.crops["natural grass"], 0.0m)) - end -end - end # module SimpleCrop diff --git a/test/landscape_tests.jl b/test/landscape_tests.jl index fc6ae84..d2d3f02 100644 --- a/test/landscape_tests.jl +++ b/test/landscape_tests.jl @@ -6,7 +6,8 @@ @testset "Landscape initialisation" begin model = inittestmodel(false) # these tests are specific to the Jena maps - @test_logs (:info, "Initialised 2092 farm plots.") match_mode=:any Ps.ALMaSS.initfields!(model) + cropmodel = "almass" + @test_logs (:info, "Initialised 2092 farm plots.") match_mode=:any Ps.initfields!(model, cropmodel) @test size(model.landscape) == (1754, 1602) @test Ps.landcover((100,100), model) == Ps.forest @test Ps.landcover((300,1), model) == Ps.soil -- GitLab