Simulation over several time-steps
Running the simulation
We saw in the previous section how to run a simulation over one time step. We can also easily perform computations over several time steps from a weather file:
using PlantBiophysics, PlantSimEngine, PlantMeteo
using Dates, DataFrames
meteo =
read_weather(
joinpath(dirname(dirname(pathof(PlantMeteo))), "test", "data", "meteo.csv"),
:temperature => :T,
:relativeHumidity => (x -> x ./ 100) => :Rh,
:wind => :Wind,
:atmosphereCO2_ppm => :Cₐ,
date_format=DateFormat("yyyy/mm/dd")
)
leaf = ModelList(
Monteith(),
Fvcb(),
Medlyn(0.03, 12.0),
status = (
Ra_SW_f = [5., 10., 20.],
sky_fraction = 1.0,
aPPFD = [500., 1000., 1500.0],
d = 0.03
)
)
run!(leaf,meteo)
DataFrame(leaf)
Row | Ra_SW_f | sky_fraction | d | Tₗ | Rn | Ra_LW_f | H | λE | Cₛ | Cᵢ | A | Gₛ | Gbₕ | Dₗ | Gbc | iter | aPPFD | timestep |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Int64 | Float64 | Int64 | |
1 | 5.0 | 1.0 | 0.03 | 21.8357 | 15.9653 | 10.9653 | -165.133 | 181.098 | 343.21 | 321.31 | 24.8309 | 1.12546 | 0.0217955 | 0.71935 | 0.67494 | 2 | 500.0 | 1 |
2 | 10.0 | 1.0 | 0.03 | 22.8402 | 21.1985 | 11.1985 | -193.863 | 215.062 | 339.044 | 317.598 | 32.5028 | 1.49921 | 0.0257133 | 0.700639 | 0.7936 | 2 | 1000.0 | 2 |
3 | 20.0 | 1.0 | 0.03 | 21.9401 | 31.6394 | 11.6394 | -206.854 | 238.493 | 336.54 | 314.38 | 34.6385 | 1.54232 | 0.025764 | 0.766502 | 0.797028 | 2 | 1500.0 | 3 |
The only difference is that we use the Weather
structure instead of the Atmosphere
, and that we provide the models inputs as an Array in the status for the ones that change over time.
Then PlantBiophysics.jl
takes care of the rest and simulate the energy balance over each time-step. Then the output DataFrame has a row for each time-step.
Note that Weather
is in fact just an array of Atmosphere
, with some optional metadata attached to it. We could declare one manually either by using an array of Atmosphere
like so:
meteo = Weather(
[
Atmosphere(T = 20.0, Wind = 1.0, P = 101.3, Rh = 0.65),
Atmosphere(T = 23.0, Wind = 1.5, P = 101.3, Rh = 0.60),
Atmosphere(T = 25.0, Wind = 3.0, P = 101.3, Rh = 0.55)
]
)
Or by passing a DataFrame
:
using DataFrames
df = DataFrame(
T = [20.0, 23.0, 25.0],
Wind = [1.0, 1.5, 3.0],
P = [101.3, 101.3, 101.3],
Rh = [0.65, 0.6, 0.55]
)
meteo = Weather(df)
You'll have to be careful about the names and the units you are using though, they must match exactly the ones expected for Atmosphere
. See the documentation of the structure if in doubt.
The status argument of the ModelList can also be provided as a DataFrame, or any other type that implements the Tables.jl interface. Here's an example using a DataFrame:
using DataFrames
df = DataFrame(:Ra_SW_f => [13.747, 13.8], :sky_fraction => [1.0, 1.0], :d => [0.03, 0.03], :aPPFD => [1300.0, 1500.0])
m = ModelList(Monteith(), Fvcb(), Medlyn(0.03, 12.0), status=df)
PlantSimEngine.DependencyGraph{Dict{Symbol, PlantSimEngine.SoftDependencyNode}}(Dict{Symbol, PlantSimEngine.SoftDependencyNode}(:energy_balance => Monteith{Float64, Int64}
), Dict{Symbol, DataType}())TimeStepTable{Status{(:Ra_SW_f, :sky_fracti...}(2 x 17):
╭─────┬─────────┬──────────────┬─────────┬─────────┬─────────┬─────────┬────────
│ Row │ Ra_SW_f │ sky_fraction │ d │ Tₗ │ Rn │ Ra_LW_f │ ⋯
│ │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float ⋯
├─────┼─────────┼──────────────┼─────────┼─────────┼─────────┼─────────┼────────
│ 1 │ 13.747 │ 1.0 │ 0.03 │ -Inf │ -Inf │ -Inf │ -I ⋯
│ 2 │ 13.8 │ 1.0 │ 0.03 │ -Inf │ -Inf │ -Inf │ -I ⋯
╰─────┴─────────┴──────────────┴─────────┴─────────┴─────────┴─────────┴────────
11 columns omitted
Note that computations will be slower, so if performance is an issue, use TimeStepTable
instead (or a NamedTuple as shown in the example above).