Skip to content
Snippets Groups Projects
Select Git revision
  • b3e9154953b4393d0efed40cda50ef3955583b11
  • master default protected
  • beta
  • dev
  • andrewssobral-patch-1
  • update
  • thomas-fork
  • 2.0
  • v3.2.0
  • v3.1.0
  • v3.0
  • bgslib_py27_ocv3_win64
  • bgslib_java_2.0.0
  • bgslib_console_2.0.0
  • bgslib_matlab_win64_2.0.0
  • bgslib_qtgui_2.0.0
  • 2.0.0
  • bgs_console_2.0.0
  • bgs_matlab_win64_2.0.0
  • bgs_qtgui_2.0.0
  • v1.9.2_x86_mfc_gui
  • v1.9.2_x64_java_gui
  • v1.9.2_x86_java_gui
23 results

run_video.bat

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    farm.jl 4.47 KiB
    ### Persefone.jl - a model of agricultural landscapes and ecosystems in Europe.
    ###
    ### This file is responsible for managing the farm module(s).
    ###    
    
    
    ## GENERIC TYPES AND FUNCTIONS
    
    "This is the agent type for the farm ABM."
    abstract type Farmer <: ModelAgent end
    
    stepagent!(f::Farmer, model::SimulationModel) =
        @error "Farmer type $(typeof(f)) has no stepagent!() method."
    
    """
        initfarms!(model)
    
    Initialise the model with a set of farm agents, depending on the configured farm model.
    """
    function initfarms!(model::SimulationModel)
        if @param(farm.farmmodel) == "BasicFarmer"
            initbasicfarms!(model)
        else
            Base.error("Farm model $(@param(farm.farmmodel)) doesn't exist.")
        end
    end
    
    
    ## BASIC FARM MODEL
    
    #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.
    
    """
        BasicFarmer
    
    The BasicFarmer type simply applies a set crop rotation to his fields and keeps track of income.
    """
    mutable struct BasicFarmer <: Farmer
        const id::Int64
        # 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. Cycle through all fields and see what management is needed.
    """
    function stepagent!(farmer::BasicFarmer, model::SimulationModel)
        for f in farmer.fields
            field = model.farmplots[f]
            ctype = croptype(field)
            if ctype.group != "semi-natural" && isharvestable(field)
                @harvest()
                #XXX later: calculate income based on yield and annual price
                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
    
    """
        initbasicfarms!(model)
    
    Initialise the basic farm model. All fields are controlled by a single farmer actor
    and are assigned as grassland, set-aside, or arable land with a crop rotation.
    """
    function initbasicfarms!(model::SimulationModel)
        farmer = BasicFarmer(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 (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") # 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
        initfarmdata(model)
    end
    
    """
        findsetasides(farmer, model)
    
    Return a vector of field IDs that this farmer should keep fallow to satisfy the configured
    set-aside rules.
    """
    function findsetasides(farmer::BasicFarmer, model::SimulationModel)
        @param(farm.setaside) == 0 && return []
        croparea = @areaof(sum(f -> isgrassland(f, model) ? 0 : length(f.pixels),
                               model.farmplots[farmer.fields]))
        setasidearea = 0m²
        setasides = []
        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)
            setasidearea += @areaof(length(field.pixels))
            if setasidearea >= croparea*@param(farm.setaside)
                @debug "Farmer $(farmer.id) has set aside $(setasidearea |> ha)."
                return setasides
            end
        end
    end