Skip to content

Commit

Permalink
Work on updating timesteparrays
Browse files Browse the repository at this point in the history
  • Loading branch information
lrennels committed Feb 20, 2021
1 parent 542aa03 commit ab3ade7
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 254 deletions.
3 changes: 2 additions & 1 deletion benchmark/getindex.jl
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ end
function _get_timesteparray_type(years, num_dims, dtype=Float64)
if Mimi.isuniform(years)
first, stepsize = Mimi.first_and_step(years)
T = Mimi.TimestepArray{Mimi.FixedTimestep{first, stepsize}, Union{dtype, Missing}, num_dims}
last = years[last]
T = Mimi.TimestepArray{Mimi.FixedTimestep{first, stepsize, last}, Union{dtype, Missing}, num_dims}
else
T = Mimi.TimestepArray{Mimi.VariableTimestep{(years...,)}, Union{dtype, Missing}, num_dims}
end
Expand Down
3 changes: 2 additions & 1 deletion src/core/build.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ function _instance_datatype(md::ModelDef, def::AbstractDatumDef)
else
if isuniform(md)
first, stepsize = first_and_step(md)
last = last_period(md)
first === nothing && @warn "_instance_datatype: first === nothing"
T = TimestepArray{FixedTimestep{first, stepsize}, Union{dtype, Missing}, num_dims, ti}
T = TimestepArray{FixedTimestep{first, stepsize, last}, Union{dtype, Missing}, num_dims, ti}
else
times = time_labels(md)
T = TimestepArray{VariableTimestep{(times...,)}, Union{dtype, Missing}, num_dims, ti}
Expand Down
10 changes: 5 additions & 5 deletions src/core/defs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -529,19 +529,19 @@ function set_param!(md::ModelDef, param_name::Symbol, value; dims=nothing, ignor
if num_dims == 0
values = value
else
# # Use the first from the comp_def if it has it, else use the tree root (usu. a ModelDef)
# first = first_period(md, comp_def)


# Use the first from the Model def, not the component, since we now say that the
# data needs to match the dimensions of the model itself, so we need to allocate
# the full time length even if we pad it with missings.
first = first_period(md)

first === nothing && @warn "set_param!: first === nothing"

last = last_period(md)
last === nothing && @warn "set_param!: last === nothing"

if isuniform(md)
stepsize = step_size(md)
values = TimestepArray{FixedTimestep{first, stepsize}, T, num_dims, ti}(value)
values = TimestepArray{FixedTimestep{first, stepsize, last}, T, num_dims, ti}(value)
else
times = time_labels(md)
first_index = findfirst(isequal(first), times)
Expand Down
295 changes: 100 additions & 195 deletions src/core/time_arrays.jl

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/core/types/time.jl
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ mutable struct Clock{T <: AbstractTimestep} <: MimiStruct
end
end

# TDESIGN DISCUSSION: add this for performance?
# mutable struct TimestepArray{T_TS <: AbstractTimestep, T, N, ti, S<:AbstractArray{T,N}} <: MimiStruct
# DESIGN DISCUSSION: add this for performance?
# struct TimestepArray{T_TS <: AbstractTimestep, T, N, ti, S<:AbstractArray{T,N}} <: MimiStruct
# data::S
mutable struct TimestepArray{T_TS <: AbstractTimestep, T, N, ti} <: MimiStruct
data::Union{Array{T, N}, SubArray}
Expand Down
12 changes: 6 additions & 6 deletions test/test_parametertypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ extpars = external_params(m.mi.md)
@test isa(extpars[:e], ArrayModelParameter)
@test isa(extpars[:f], ScalarModelParameter) # note that :f is stored as a scalar parameter even though its values are an array

@test typeof(extpars[:a].values) == TimestepMatrix{FixedTimestep{2000, 1}, arrtype, 1}
@test typeof(extpars[:b].values) == TimestepVector{FixedTimestep{2000, 1}, arrtype}
@test typeof(extpars[:a].values) == TimestepMatrix{FixedTimestep{2000, 1, 2100}, arrtype, 1}
@test typeof(extpars[:b].values) == TimestepVector{FixedTimestep{2000, 1, 2100}, arrtype}

@test typeof(extpars[:c].values) == Array{arrtype, 1}
@test typeof(extpars[:d].value) == numtype
Expand All @@ -111,7 +111,7 @@ update_param!(m, :e, [4,5,6,7])

@test length(extpars) == 9 # The old dictionary has the default values that were added during build, so it has more entries
@test length(new_extpars) == 6
@test typeof(new_extpars[:a].values) == TimestepMatrix{FixedTimestep{2000, 1}, arrtype, 1}
@test typeof(new_extpars[:a].values) == TimestepMatrix{FixedTimestep{2000, 1, 2100}, arrtype, 1}

@test typeof(new_extpars[:d].value) == numtype
@test typeof(new_extpars[:e].values) == Array{arrtype, 1}
Expand Down Expand Up @@ -141,7 +141,7 @@ set_param!(m, :MyComp2, :x, [1, 2, 3, 4, 5])
set_dimension!(m, :time, 2001:2003)
update_param!(m, :x, [2, 3, 4])
x = external_param(m.md, :x)
@test x.values isa Mimi.TimestepArray{Mimi.FixedTimestep{2001, 1, LAST} where LAST, Union{Missing,Float64}, 1}
@test x.values isa Mimi.TimestepArray{Mimi.FixedTimestep{2001, 1, 2003}, Union{Missing,Float64}, 1}
@test x.values.data == [2., 3., 4.]
run(m)
@test m[:MyComp2, :y][1] == 2 # 2001
Expand Down Expand Up @@ -196,7 +196,7 @@ set_dimension!(m, :time, 1999:2003) # length 5

update_param!(m, :x, [2, 3, 4, 5, 6])
x = external_param(m.md, :x)
@test x.values isa Mimi.TimestepArray{Mimi.FixedTimestep{1999, 1, LAST} where LAST, Union{Missing,Float64}, 1}
@test x.values isa Mimi.TimestepArray{Mimi.FixedTimestep{1999, 1, 2003}, Union{Missing, Float64}, 1, 1}
@test x.values.data == [2., 3., 4., 5., 6.]

run(m)
Expand Down Expand Up @@ -230,7 +230,7 @@ set_dimension!(m, :time, 2005:2007)

update_params!(m, Dict(:x=>[3,4,5], :y=>[10,20], :z=>0)) # Won't error when updating from a dictionary

@test external_param(m.md, :x).values isa Mimi.TimestepArray{Mimi.FixedTimestep{2005,1},Union{Missing,Float64},1}
@test external_param(m.md, :x).values isa Mimi.TimestepArray{Mimi.FixedTimestep{2005,1, 2007},Union{Missing,Float64},1}
@test external_param(m.md, :x).values.data == [3.,4.,5.]
@test external_param(m.md, :y).values == [10.,20.]
@test external_param(m.md, :z).value == 0
Expand Down
4 changes: 2 additions & 2 deletions test/test_show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ Model
param_name: :x
external_param: :x
external_params: Dict{Symbol,ModelParameter}
x => ArrayModelParameter{TimestepArray{FixedTimestep{2000,1,LAST} where LAST,Float64,1}}
values: TimestepArray{FixedTimestep{2000,1,LAST} where LAST,Float64,1}
x => ArrayModelParameter{TimestepArray{FixedTimestep{2000,1,2005},Float64,1}}
values: TimestepArray{FixedTimestep{2000,1,2005},Float64,1}
1: 0.0
2: 0.0
3: 0.0
Expand Down
86 changes: 44 additions & 42 deletions test/test_timesteparrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ idx4 = TimestepIndex(4)
#1a. test constructor, lastindex, and length (with both
# matching years and mismatched years)

x = TimestepVector{FixedTimestep{2000, 1}, Int}([9, 10, 11, 12])
x = TimestepVector{FixedTimestep{2000, 1, 2003}, Int}([9, 10, 11, 12])
@test length(x) == 4
@test lastindex(x) == TimestepIndex(4)

Expand Down Expand Up @@ -80,21 +80,22 @@ reset_time_val(x, time_dim_val)

# AbstractTimestep Indexing
t = FixedTimestep{2001, 1, 3000}(1)

@test hasvalue(x, t)
@test !hasvalue(x, FixedTimestep{2000, 1, 2012}(10))
@test x[t] == 10

t = FixedTimestep{2000, 1, 3000}(1)
@test x[t] == 9 # x

t2 = next_timestep(t)
@test x[t2] == time_dim_val[3]
x[t2] = temp_dim_val[3]
@test x[t2] == temp_dim_val[3]
@test x[t2] == time_dim_val[2]
x[t2] = temp_dim_val[2]
@test x[t2] == temp_dim_val[2]
reset_time_val(x, time_dim_val)

t3 = FixedTimestep{2000, 1, 2003}(1)
@test x[t3] == time_dim_val[1]
x[t3] = temp_dim_val[1]
@test x[t3] == temp_dim_val[1]
t3 = next_timestep(t2)
@test x[t3] == time_dim_val[3]
x[t3] = temp_dim_val[3]
@test x[t3] == temp_dim_val[3]
reset_time_val(x, time_dim_val)

# Deprecated int indexing now errors
Expand Down Expand Up @@ -148,12 +149,12 @@ t = VariableTimestep{y2}()

@test hasvalue(x, t)
@test !hasvalue(x, VariableTimestep{years}(time_dim_val[2]))
@test x[t] == time_dim_val[2]
@test x[t] == time_dim_val[1]

t2 = next_timestep(t)
@test x[t2] == time_dim_val[3]
x[t2] = temp_dim_val[3]
@test x[t2] == temp_dim_val[3]
@test x[t2] == time_dim_val[2]
x[t2] = temp_dim_val[2]
@test x[t2] == temp_dim_val[2]
reset_time_val(x, time_dim_val)

t3 = VariableTimestep{years}()
Expand All @@ -176,8 +177,8 @@ for ti = 1:2
#3a. test constructor (with both matching years
# and mismatched years)

y = TimestepMatrix{FixedTimestep{2000, 1}, Int, ti}(collect(reshape(1:8, 4, 2)))
z = TimestepMatrix{FixedTimestep{2000, 2}, Int, ti}(collect(reshape(1:8, 4, 2)))
y = TimestepMatrix{FixedTimestep{2000, 1, 2003}, Int, ti}(collect(reshape(1:8, 4, 2)))
z = TimestepMatrix{FixedTimestep{2000, 2, 2003}, Int, ti}(collect(reshape(1:8, 4, 2)))

time_dim_val = collect(reshape(1:8, 4, 2))
temp_dim_val = collect(reshape(100:107, 4, 2))
Expand Down Expand Up @@ -239,19 +240,19 @@ for ti = 1:2
@test y[:, TimestepValue(2001)] == time_dim_val[:,2]
@test y[1, TimestepValue(2000; offset = 1)] == time_dim_val[1,2]
@test y[1, TimestepValue(2000) + 1] == time_dim_val[1,2]
@test_throws ErrorException y[1, TimestepValue(2003)]
@test_throws ErrorException y[1, TimestepValue(2002)+1]
@test_throws BoundsError y[1, TimestepValue(2003)]
@test_throws BoundsError y[1, TimestepValue(2002)+1]

y[1, TimestepValue(2000)] = temp_dim_val[1]
@test y[1, TimestepValue(2000)] == temp_dim_val[1]
reset_time_val(y, time_dim_val)
end

# AbstractTimestep Indexing
t = FixedTimestep{2001, 1, 3000}(1)
t = FixedTimestep{2000, 1, 3000}(1)
@test hasvalue(y, t, 1)
@test !hasvalue(y, FixedTimestep{2000, 1, 3000}(10), 1)

t = next_timestep(t)
if ti == 1
@test y[t,1] == time_dim_val[2,1]
@test y[t,2] == time_dim_val[2,2]
Expand All @@ -271,7 +272,7 @@ for ti = 1:2
reset_time_val(y, time_dim_val)

#3c. interval wider than 1 using z from above
t = FixedTimestep{1980, 2, 3000}(11)
t = FixedTimestep{1980, 2, 3000}(1)

@test z[t,1] == time_dim_val[1,1]
@test z[t,2] == time_dim_val[1,2]
Expand All @@ -292,7 +293,7 @@ for ti = 1:2
reset_time_val(y, time_dim_val)

#3c. interval wider than 1 using z from above
t = FixedTimestep{1980, 2, 3000}(11)
t = FixedTimestep{1980, 2, 3000}(1)

@test z[1, t] == time_dim_val[1,1]
@test z[2, t] == time_dim_val[2,1]
Expand Down Expand Up @@ -402,14 +403,16 @@ for ti = 1:2
if ti == 1
@test hasvalue(y, t, time_dim_val[1])
@test !hasvalue(y, VariableTimestep{years}(10))
@test y[t,1] == time_dim_val[2,1]
@test y[t,2] == time_dim_val[2,2]

t2 = next_timestep(t)
@test y[t2,1] == time_dim_val[3,1]
@test y[t2,2] == time_dim_val[3,2]
y[t2, 1] = temp_dim_val[3,1]
@test y[t2, 1] == temp_dim_val[3,1]
@test y[t2,1] == time_dim_val[2,1]
@test y[t2,2] == time_dim_val[2,2]

t3 = next_timestep(t2)
@test y[t3,1] == time_dim_val[3,1]
@test y[t3,2] == time_dim_val[3,2]
y[t3, 1] = temp_dim_val[3,1]
@test y[t3, 1] == temp_dim_val[3,1]
reset_time_val(y, time_dim_val)

t3 = VariableTimestep{years}()
Expand All @@ -422,8 +425,10 @@ for ti = 1:2
else
@test hasvalue(y, t, time_dim_val[1])
@test !hasvalue(y, VariableTimestep{years}(10))
@test y[1,t] == time_dim_val[1,2]
@test y[2,t] == time_dim_val[2,2]

t2 = next_timestep(t)
@test y[1,t2] == time_dim_val[1,2]
@test y[2,t2] == time_dim_val[2,2]

t3 = VariableTimestep{years}()
@test y[1, t3] == time_dim_val[1,1]
Expand All @@ -446,7 +451,7 @@ end
for ti = 1:2

years = Tuple([2000:5:2005; 2015:10:2025])
arr_fixed = TimestepArray{FixedTimestep{2000, 5}, Int, 3, ti}(collect(reshape(1:64, 4, 4, 4)))
arr_fixed = TimestepArray{FixedTimestep{2000, 5, 2020}, Int, 3, ti}(collect(reshape(1:64, 4, 4, 4)))
arr_variable = TimestepArray{VariableTimestep{years}, Int, 3, ti}(collect(reshape(1:64, 4, 4, 4)))

time_dim_val = collect(reshape(1:64, 4, 4, 4))
Expand Down Expand Up @@ -591,8 +596,8 @@ time_dim_val = collect(reshape(1:64, 4, 4, 4))
x_years = Tuple(2000:5:2015) #fixed
y_years = Tuple([2000:5:2005; 2015:10:2025]) #variable

x_vec = TimestepVector{FixedTimestep{2000, 5}, Int}(time_dim_val[:,1,1])
x_mat = TimestepMatrix{FixedTimestep{2000, 5}, Int, 1}(time_dim_val[:,:,1])
x_vec = TimestepVector{FixedTimestep{2000, 5, 2015}, Int}(time_dim_val[:,1,1])
x_mat = TimestepMatrix{FixedTimestep{2000, 5, 2015}, Int, 1}(time_dim_val[:,:,1])
y_vec = TimestepVector{VariableTimestep{y_years}, Int}(time_dim_val[:,2,2])
y_mat = TimestepMatrix{VariableTimestep{y_years}, Int, 1}(time_dim_val[:,:,2])

Expand Down Expand Up @@ -717,11 +722,8 @@ run(m)
# 8. Check broadcast assignment to underlying array
#------------------------------------------------------------------------------

x_arr = zeros(10)
y_arr = collect(reshape(zeros(8), 4, 2))

x = Mimi.TimestepVector{Mimi.FixedTimestep{2005,10}, Float64}(x_arr)
y = TimestepMatrix{FixedTimestep{2000, 1}, Float64, 1}(y_arr)
x = Mimi.TimestepVector{Mimi.FixedTimestep{2005,10}, Float64}(zeros(10))
y = TimestepMatrix{FixedTimestep{2000, 1}, Float64, 1}(collect(reshape(zeros(8), 4, 2)))

# colon and ints
x[:] .= 10
Expand All @@ -732,14 +734,14 @@ y[:] .= 10
y[:,1] .= 20
@test all(y.data[:,1] .== 20)

reset_time_val(x, x_arr)
reset_time_val(y, y_arr)
reset_time_val(x, zeros(10))
reset_time_val(y, collect(reshape(zeros(8), 4, 2)))

# TimestepIndex
y[TimestepIndex(2),:] .= 10
@test all(y.data[2,:] .== 10)

reset_time_val(x, x_arr)
reset_time_val(y, y_arr)
reset_time_val(x, zeros(10))
reset_time_val(y, collect(reshape(zeros(8), 4, 2)))

end #module

0 comments on commit ab3ade7

Please sign in to comment.