Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Persefone.jl
Manage
Activity
Members
Plan
Wiki
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Locked files
Deploy
Package Registry
Model registry
Operate
Terraform modules
Analyze
Contributor analytics
Repository analytics
Insights
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Persefone
Persefone.jl
Commits
e43c5ebd
Commit
e43c5ebd
authored
8 months ago
by
xo30xoqa
Browse files
Options
Downloads
Patches
Plain Diff
First version of farm model (seems to work)
parent
eb8515d8
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
src/crop/almass.jl
+10
-8
10 additions, 8 deletions
src/crop/almass.jl
src/crop/farmplot.jl
+2
-1
2 additions, 1 deletion
src/crop/farmplot.jl
src/farm/farm.jl
+36
-13
36 additions, 13 deletions
src/farm/farm.jl
with
48 additions
and
22 deletions
src/crop/almass.jl
+
10
−
8
View file @
e43c5ebd
...
...
@@ -8,6 +8,7 @@
module
ALMaSS
using
Persefone
:
AnnualDate
,
Management
,
Length
,
cm
,
...
...
@@ -60,16 +61,17 @@ The type struct for all crops. Currently follows the crop growth model as
implemented in ALMaSS.
"""
struct
CropType
#FIXME this needs thinking about. The sowing and harvest dates belong in the farm model,
# not here. Also, we need to harmonise crops across the crop growth models.
name
::
String
group
::
String
minsowdate
::
Union
{
Missing
,
Date
}
maxsowdate
::
Union
{
Missing
,
Date
}
minharvestdate
::
Union
{
Missing
,
Date
}
maxharvestdate
::
Union
{
Missing
,
Date
}
minsowdate
::
Union
{
Missing
,
Annual
Date
}
maxsowdate
::
Union
{
Missing
,
Annual
Date
}
minharvestdate
::
Union
{
Missing
,
Annual
Date
}
maxharvestdate
::
Union
{
Missing
,
Annual
Date
}
mingrowthtemp
::
Union
{
Missing
,
Float64
}
highnutrientgrowth
::
Union
{
Missing
,
CropCurveParams
}
lownutrientgrowth
::
Union
{
Missing
,
CropCurveParams
}
#issowable::Union{Function,Bool}
end
cropname
(
ct
::
CropType
)
=
ct
.
name
...
...
@@ -106,7 +108,7 @@ isharvestable(cs::CropState) = cs.mature
Extend `tryparse` to allow parsing GrowthPhase values.
(Needed to read in the CSV parameter file.)
"""
function
Base.tryparse
(
type
::
Type
{
GrowthPhase
},
str
::
String
)
function
Base.tryparse
(
::
Type
{
GrowthPhase
},
str
::
String
)
str
==
"janfirst"
?
janfirst
:
str
==
"sow"
?
sow
:
str
==
"marchfirst"
?
marchfirst
:
...
...
@@ -152,8 +154,8 @@ Parse a CSV file containing the required parameter values for each crop
"""
function
readcropparameters
(
generalcropfile
::
String
,
growthfile
::
String
)
@debug
"Reading crop parameters"
cropdata
=
CSV
.
File
(
generalcropfile
,
missingstring
=
"NA"
,
dateformat
=
"d U"
,
types
=
[
String
,
Date
,
Date
,
Date
,
Date
,
Float64
,
String
])
cropdata
=
CSV
.
File
(
generalcropfile
,
missingstring
=
"NA"
,
types
=
[
String
,
AnnualDate
,
AnnualDate
,
AnnualDate
,
Annual
Date
,
Float64
,
String
])
growthdata
=
CSV
.
File
(
growthfile
,
missingstring
=
"NA"
,
types
=
[
Int
,
String
,
String
,
GrowthPhase
,
String
,
Float64
,
Float64
,
Float64
,
Float64
])
...
...
This diff is collapsed.
Click to expand it.
src/crop/farmplot.jl
+
2
−
1
View file @
e43c5ebd
...
...
@@ -37,9 +37,9 @@ end
Sow the specified crop on the farmplot.
"""
function
sow!
(
farmplot
::
FarmPlot
,
model
::
SimulationModel
,
cropname
::
String
)
#XXX test if the crop is sowable?
createevent!
(
model
,
farmplot
.
pixels
,
sowing
)
sow!
(
farmplot
.
cropstate
,
model
,
cropname
)
@debug
"Farmer
$
(farmplot.farmer) sowed
$(cropname)
on farmplot
$
(farmplot.id)."
end
"""
...
...
@@ -50,6 +50,7 @@ Harvest the crop of this farmplot.
function
harvest!
(
farmplot
::
FarmPlot
{
T
},
model
::
SimulationModel
)
where
T
createevent!
(
model
,
farmplot
.
pixels
,
harvesting
)
harvest!
(
farmplot
.
cropstate
,
model
)
# TODO: multiply with area to return units of `g`
@debug
"Farmer
$
(farmplot.farmer) harvested
$
(cropname(farmplot)) from farmplot
$
(farmplot.id)."
end
"""
...
...
This diff is collapsed.
Click to expand it.
src/farm/farm.jl
+
36
−
13
View file @
e43c5ebd
...
...
@@ -4,35 +4,52 @@
###
##TODO what data do we need to gather from the farm submodel?
## - area covered by each crop over time
## - average height of each crop over time
## - total income per year
#XXX Initially, we're only working with a single simple crop rotation.
# Later on, we need to figure out how to integrate several.
const
CROPROTATION
=
[
"winter rape"
,
"winter wheat"
,
"maize"
,
"winter barley"
]
#FIXME Currently, this is specific to the ALMaSS model. We need to figure out how to generalise it.
"""
Farmer
This is the agent type for the farm ABM.
(Not yet implemented.)
This is the agent type for the farm ABM.
"""
mutable struct
Farmer
<:
ModelAgent
#XXX make this into an abstract type and create subtypes for different farm submodels? (#69)
const
id
::
Int64
fields
::
Vector
{
Int64
}
# IDs of the farmplots this farmer owns
croprotation
::
Vector
{
String
}
#TODO figure this out
totalincome
::
Float64
# farmplots owned by this farmer and their associated crop rotations and next sowing date
fields
::
Vector
{
Int64
}
croprotations
::
Dict
{
Int64
,
Vector
{
String
}}
sowdates
::
Dict
{
Int64
,
AnnualDate
}
totalincome
::
Float64
# accumulated income XXX split up by year?
end
"""
stepagent!(farmer, model)
Update a farmer by one day.
Update a farmer by one day.
Cycle through all fields and see what management is needed.
"""
function
stepagent!
(
farmer
::
Farmer
,
model
::
SimulationModel
)
for
f
in
farmer
.
fields
field
=
model
.
farmplots
[
f
]
ctype
=
croptype
(
field
)
if
ctype
.
group
!=
"semi-natural"
&&
isharvestable
(
field
)
harvest
!
(
field
,
model
)
@
harvest
(
)
#XXX later: calculate income based on yield and annual price
(
ctype
.
group
!=
"grass"
)
&&
@sow
(
"no growth"
)
elseif
cropname
(
field
)
==
"no growth"
#TODO if a field has been harvested, check if the next crop can be sown
if
ctype
.
group
!=
"grass"
@sow
(
"no growth"
)
cycle!
(
farmer
.
croprotations
[
f
])
# advance the crop rotation
nextcrop
=
model
.
crops
[
farmer
.
croprotations
[
f
][
1
]]
farmer
.
sowdates
[
f
]
=
@rand
(
nextcrop
.
minsowdate
:
nextcrop
.
maxsowdate
)
end
elseif
cropname
(
field
)
==
"no growth"
&&
model
.
date
==
farmer
.
sowdates
[
f
]
# if a field has been harvested, check if the next crop can be sown
@sow
(
farmer
.
croprotations
[
f
][
1
])
end
end
end
...
...
@@ -44,16 +61,22 @@ Initialise the model with a set of farm agents.
"""
function
initfarms!
(
model
::
SimulationModel
)
#XXX initially, we only have one farmer controlling all fields in the region
farmer
=
Farmer
(
1
,
collect
(
1
:
length
(
model
.
farmplots
)),
[]
,
0
)
farmer
=
Farmer
(
1
,
collect
(
1
:
length
(
model
.
farmplots
)),
Dict
(),
Dict
()
,
0
)
model
.
farmers
=
[
farmer
]
setasides
=
findsetasides
(
farmer
,
model
)
for
field
in
model
.
farmplots
field
.
farmer
=
farmer
.
id
if
isgrassland
(
field
,
model
)
@sow
(
"permanent grassland (seeded)"
)
@sow
(
"permanent grassland (grazed)"
)
farmer
.
croprotations
[
field
.
id
]
=
[
"permanent grassland (grazed)"
]
elseif
field
.
id
in
setasides
@sow
(
"permanent set-aside"
)
farmer
.
croprotations
[
field
.
id
]
=
[
"permanent set-aside"
]
else
@sow
(
"no growth"
)
@sow
(
"no growth"
)
# assign each arable field a crop rotation, cycled randomly
farmer
.
croprotations
[
field
.
id
]
=
cycle!
(
deepcopy
(
CROPROTATION
),
@rand
(
0
:
3
))
nextcrop
=
model
.
crops
[
farmer
.
croprotations
[
field
.
id
][
1
]]
farmer
.
sowdates
[
field
.
id
]
=
@rand
(
nextcrop
.
minsowdate
:
nextcrop
.
maxsowdate
)
end
end
end
...
...
@@ -70,7 +93,7 @@ function findsetasides(farmer::Farmer, model::SimulationModel)
model
.
farmplots
[
farmer
.
fields
]))
setasidearea
=
0
m²
setasides
=
[]
for
f
in
farmer
.
fields
#XXX should be sorted smallest-largest for highest efficiency
for
f
in
keys
(
farmer
.
fields
)
#XXX should be sorted smallest-largest for highest efficiency
field
=
model
.
farmplots
[
f
]
isgrassland
(
field
,
model
)
&&
continue
push!
(
setasides
,
f
)
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment