11using Agents
2- using Statistics: mean
32import StatsBase
43using Random
54
6-
75@agent Daisy GridAgent{2 } begin
86 breed:: Symbol
97 age:: Int
108 albedo:: Float64 # 0-1 fraction
119end
1210
13- DaisyWorld = ABM{<: GridSpaceSingle , Daisy};
11+ DaisyWorld = ABM{<: GridSpaceSingle , Daisy}
1412
1513function update_surface_temperature! (pos, model:: DaisyWorld )
16- ids = ids_in_position (pos, model)
17- absorbed_luminosity = if isempty (ids) # no daisy
18- # # Set luminosity via surface albedo
14+ absorbed_luminosity = if isempty (pos, model) # no daisy
1915 (1 - model. surface_albedo) * model. solar_luminosity
2016 else
21- # # Set luminosity via daisy albedo
22- (1 - model[ids[ 1 ]] . albedo) * model. solar_luminosity
17+ daisy = model[ id_in_position (pos, model)]
18+ (1 - daisy . albedo) * model. solar_luminosity
2319 end
24- # # We expect local heating to be 80 ᵒC for an absorbed luminosity of 1,
25- # # approximately 30 for 0.5 and approximately -273 for 0.01.
2620 local_heating = absorbed_luminosity > 0 ? 72 * log (absorbed_luminosity) + 80 : 80
27- # # Surface temperature is the average of the current temperature and local heating.
2821 model. temperature[pos... ] = (model. temperature[pos... ] + local_heating) / 2
2922end
3023
3124function diffuse_temperature! (pos, model:: DaisyWorld )
32- ratio = get ( model. properties, : ratio, 0.5 ) # diffusion ratio
25+ ratio = model. ratio # diffusion ratio
3326 npos = nearby_positions (pos, model)
3427 model. temperature[pos... ] =
3528 (1 - ratio) * model. temperature[pos... ] +
36- # # Each neighbor is giving up 1/8 of the diffused
37- # # amount to each of *its* neighbors
3829 sum (model. temperature[p... ] for p in npos) * 0.125 * ratio
3930end
4031
41- function propagate_daisy! (pos, model:: DaisyWorld )
42- ids = ids_in_position (pos, model)
43- if ! isempty (ids)
44- daisy = model[ids[1 ]]
45- temperature = model. temperature[pos... ]
46- # # Set optimum growth rate to 22.5 ᵒC, with bounds of [5, 40]
47- seed_threshold = (0.1457 * temperature - 0.0032 * temperature^ 2 ) - 0.6443
48- if rand (model. rng) < seed_threshold
49- # # Collect all adjacent position that have no daisies
50- empty_neighbors = Tuple{Int,Int}[]
51- neighbors = nearby_positions (pos, model)
52- for n in neighbors
53- if isempty (ids_in_position (n, model))
54- push! (empty_neighbors, n)
55- end
56- end
57- if ! isempty (empty_neighbors)
58- # # Seed a new daisy in one of those position
59- seeding_place = rand (model. rng, empty_neighbors)
60- add_agent! (seeding_place, model, daisy. breed, 0 , daisy. albedo)
32+ function propagate! (pos, model:: DaisyWorld )
33+ isempty (pos, model) && return
34+ daisy = model[id_in_position (pos, model)]
35+ temperature = model. temperature[pos... ]
36+ seed_threshold = (0.1457 * temperature - 0.0032 * temperature^ 2 ) - 0.6443
37+ if rand (model. rng) < seed_threshold
38+ empty_near_pos = Tuple{Int,Int}[]
39+ for near_pos in nearby_positions (pos, model)
40+ if isempty (near_pos, model)
41+ push! (empty_near_pos, near_pos)
6142 end
6243 end
44+ if ! isempty (empty_near_pos)
45+ seeding_place = rand (model. rng, empty_near_pos)
46+ add_agent! (seeding_place, model, daisy. breed, 0 , daisy. albedo)
47+ end
6348 end
6449end
6550
6651function daisy_step! (agent:: Daisy , model:: DaisyWorld )
6752 agent. age += 1
68- agent. age >= model. max_age && kill_agent! (agent, model)
53+ agent. age ≥ model. max_age && kill_agent! (agent, model)
6954end
7055
7156function daisyworld_step! (model)
7257 for p in positions (model)
7358 update_surface_temperature! (p, model)
7459 diffuse_temperature! (p, model)
75- propagate_daisy ! (p, model)
60+ propagate ! (p, model)
7661 end
77- model. tick += 1
62+ model. tick[] = model . tick[] + 1
7863 solar_activity! (model)
7964end
8065
8166function solar_activity! (model:: DaisyWorld )
8267 if model. scenario == :ramp
83- if model. tick > 200 && model. tick <= 400
68+ if model. tick[] > 200 && model. tick[] ≤ 400
8469 model. solar_luminosity += model. solar_change
8570 end
86- if model. tick > 500 && model. tick <= 750
71+ if model. tick[] > 500 && model. tick[] ≤ 750
8772 model. solar_luminosity -= model. solar_change / 2
8873 end
8974 elseif model. scenario == :change
9075 model. solar_luminosity += model. solar_change
9176 end
9277end
9378
79+ using Random
80+
9481function daisyworld (;
9582 griddims = (30 , 30 ),
9683 max_age = 25 ,
@@ -107,14 +94,12 @@ function daisyworld(;
10794
10895 rng = MersenneTwister (seed)
10996 space = GridSpaceSingle (griddims)
110- properties = (;max_age, surface_albedo, solar_luminosity, solar_change, scenario,)
111- properties = Dict (pairs (properties))
112- properties[:tick ] = 0
113- properties[:temperature ] = zeros (griddims)
97+ properties = (;max_age, surface_albedo, solar_luminosity, solar_change, scenario,
98+ tick = Ref (0 ), ratio = 0.5 , temperature = zeros (griddims)
99+ )
114100
115101 model = ABM (Daisy, space; properties, rng)
116102
117- # # Populate with daisies: each position has only one daisy (black or white)
118103 grid = collect (positions (model))
119104 num_positions = prod (griddims)
120105 white_positions =
@@ -131,10 +116,9 @@ function daisyworld(;
131116 add_agent_pos! (wd, model)
132117 end
133118
134- # # Adjust temperature to initial daisy distribution
135119 for p in positions (model)
136120 update_surface_temperature! (p, model)
137121 end
138122
139- return model, daisy_step!, daisyworld_step!
123+ return model
140124end
0 commit comments