|
| 1 | +using MultiScaleArrays, OrdinaryDiffEq, DiffEqBase, StochasticDiffEq |
| 2 | +using Base.Test |
| 3 | + |
| 4 | +struct PlantSettings{T} x::T end |
| 5 | +struct OrganParams{T} y::T end |
| 6 | + |
| 7 | +struct Organ{B<:Number,P} <: AbstractMultiScaleArrayLeaf{B} |
| 8 | + values::Vector{B} |
| 9 | + name::Symbol |
| 10 | + params::P |
| 11 | +end |
| 12 | + |
| 13 | +struct Plant{B,S,N<:Tuple{Vararg{<:Organ{<:Number}}}} <: AbstractMultiScaleArray{B} |
| 14 | + nodes::N |
| 15 | + values::Vector{B} |
| 16 | + end_idxs::Vector{Int} |
| 17 | + settings::S |
| 18 | +end |
| 19 | + |
| 20 | +struct Community{B,N<:Tuple{Vararg{<:Plant{<:Number}}}} <: AbstractMultiScaleArray{B} |
| 21 | + nodes::N |
| 22 | + values::Vector{B} |
| 23 | + end_idxs::Vector{Int} |
| 24 | +end |
| 25 | + |
| 26 | +mutable struct Scenario{B,N<:Tuple{Vararg{<:Community{<:Number}}}} <: AbstractMultiScaleArrayHead{B} |
| 27 | + nodes::N |
| 28 | + values::Vector{B} |
| 29 | + end_idxs::Vector{Int} |
| 30 | +end |
| 31 | + |
| 32 | +organ1 = Organ([1.1,2.1,3.1], :Shoot, OrganParams(:grows_up)) |
| 33 | +organ2 = Organ([4.1,5.1,6.1], :Root, OrganParams("grows down")) |
| 34 | +organ3 = Organ([1.2,2.2,3.2], :Shoot, OrganParams(true)) |
| 35 | +organ4 = Organ([4.2,5.2,6.2], :Root, OrganParams(1//3)) |
| 36 | +plant1 = construct(Plant, (deepcopy(organ1), deepcopy(organ2)), Float64[], PlantSettings(1)) |
| 37 | +plant2 = construct(Plant, (deepcopy(organ3), deepcopy(organ4)), Float64[], PlantSettings(1.0)) |
| 38 | +community = construct(Community, (deepcopy(plant1), deepcopy(plant2), )) |
| 39 | +scenario = construct(Scenario, (deepcopy(community),)) |
| 40 | + |
| 41 | +@inferred getindex(organ1, 1) |
| 42 | +@inferred getindex(plant1, 3) |
| 43 | +@inferred getindex(community, 4) |
| 44 | +@inferred getindex(scenario, 8) |
| 45 | + |
| 46 | +@test scenario[1] == 1.1 |
| 47 | +@test scenario[2] == 2.1 |
| 48 | +@test scenario[3] == 3.1 |
| 49 | +@test scenario[4] == 4.1 |
| 50 | +@test scenario[5] == 5.1 |
| 51 | +@test scenario[6] == 6.1 |
| 52 | +@test scenario[7] == 1.2 |
| 53 | +@test scenario[8] == 2.2 |
| 54 | +@test scenario[9] == 3.2 |
| 55 | +@test scenario[10] == 4.2 |
| 56 | +@test scenario[11] == 5.2 |
| 57 | +@test scenario[12] == 6.2 |
| 58 | + |
| 59 | +@test getindices(scenario, 1) == 1:12 |
| 60 | +@test getindices(scenario, 1, 1) == 1:6 |
| 61 | +@test getindices(scenario, 1, 2) == 7:12 |
| 62 | +@test getindices(scenario, 1, 1, 1) == 1:3 |
| 63 | +@test getindices(scenario, 1, 1, 2) == 4:6 |
| 64 | +@test getindices(scenario, 1, 2, 1) == 7:9 |
| 65 | +@test getindices(scenario, 1, 2, 2) == 10:12 |
| 66 | + |
| 67 | +organ_ode = function (dorgan,organ,p,t) |
| 68 | + m = mean(organ) |
| 69 | + for i in eachindex(organ) |
| 70 | + dorgan[i] = -m*organ[i] |
| 71 | + end |
| 72 | +end |
| 73 | +f = function (dscenario,scenario,p,t) |
| 74 | + for (organ, y, z) in LevelIterIdx(scenario, 2) |
| 75 | + organ_ode(@view(dscenario[y:z]),organ,p,t) |
| 76 | + end |
| 77 | +end |
| 78 | +affect! = function (integrator) |
| 79 | + add_node!(integrator, integrator.u[1, 1, 1], 1, 1) |
| 80 | +end |
| 81 | + |
| 82 | +println("ODE with tuple nodes") |
| 83 | + |
| 84 | +prob = ODEProblem(f, scenario, (0.0, 1.0)) |
| 85 | + |
| 86 | +sol = solve(prob, Tsit5()) |
| 87 | + |
| 88 | +@test length(sol[end]) == 12 |
0 commit comments