Skip to content

Commit ab0f26c

Browse files
committed
Merge branch 'main' into compile-models
2 parents fff3b81 + c2254a8 commit ab0f26c

30 files changed

Lines changed: 261 additions & 171 deletions

.github/workflows/CI.yml

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ concurrency:
1313
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
1414
jobs:
1515
test:
16-
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }}
16+
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ github.event_name }}
1717
runs-on: ${{ matrix.os }}
1818
timeout-minutes: 60
19-
permissions: # needed to allow julia-actions/cache to proactively delete old caches that it has created
19+
permissions:
20+
# needed to allow julia-actions/cache to proactively delete old caches that it has created
2021
actions: write
2122
contents: read
2223
strategy:
@@ -29,21 +30,18 @@ jobs:
2930
- ubuntu-latest
3031
- macOS-latest
3132
- windows-latest
32-
arch:
33-
- x64
3433
steps:
3534
- uses: actions/checkout@v6
36-
- uses: julia-actions/setup-julia@v2
35+
- uses: julia-actions/setup-julia@v3
3736
with:
3837
version: ${{ matrix.version }}
39-
arch: ${{ matrix.arch }}
4038
- uses: julia-actions/cache@v3
4139
- uses: julia-actions/julia-buildpkg@v1
4240
- uses: julia-actions/julia-runtest@v1
4341
env:
4442
JULIA_NUM_THREADS: 4
4543
- uses: julia-actions/julia-processcoverage@v1
46-
- uses: codecov/codecov-action@v5
44+
- uses: codecov/codecov-action@v6
4745
with:
4846
files: lcov.info
4947
docs:
@@ -55,7 +53,7 @@ jobs:
5553
statuses: write
5654
steps:
5755
- uses: actions/checkout@v6
58-
- uses: julia-actions/setup-julia@v2
56+
- uses: julia-actions/setup-julia@v3
5957
with:
6058
version: "1"
6159
- uses: julia-actions/cache@v3

.github/workflows/Integration.yml

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ concurrency:
1313
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
1414
jobs:
1515
test:
16-
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }}
16+
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ github.event_name }}
1717
runs-on: ${{ matrix.os }}
1818
timeout-minutes: 60
19-
permissions: # needed to allow julia-actions/cache to proactively delete old caches that it has created
19+
permissions:
20+
# needed to allow julia-actions/cache to proactively delete old caches that it has created
2021
actions: write
2122
contents: read
2223
strategy:
@@ -26,22 +27,14 @@ jobs:
2627
- "1"
2728
os:
2829
- ubuntu-latest
29-
arch:
30-
- x64
3130
package:
3231
- { user: PalmStudio, repo: XPalm.jl, branch: main, default: main }
33-
- {
34-
user: VEZY,
35-
repo: PlantBioPhysics.jl,
36-
branch: master,
37-
default: master,
38-
}
32+
- { user: VEZY, repo: PlantBioPhysics.jl, branch: master, default: master }
3933
steps:
4034
- uses: actions/checkout@v6
41-
- uses: julia-actions/setup-julia@v2
35+
- uses: julia-actions/setup-julia@v3
4236
with:
4337
version: ${{ matrix.version }}
44-
arch: ${{ matrix.arch }}
4538
- uses: julia-actions/julia-buildpkg@v1
4639
- name: Clone Downstream
4740
uses: actions/checkout@v6
@@ -72,6 +65,6 @@ jobs:
7265
echo "This action requires the downstream dependencies' branches to be set to their main/master to succeed. Please switch them back and ensure tests pass before merging"
7366
exit 1
7467
- uses: julia-actions/julia-processcoverage@v1
75-
- uses: codecov/codecov-action@v5
68+
- uses: codecov/codecov-action@v6
7669
with:
7770
files: lcov.info

README.md

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -233,52 +233,52 @@ The package is designed to be easily scalable, and can be used to simulate model
233233

234234
```julia
235235
mapping = ModelMapping(
236-
"Scene" => ToyDegreeDaysCumulModel(),
237-
"Plant" => (
236+
:Scene => ToyDegreeDaysCumulModel(),
237+
:Plant => (
238238
MultiScaleModel(
239239
model=ToyLAIModel(),
240240
mapped_variables=[
241-
:TT_cu => "Scene",
241+
:TT_cu => :Scene,
242242
],
243243
),
244244
Beer(0.6),
245245
MultiScaleModel(
246246
model=ToyAssimModel(),
247-
mapped_variables=[:soil_water_content => "Soil"],
247+
mapped_variables=[:soil_water_content => :Soil],
248248
),
249249
MultiScaleModel(
250250
model=ToyCAllocationModel(),
251251
mapped_variables=[
252-
:carbon_demand => ["Leaf", "Internode"],
253-
:carbon_allocation => ["Leaf", "Internode"]
252+
:carbon_demand => [:Leaf, :Internode],
253+
:carbon_allocation => [:Leaf, :Internode]
254254
],
255255
),
256256
MultiScaleModel(
257257
model=ToyPlantRmModel(),
258-
mapped_variables=[:Rm_organs => ["Leaf" => :Rm, "Internode" => :Rm],],
258+
mapped_variables=[:Rm_organs => [:Leaf => :Rm, :Internode => :Rm],],
259259
),
260260
),
261-
"Internode" => (
261+
:Internode => (
262262
MultiScaleModel(
263263
model=ToyCDemandModel(optimal_biomass=10.0, development_duration=200.0),
264-
mapped_variables=[:TT => "Scene",],
264+
mapped_variables=[:TT => :Scene,],
265265
),
266266
MultiScaleModel(
267267
model=ToyInternodeEmergence(TT_emergence=20.0),
268-
mapped_variables=[:TT_cu => "Scene"],
268+
mapped_variables=[:TT_cu => :Scene],
269269
),
270270
ToyMaintenanceRespirationModel(1.5, 0.06, 25.0, 0.6, 0.004),
271271
Status(carbon_biomass=1.0)
272272
),
273-
"Leaf" => (
273+
:Leaf => (
274274
MultiScaleModel(
275275
model=ToyCDemandModel(optimal_biomass=10.0, development_duration=200.0),
276-
mapped_variables=[:TT => "Scene",],
276+
mapped_variables=[:TT => :Scene,],
277277
),
278278
ToyMaintenanceRespirationModel(2.1, 0.06, 25.0, 1.0, 0.025),
279279
Status(carbon_biomass=1.0)
280280
),
281-
"Soil" => (
281+
:Soil => (
282282
ToySoilWaterModel(),
283283
),
284284
);
@@ -305,11 +305,11 @@ And run the simulation:
305305

306306
```julia
307307
out_vars = ModelMapping(
308-
"Scene" => (:TT_cu,),
309-
"Plant" => (:carbon_allocation, :carbon_assimilation, :soil_water_content, :aPPFD, :TT_cu, :LAI),
310-
"Leaf" => (:carbon_demand, :carbon_allocation),
311-
"Internode" => (:carbon_demand, :carbon_allocation),
312-
"Soil" => (:soil_water_content,),
308+
:Scene => (:TT_cu,),
309+
:Plant => (:carbon_allocation, :carbon_assimilation, :soil_water_content, :aPPFD, :TT_cu, :LAI),
310+
:Leaf => (:carbon_demand, :carbon_allocation),
311+
:Internode => (:carbon_demand, :carbon_allocation),
312+
:Soil => (:soil_water_content,),
313313
)
314314

315315
out = run!(mtg, mapping, meteo, outputs=out_vars, executor=SequentialEx());

benchmark/benchmarks.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ SUITE[suite_name]["XPalm_setup"] = @benchmarkable xpalm_default_param_create() s
4444
palm, models, out_vars, meteo = xpalm_default_param_create()
4545
sim_outputs = xpalm_default_param_run(palm, models, out_vars, meteo)
4646

47-
SUITE[suite_name]["XPalm_run"] = @benchmarkable xpalm_default_param_run($palm, $models, $out_vars, $meteo) seconds = 120
48-
SUITE[suite_name]["XPalm_convert_outputs"] = @benchmarkable xpalm_default_param_convert_outputs($sim_outputs) seconds = 120
47+
SUITE[suite_name]["XPalm_run"] = @benchmarkable xpalm_default_param_run(palm, models, out_vars, meteo) setup = ((palm, models, out_vars, meteo) = xpalm_default_param_create())
48+
SUITE[suite_name]["XPalm_convert_outputs"] = @benchmarkable xpalm_default_param_convert_outputs($sim_outputs)
4949

5050
#tune!(SUITE)
5151
#results = run(SUITE, verbose=true)

benchmark/test-PSE-benchmark.jl

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,21 @@ function PlantSimEngine.run!(m::ToyInternodeCrazyEmergence, models, status, mete
2828

2929
if length(MultiScaleTreeGraph.children(status.node)) == 1 && status.TT_cu - status.TT_cu_emergence >= m.TT_emergence
3030

31-
status_new_internode = add_organ!(status.node, sim_object, "<", "Internode", 2, index=1)
32-
add_organ!(status_new_internode.node, sim_object, "+", "Leaf", 2, index=1)
31+
status_new_internode = add_organ!(status.node, sim_object, "<", :Internode, 2, index=1)
32+
add_organ!(status_new_internode.node, sim_object, "+", :Leaf, 2, index=1)
3333
status_new_internode.TT_cu_emergence = status.TT_cu
3434
elseif (length(MultiScaleTreeGraph.children(status.node)) >= 2 && length(MultiScaleTreeGraph.children(status.node)) < 7) && status.TT_cu - status.TT_cu_emergence >= m.TT_emergence
35-
status_new_internode = add_organ!(status.node, sim_object, "<", "Internode", 2, index=1)
36-
add_organ!(status.node, sim_object, "+", "Leaf", 2, index=4)
37-
add_organ!(status.node, sim_object, "+", "Leaf", 2, index=5)
35+
status_new_internode = add_organ!(status.node, sim_object, "<", :Internode, 2, index=1)
36+
add_organ!(status.node, sim_object, "+", :Leaf, 2, index=4)
37+
add_organ!(status.node, sim_object, "+", :Leaf, 2, index=5)
3838
status_new_internode.TT_cu_emergence = status.TT_cu
3939
elseif (length(MultiScaleTreeGraph.children(status.node)) >= 7 && length(MultiScaleTreeGraph.children(status.node)) < 30) && status.TT_cu - status.TT_cu_emergence >= m.TT_emergence
40-
add_organ!(status.node, sim_object, "+", "Leaf", 2, index=6)
41-
add_organ!(status.node, sim_object, "+", "Leaf", 2, index=7)
42-
add_organ!(status.node, sim_object, "+", "Leaf", 2, index=8)
43-
add_organ!(status.node, sim_object, "+", "Leaf", 2, index=9)
44-
add_organ!(status.node, sim_object, "+", "Leaf", 2, index=10)
45-
add_organ!(status.node, sim_object, "+", "Leaf", 2, index=11)
40+
add_organ!(status.node, sim_object, "+", :Leaf, 2, index=6)
41+
add_organ!(status.node, sim_object, "+", :Leaf, 2, index=7)
42+
add_organ!(status.node, sim_object, "+", :Leaf, 2, index=8)
43+
add_organ!(status.node, sim_object, "+", :Leaf, 2, index=9)
44+
add_organ!(status.node, sim_object, "+", :Leaf, 2, index=10)
45+
add_organ!(status.node, sim_object, "+", :Leaf, 2, index=11)
4646

4747
end
4848

@@ -60,62 +60,62 @@ function do_benchmark_on_heavier_mtg()
6060

6161
#similar to the mtg growth test but with a much lower emergence threshold
6262
mapping = ModelMapping(
63-
"Scene" => ToyDegreeDaysCumulModel(),
64-
"Plant" => (
63+
:Scene => ToyDegreeDaysCumulModel(),
64+
:Plant => (
6565
MultiScaleModel(
6666
model=ToyLAIModel(),
6767
mapped_variables=[
68-
:TT_cu => "Scene",
68+
:TT_cu => :Scene,
6969
],
7070
),
7171
PlantSimEngine.Examples.Beer(0.6),
7272
MultiScaleModel(
7373
model=ToyCAllocationModel(),
7474
mapped_variables=[
75-
:carbon_assimilation => ["Leaf"],
76-
:carbon_demand => ["Leaf", "Internode"],
77-
:carbon_allocation => ["Leaf", "Internode"]
75+
:carbon_assimilation => [:Leaf],
76+
:carbon_demand => [:Leaf, :Internode],
77+
:carbon_allocation => [:Leaf, :Internode]
7878
],
7979
),
8080
MultiScaleModel(
8181
model=ToyPlantRmModel(),
82-
mapped_variables=[:Rm_organs => ["Leaf" => :Rm, "Internode" => :Rm],],
82+
mapped_variables=[:Rm_organs => [:Leaf => :Rm, :Internode => :Rm],],
8383
),
8484
),
85-
"Internode" => (
85+
:Internode => (
8686
MultiScaleModel(
8787
model=ToyCDemandModel(optimal_biomass=10.0, development_duration=200.0),
88-
mapped_variables=[:TT => "Scene",],
88+
mapped_variables=[:TT => :Scene,],
8989
),
9090
MultiScaleModel(
9191
model=ToyInternodeCrazyEmergence(TT_emergence=1.0),
92-
mapped_variables=[:TT_cu => "Scene"],
92+
mapped_variables=[:TT_cu => :Scene],
9393
),
9494
ToyMaintenanceRespirationModel(1.5, 0.06, 25.0, 0.6, 0.004),
9595
Status(carbon_biomass=1.0)
9696
),
97-
"Leaf" => (
97+
:Leaf => (
9898
MultiScaleModel(
9999
model=ToyAssimModel(),
100-
mapped_variables=[:soil_water_content => "Soil", :aPPFD => "Plant"],
100+
mapped_variables=[:soil_water_content => :Soil, :aPPFD => :Plant],
101101
),
102102
MultiScaleModel(
103103
model=ToyCDemandModel(optimal_biomass=10.0, development_duration=200.0),
104-
mapped_variables=[:TT => "Scene",],
104+
mapped_variables=[:TT => :Scene,],
105105
),
106106
ToyMaintenanceRespirationModel(2.1, 0.06, 25.0, 1.0, 0.025),
107107
Status(carbon_biomass=1.0)
108108
),
109-
"Soil" => (
109+
:Soil => (
110110
ToySoilWaterModel(),
111111
),
112112
)
113113

114114
out_vars = Dict(
115-
"Leaf" => (:carbon_assimilation, :carbon_demand, :soil_water_content, :carbon_allocation),
116-
"Internode" => (:carbon_allocation, :TT_cu_emergence),
117-
"Plant" => (:carbon_allocation,),
118-
"Soil" => (:soil_water_content,),
115+
:Leaf => (:carbon_assimilation, :carbon_demand, :soil_water_content, :carbon_allocation),
116+
:Internode => (:carbon_allocation, :TT_cu_emergence),
117+
:Plant => (:carbon_allocation,),
118+
:Soil => (:soil_water_content,),
119119
)
120120

121121
out = run!(mtg, mapping, meteo_day, tracked_outputs=out_vars, executor=SequentialEx())

benchmark/test-multirate-buffer-benchmark.jl

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ function PlantSimEngine.run!(::MRBenchConsumer24Model, models, status, meteo, co
3131
end
3232

3333
function _build_multirate_benchmark_mtg(nleaves::Int)
34-
mtg = Node(MultiScaleTreeGraph.NodeMTG("/", "Scene", 1, 0))
35-
plant = Node(mtg, MultiScaleTreeGraph.NodeMTG("+", "Plant", 1, 1))
36-
internode = Node(plant, MultiScaleTreeGraph.NodeMTG("/", "Internode", 1, 2))
34+
mtg = Node(MultiScaleTreeGraph.NodeMTG("/", :Scene, 1, 0))
35+
plant = Node(mtg, MultiScaleTreeGraph.NodeMTG("+", :Plant, 1, 1))
36+
internode = Node(plant, MultiScaleTreeGraph.NodeMTG("/", :Internode, 1, 2))
3737

3838
for i in 1:nleaves
39-
Node(internode, MultiScaleTreeGraph.NodeMTG("+", "Leaf", i, 2))
39+
Node(internode, MultiScaleTreeGraph.NodeMTG("+", :Leaf, i, 2))
4040
end
4141

4242
return mtg
@@ -46,30 +46,30 @@ function setup_multirate_buffer_benchmark(; nleaves=2000, ndays=30)
4646
mtg = _build_multirate_benchmark_mtg(nleaves)
4747

4848
mapping = ModelMapping(
49-
"Leaf" => (
49+
:Leaf => (
5050
ModelSpec(MRBenchSourceModel(Ref(0))) |> TimeStepModel(1.0),
5151
),
52-
"Plant" => (
52+
:Plant => (
5353
ModelSpec(MRBenchConsumer4Model()) |>
54-
MultiScaleModel([:X => ["Leaf"]]) |>
54+
MultiScaleModel([:X => [:Leaf]]) |>
5555
TimeStepModel(ClockSpec(4.0, 1.0)) |>
56-
InputBindings(; X=(process=:mrbenchsource, var=:X, scale="Leaf", policy=Integrate())),
56+
InputBindings(; X=(process=:mrbenchsource, var=:X, scale=:Leaf, policy=Integrate())),
5757
ModelSpec(MRBenchConsumer24Model()) |>
58-
MultiScaleModel([:X => ["Leaf"]]) |>
58+
MultiScaleModel([:X => [:Leaf]]) |>
5959
TimeStepModel(ClockSpec(24.0, 1.0)) |>
60-
InputBindings(; X=(process=:mrbenchsource, var=:X, scale="Leaf", policy=Integrate())),
60+
InputBindings(; X=(process=:mrbenchsource, var=:X, scale=:Leaf, policy=Integrate())),
6161
),
6262
)
6363

6464
nsteps = 24 * ndays
6565
meteo = Weather(repeat([Atmosphere(T=20.0, Wind=1.0, Rh=0.65)], nsteps))
6666

6767
reqs = [
68-
OutputRequest("Leaf", :X; name=:x_hourly, process=:mrbenchsource, policy=HoldLast()),
69-
OutputRequest("Leaf", :X; name=:x_daily_sum, process=:mrbenchsource, policy=Integrate(), clock=ClockSpec(24.0, 1.0)),
68+
OutputRequest(:Leaf, :X; name=:x_hourly, process=:mrbenchsource, policy=HoldLast()),
69+
OutputRequest(:Leaf, :X; name=:x_daily_sum, process=:mrbenchsource, policy=Integrate(), clock=ClockSpec(24.0, 1.0)),
7070
]
7171

72-
tracked = Dict("Plant" => (:Y4, :Y24), "Leaf" => (:X,))
72+
tracked = Dict(:Plant => (:Y4, :Y24), :Leaf => (:X,))
7373
return mtg, mapping, meteo, reqs, tracked, nsteps
7474
end
7575

docs/src/API/API_public.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ Scope selection detail:
7070
### Exporting variables at requested rates
7171

7272
```julia
73-
req_hold = OutputRequest("Leaf", :A; name=:A_hourly, process=:assim, policy=HoldLast())
74-
req_day = OutputRequest("Leaf", :A; name=:A_daily_sum, process=:assim, policy=Integrate(), clock=ClockSpec(24.0, 1.0))
73+
req_hold = OutputRequest(:Leaf, :A; name=:A_hourly, process=:assim, policy=HoldLast())
74+
req_day = OutputRequest(:Leaf, :A; name=:A_daily_sum, process=:assim, policy=Integrate(), clock=ClockSpec(24.0, 1.0))
7575
run!(sim, meteo; tracked_outputs=[req_hold, req_day], executor=SequentialEx())
7676
out = collect_outputs(sim; sink=DataFrame)
7777

@@ -126,23 +126,23 @@ Use `Integrate` for accumulation semantics and `Aggregate` for summary-statistic
126126
```julia
127127
ModelSpec(DailyModel()) |>
128128
TimeStepModel(ClockSpec(24.0, 1.0)) |>
129-
InputBindings(; a=(process=:hourly_assim, var=:A, scale="Leaf", policy=Integrate(SumReducer())))
129+
InputBindings(; a=(process=:hourly_assim, var=:A, scale=:Leaf, policy=Integrate(SumReducer())))
130130

131131
ModelSpec(DailyModel()) |>
132132
TimeStepModel(ClockSpec(24.0, 1.0)) |>
133-
InputBindings(; a=(process=:hourly_assim, var=:A, scale="Leaf", policy=Aggregate(MaxReducer())))
133+
InputBindings(; a=(process=:hourly_assim, var=:A, scale=:Leaf, policy=Aggregate(MaxReducer())))
134134

135135
ModelSpec(DailyModel()) |>
136136
TimeStepModel(ClockSpec(24.0, 1.0)) |>
137-
InputBindings(; a=(process=:hourly_assim, var=:A, scale="Leaf", policy=Integrate(vals -> maximum(vals) - minimum(vals))))
137+
InputBindings(; a=(process=:hourly_assim, var=:A, scale=:Leaf, policy=Integrate(vals -> maximum(vals) - minimum(vals))))
138138

139139
ModelSpec(DailyModel()) |>
140140
TimeStepModel(ClockSpec(24.0, 1.0)) |>
141-
InputBindings(; a=(process=:hourly_assim, var=:A, scale="Leaf", policy=Integrate((vals, durations) -> sum(vals .* durations))))
141+
InputBindings(; a=(process=:hourly_assim, var=:A, scale=:Leaf, policy=Integrate((vals, durations) -> sum(vals .* durations))))
142142

143143
ModelSpec(DailyModel()) |>
144144
TimeStepModel(ClockSpec(24.0, 1.0)) |>
145-
InputBindings(; a=(process=:hourly_assim, var=:A, scale="Leaf", policy=Integrate(PlantMeteo.DurationSumReducer())))
145+
InputBindings(; a=(process=:hourly_assim, var=:A, scale=:Leaf, policy=Integrate(PlantMeteo.DurationSumReducer())))
146146
```
147147

148148
Built-in reducer types are:

0 commit comments

Comments
 (0)