Skip to content

Commit

Permalink
Add views and break everything
Browse files Browse the repository at this point in the history
  • Loading branch information
lrennels committed Feb 20, 2021
1 parent e0755ca commit 542aa03
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 91 deletions.
28 changes: 22 additions & 6 deletions src/core/build.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
connector_comp_name(i::Int) = Symbol("ConnectorComp$i")

# helper function to substitute views for data
function _substitute_views!(vals::Array{T, N}, comp_def) where {T, N}
times = [keys(comp_def.dim_dict[:time])...]
first_idx = findfirst(times .== comp_def.first)
last_idx = findfirst(times .== comp_def.last)
for (i, val) in enumerate(vals)
# DESIGN DISCUSSION should we deep copy here or can we just do in-place val.data = _get_view(val, first_idx, last_idx)
if val isa TimestepArray
new_val = deepcopy(val)
new_val.data = _get_view(val, first_idx, last_idx)
vals[i] = new_val
end
end
end

function _get_view(val::TimestepArray{T_TS, T, N, ti}, first_idx, last_idx) where {T_TS, T, N, ti}
idxs = Array{Any}(fill(:, N))
idxs[ti] = first_idx:last_idx
return view(val.data, idxs...)
end

# Return the datatype to use for instance variables/parameters
function _instance_datatype(md::ModelDef, def::AbstractDatumDef)
Expand Down Expand Up @@ -71,9 +91,7 @@ function _instantiate_component_vars(md::ModelDef, comp_def::ComponentDef)

names = Symbol[nameof(def) for def in var_defs]
values = Any[_instantiate_datum(md, def) for def in var_defs]
# TODO Loop over content of values, if an element is a TimestepArray, replace it with a new
# TimestepArray that is properly shifted etc, and essentially a view into the original data
# that the TSA here had.
_substitute_views!(values, comp_def)
types = DataType[_instance_datatype(md, def) for def in var_defs]
paths = repeat(Any[comp_def.comp_path], length(names))

Expand Down Expand Up @@ -230,9 +248,7 @@ function _instantiate_params(comp_def::ComponentDef, par_dict::Dict{Tuple{Compon
comp_path = comp_def.comp_path
names = parameter_names(comp_def)
vals = Any[par_dict[(comp_path, name)] for name in names]
# TODO Loop over content of vals, if an element is a TimestepArray, replace it with a new
# TimestepArray that is properly shifted etc, and essentially a view into the original data
# that the TSA here had.
_substitute_views!(vals, comp_def)
types = DataType[typeof(val) for val in vals]
paths = repeat([comp_def.comp_path], length(names))

Expand Down
12 changes: 12 additions & 0 deletions src/core/dimensions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,18 @@ function set_dimension!(ccd::AbstractCompositeComponentDef, name::Symbol, keys::
dim = Dimension(keys)

if name == :time

# check to make sure if we are setting time dimension for the Model that
# it doesn't start after, or end before, any of the components. Note that
# here we can dependent on the invariant that all subcomponents of a composite
# component have the same first and last bounds
ccd_first = [keys...][1]
ccd_last = [keys...][end]
for subcomp in compdefs(ccd)
subcomp.first_free || ccd_first > subcomp.first && error("Top time dimension must end after or at same time as all it's subcomponents, but $(ccd_first) is after $(subcomp.first).")
subcomp.last_free || ccd_last < subcomp.last && error("Top time dimension must start before or at same time as all it's subcomponents, but $(ccd_last) is before $(subcomp.last).")
end

propagate_time!(ccd, dim)
set_uniform!(ccd, isuniform(keys))
end
Expand Down
101 changes: 51 additions & 50 deletions src/core/time_arrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ end
# b. TimestepVector
#

function Base.length(v::TimestepVector)
return length(v.data)
end

function Base.getindex(v::TimestepVector{FixedTimestep{FIRST, STEP}, T}, ts::FixedTimestep{FIRST, STEP, LAST}) where {T, FIRST, STEP, LAST}
data = v.data[ts.t]
_missing_data_check(data, ts.t)
Expand All @@ -179,35 +183,34 @@ function Base.getindex(v::TimestepVector{VariableTimestep{TIMES}, T}, ts::Variab
end

function Base.getindex(v::TimestepVector{FixedTimestep{D_FIRST, STEP}, T}, ts::FixedTimestep{T_FIRST, STEP, LAST}) where {T, D_FIRST, T_FIRST, STEP, LAST}
t = Int(ts.t + (T_FIRST - D_FIRST) / STEP)
data = v.data[t]
_missing_data_check(data, t)
data = v.data[ts.t]
_missing_data_check(data, ts.t)
end

function Base.getindex(v::TimestepVector{VariableTimestep{D_TIMES}, T}, ts::VariableTimestep{T_TIMES}) where {T, D_TIMES, T_TIMES}
t = ts.t + findfirst(isequal(T_TIMES[1]), D_TIMES) - 1
data = v.data[t]
_missing_data_check(data, t)
data = v.data[ts.t]
_missing_data_check(data, ts.t)
end

function Base.getindex(v::TimestepVector{FixedTimestep{FIRST, STEP}, T_data}, ts::TimestepValue{T_time}) where {T_data, FIRST, STEP, T_time}
LAST = FIRST + ((length(v.data)-1) * STEP)
t = _get_time_value_position([FIRST:STEP:LAST...], ts)
t = t - v.data.offset1
data = v.data[t]
_missing_data_check(data, t)
end

function Base.getindex(v::TimestepVector{VariableTimestep{TIMES}, T_data}, ts::TimestepValue{T_time}) where {T_data, TIMES, T_time}
t = _get_time_value_position(TIMES, ts)
t = t - v.data.offset1
data = v.data[t]
_missing_data_check(data, t)
end

function Base.getindex(v::TimestepVector, ts::TimestepIndex)
t = ts.index
_index_bounds_check(v.data, 1, t)
data = v.data[t]
_missing_data_check(data, t)
_index_bounds_check(v.data, 1, ts.index)
data = v.data[ts.index]
_missing_data_check(data, ts.index)
end

function Base.setindex!(v::TimestepVector{FixedTimestep{FIRST, STEP}, T}, val, ts::FixedTimestep{FIRST, STEP, LAST}) where {T, FIRST, STEP, LAST}
Expand All @@ -219,23 +222,23 @@ function Base.setindex!(v::TimestepVector{VariableTimestep{TIMES}, T}, val, ts::
end

function Base.setindex!(v::TimestepVector{FixedTimestep{D_FIRST, STEP}, T}, val, ts::FixedTimestep{T_FIRST, STEP, LAST}) where {T, D_FIRST, T_FIRST, STEP, LAST}
t = Int(ts.t + (T_FIRST - D_FIRST) / STEP)
setindex!(v.data, val, t)
setindex!(v.data, val, ts.t)
end

function Base.setindex!(v::TimestepVector{VariableTimestep{D_TIMES}, T}, val, ts::VariableTimestep{T_TIMES}) where {T, D_TIMES, T_TIMES}
t = ts.t + findfirst(isequal(T_TIMES[1]), D_TIMES) - 1
setindex!(v.data, val, t)
setindex!(v.data, val, ts.t)
end

function Base.setindex!(v::TimestepVector{FixedTimestep{FIRST, STEP}, T_data}, val, ts::TimestepValue{T_time}) where {T_data, FIRST, STEP, T_time}
LAST = FIRST + ((length(v.data)-1) * STEP)
t = _get_time_value_position([FIRST:STEP:LAST...], ts)
t = t - v.data.offset1
setindex!(v.data, val, t)
end

function Base.setindex!(v::TimestepVector{VariableTimestep{TIMES}, T_data}, val, ts::TimestepValue{T_time}) where {T_data, TIMES, T_time}
t = _get_time_value_position(TIMES, ts)
t = t - v.data.offset1
setindex!(v.data, val, t)
end

Expand Down Expand Up @@ -263,10 +266,6 @@ function Base.setindex!(v::TimestepVector{VariableTimestep{TIMES}, T}, val, i::A
_throw_int_setindex_error()
end

function Base.length(v::TimestepVector)
return length(v.data)
end

#
# c. TimestepMatrix
#
Expand All @@ -282,15 +281,13 @@ function Base.getindex(mat::TimestepMatrix{VariableTimestep{TIMES}, T, 1}, ts::V
end

function Base.getindex(mat::TimestepMatrix{FixedTimestep{D_FIRST, STEP}, T, 1}, ts::FixedTimestep{T_FIRST, STEP, LAST}, idx::AnyIndex) where {T, D_FIRST, T_FIRST, STEP, LAST}
t = Int(ts.t + (T_FIRST - D_FIRST) / STEP)
data = mat.data[t, idx]
_missing_data_check(data, t)
data = mat.data[ts.t, idx]
_missing_data_check(data, ts.t)
end

function Base.getindex(mat::TimestepMatrix{VariableTimestep{D_TIMES}, T, 1}, ts::VariableTimestep{T_TIMES}, idx::AnyIndex) where {T, D_TIMES, T_TIMES}
t = ts.t + findfirst(isequal(T_TIMES[1]), D_TIMES) - 1
data = mat.data[t, idx]
_missing_data_check(data, t)
data = mat.data[ts.t, idx]
_missing_data_check(data, ts.t)
end

function Base.getindex(mat::TimestepMatrix{FixedTimestep{FIRST, STEP}, T, 2}, idx::AnyIndex, ts::FixedTimestep{FIRST, STEP, LAST}) where {T, FIRST, STEP, LAST}
Expand All @@ -304,26 +301,26 @@ function Base.getindex(mat::TimestepMatrix{VariableTimestep{TIMES}, T, 2}, idx::
end

function Base.getindex(mat::TimestepMatrix{FixedTimestep{D_FIRST, STEP}, T, 2}, idx::AnyIndex, ts::FixedTimestep{T_FIRST, STEP, LAST}) where {T, D_FIRST, T_FIRST, STEP, LAST}
t = Int(ts.t + (T_FIRST - D_FIRST) / STEP)
data = mat.data[idx, t]
_missing_data_check(data, t)
data = mat.data[idx, ts.t]
_missing_data_check(data, ts.t)
end

function Base.getindex(mat::TimestepMatrix{VariableTimestep{D_TIMES}, T, 2}, idx::AnyIndex, ts::VariableTimestep{T_TIMES}) where {T, D_TIMES, T_TIMES}
t = ts.t + findfirst(isequal(T_TIMES[1]), D_TIMES) - 1
data = mat.data[idx, t]
_missing_data_check(data, t)
data = mat.data[idx, ts.t]
_missing_data_check(data, ts.t)
end

function Base.getindex(mat::TimestepMatrix{FixedTimestep{FIRST, STEP}, T_data, 1}, ts::TimestepValue{T_time}, idx::AnyIndex) where {T_data, FIRST, STEP, T_time}
LAST = FIRST + ((size(mat.data, 1) - 1) * STEP)
t = _get_time_value_position([FIRST:STEP:LAST...], ts)
t = t - mat.data.indices[1][1] + 1
data = mat.data[t, idx]
_missing_data_check(data, t)
end

function Base.getindex(mat::TimestepMatrix{VariableTimestep{TIMES}, T_data, 1}, ts::TimestepValue{T_time}, idx::AnyIndex) where {T_data, TIMES, T_time}
t = _get_time_value_position(TIMES, ts)
t = t - mat.data.indices[1][1] + 1
data = mat.data[t, idx]
_missing_data_check(data, t)
end
Expand All @@ -338,12 +335,14 @@ end
function Base.getindex(mat::TimestepMatrix{FixedTimestep{FIRST, STEP}, T_data, 2}, idx::AnyIndex, ts::TimestepValue{T_time}) where {T_data, FIRST, STEP, T_time}
LAST = FIRST + ((size(mat.data, 2) - 1) * STEP)
t = _get_time_value_position([FIRST:STEP:LAST...], ts)
t = t - mat.data.indices[2][1] + 1
data = mat.data[idx, t]
_missing_data_check(data, t)
end

function Base.getindex(mat::TimestepMatrix{VariableTimestep{TIMES}, T_data, 2}, idx::AnyIndex, ts::TimestepValue{T_time}) where {T_data, TIMES, T_time}
t = _get_time_value_position(TIMES, ts)
t = t - mat.data.indices[2][1] + 1
data = mat.data[idx, t]
_missing_data_check(data, t)
end
Expand All @@ -364,13 +363,11 @@ function Base.setindex!(mat::TimestepMatrix{VariableTimestep{TIMES}, T, 1}, val,
end

function Base.setindex!(mat::TimestepMatrix{FixedTimestep{D_FIRST, STEP}, T, 1}, val, ts::FixedTimestep{T_FIRST, STEP, LAST}, idx::AnyIndex) where {T, D_FIRST, T_FIRST, STEP, LAST}
t = Int(ts.t + (T_FIRST - D_FIRST) / STEP)
setindex!(mat.data, val, t, idx)
setindex!(mat.data, val, ts.t, idx)
end

function Base.setindex!(mat::TimestepMatrix{VariableTimestep{D_TIMES}, T, 1}, val, ts::VariableTimestep{T_TIMES}, idx::AnyIndex) where {T, D_TIMES, T_TIMES}
t = ts.t + findfirst(isequal(T_TIMES[1]), D_TIMES) - 1
setindex!(mat.data, val, t, idx)
setindex!(mat.data, val, ts.t, idx)
end

function Base.setindex!(mat::TimestepMatrix{FixedTimestep{FIRST, STEP}, T, 2}, val, idx::AnyIndex, ts::FixedTimestep{FIRST, STEP, LAST}) where {T, FIRST, STEP, LAST}
Expand All @@ -382,34 +379,36 @@ function Base.setindex!(mat::TimestepMatrix{VariableTimestep{TIMES}, T, 2}, val,
end

function Base.setindex!(mat::TimestepMatrix{FixedTimestep{D_FIRST, STEP}, T, 2}, val, idx::AnyIndex, ts::FixedTimestep{T_FIRST, STEP, LAST}) where {T, D_FIRST, T_FIRST, STEP, LAST}
t = Int(ts.t + (T_FIRST - D_FIRST) / STEP)
setindex!(mat.data, val, idx, t)
setindex!(mat.data, val, ts.t, idx)
end

function Base.setindex!(mat::TimestepMatrix{VariableTimestep{D_TIMES}, T, 2}, val, idx::AnyIndex, ts::VariableTimestep{T_TIMES}) where {T, D_TIMES, T_TIMES}
t = ts.t + findfirst(isequal(T_TIMES[1]), D_TIMES) - 1
setindex!(mat.data, val, idx, t)
setindex!(mat.data, val, ts.t, idx)
end

function Base.setindex!(mat::TimestepMatrix{FixedTimestep{FIRST, STEP}, T_data, 1}, val, ts::TimestepValue{T_time}, idx::AnyIndex) where {T_data, FIRST, STEP, T_time}
LAST = FIRST + ((size(mat.data, 1) - 1) * STEP)
t = _get_time_value_position([FIRST:STEP:LAST...], ts)
t = t - mat.data.indices[1][1] + 1
setindex!(mat.data, val, t, idx)
end

function Base.setindex!(mat::TimestepMatrix{VariableTimestep{TIMES}, T_data, 1}, val, ts::TimestepValue{T_time}, idx::AnyIndex) where {T_data, TIMES, T_time}
t = _get_time_value_position(TIMES, ts)
t = t - mat.data.indices[1][1] + 1
setindex!(mat.data, val, t, idx)
end

function Base.setindex!(mat::TimestepMatrix{FixedTimestep{FIRST, STEP}, T_data, 2}, val, idx::AnyIndex, ts::TimestepValue{T_time}) where {T_data, FIRST, STEP, T_time}
LAST = FIRST + ((size(mat.data, 1) - 1) * STEP)
t = _get_time_value_position([FIRST:STEP:LAST...], ts)
t = t - mat.data.indices[2][1] + 1
setindex!(mat.data, val, idx, t)
end

function Base.setindex!(mat::TimestepMatrix{VariableTimestep{TIMES}, T_data, 2}, val, idx::AnyIndex, ts::TimestepValue{T_time}) where {T_data, TIMES, T_time}
t = _get_time_value_position(TIMES, ts)
t = t - mat.data.indices[2][1] + 1
setindex!(mat.data, val, idx, t)
end

Expand Down Expand Up @@ -509,28 +508,28 @@ end

function Base.getindex(arr::TimestepArray{FixedTimestep{D_FIRST, STEP}, T, N, ti}, idxs::Union{FixedTimestep{T_FIRST, STEP, LAST}, AnyIndex}...) where {T, N, ti, D_FIRST, T_FIRST, STEP, LAST}
idxs1, ts, idxs2 = split_indices(idxs, ti)
t = Int(ts.t + (FIRST - TIMES[1]) / STEP)
return arr.data[idxs1..., t, idxs2...]
return arr.data[idxs1..., ts.t, idxs2...]
end

function Base.getindex(arr::TimestepArray{VariableTimestep{D_TIMES}, T, N, ti}, idxs::Union{VariableTimestep{T_TIMES}, AnyIndex}...) where {T, N, ti, D_TIMES, T_TIMES}
idxs1, ts, idxs2 = split_indices(idxs, ti)
t = ts.t + findfirst(isequal(T_TIMES[1]), D_TIMES) - 1
return arr.data[idxs1..., t, idxs2...]
return arr.data[idxs1..., ts.t, idxs2...]
end

function Base.getindex(arr::TimestepArray{FixedTimestep{FIRST, STEP}, T_data, N, ti}, idxs::Union{TimestepValue{T_time}, AnyIndex}...) where {T_data, N, ti, FIRST, STEP, T_time}
_single_index_check(arr.data, idxs)
idxs1, ts, idxs2 = split_indices(idxs, ti)
LAST = FIRST + ((size(arr.data, ti) - 1) * STEP)
t = _get_time_value_position([FIRST:STEP:LAST...], ts)
t = t - arr.data.indices[ti][1] + 1
return arr.data[idxs1..., t, idxs2...]
end

function Base.getindex(arr::TimestepArray{VariableTimestep{TIMES}, T_data, N, ti}, idxs::Union{TimestepValue{T_time}, AnyIndex}...) where {T_data, N, ti, TIMES, T_time}
_single_index_check(arr.data, idxs)
idxs1, ts, idxs2 = split_indices(idxs, ti)
t = _get_time_value_position(TIMES, ts)
t = t - arr.data.indices[ti][1] + 1
return arr.data[idxs1..., t, idxs2...]
end

Expand Down Expand Up @@ -562,41 +561,39 @@ end

function Base.setindex!(arr::TimestepArray{FixedTimestep{D_FIRST, STEP}, T, N, ti}, val, idxs::Union{FixedTimestep{T_FIRST, STEP, LAST}, AnyIndex}...) where {T, N, ti, D_FIRST, T_FIRST, STEP, LAST}
idxs1, ts, idxs2 = split_indices(idxs, ti)
t = ts.t + findfirst(isequal(T_FIRST[1]), D_FIRST) - 1
setindex!(arr.data, val, idxs1..., t, idxs2...)
setindex!(arr.data, val, idxs1..., ts.t, idxs2...)
end

function Base.setindex!(arr::TimestepArray{VariableTimestep{D_TIMES}, T, N, ti}, val, idxs::Union{VariableTimestep{T_TIMES}, AnyIndex}...) where {T, N, ti, D_TIMES, T_TIMES}
idxs1, ts, idxs2 = split_indices(idxs, ti)
t = ts.t + findfirst(isequal(T_FIRST[1]), T_TIMES) - 1
setindex!(arr.data, val, idxs1..., t, idxs2...)
setindex!(arr.data, val, idxs1..., ts.t, idxs2...)
end

function Base.setindex!(arr::TimestepArray{FixedTimestep{FIRST, STEP}, T_data, N, ti}, val, idxs::Union{TimestepValue{T_time}, AnyIndex}...) where {T_data, N, ti, FIRST, STEP, T_time}
_single_index_check(arr.data, idxs)
idxs1, ts, idxs2 = split_indices(idxs, ti)
LAST = FIRST + ((size(arr.data, ti) - 1) * STEP)
t = _get_time_value_position([FIRST:STEP:LAST...], ts)
t = t - arr.data[ti][1] + 1
setindex!(arr.data, val, idxs1..., t, idxs2...)
end

function Base.setindex!(arr::TimestepArray{VariableTimestep{TIMES}, T_data, N, ti}, val, idxs::Union{TimestepValue{T_time}, AnyIndex}...) where {T_data, N, ti, TIMES, T_time}
_single_index_check(arr.data, idxs)
idxs1, ts, idxs2 = split_indices(idxs, ti)
t = _get_time_value_position(TIMES, ts)
t = t - arr.data[ti][1] + 1
setindex!(arr.data, val, idxs1..., t, idxs2...)
end

function Base.setindex!(arr::TimestepArray{FixedTimestep{FIRST, STEP}, T, N, ti}, val, idxs::Union{TimestepIndex, AnyIndex}...) where {T, N, ti, FIRST, STEP}
idxs1, ts, idxs2 = split_indices(idxs, ti)
t = ts.index
setindex!(arr.data, val, idxs1..., t, idxs2...)
setindex!(arr.data, val, idxs1..., ts.index, idxs2...)
end

function Base.setindex!(arr::TimestepArray{VariableTimestep{TIMES}, T, N, ti}, val, idxs::Union{TimestepIndex, AnyIndex}...) where {T, N, ti, TIMES}
idxs1, ts, idxs2 = split_indices(idxs, ti)
t = ts.index
setindex!(arr.data, val, idxs1..., t, idxs2...)
setindex!(arr.data, val, idxs1..., ts.index, idxs2...)
end

# DEPRECATION - EVENTUALLY REMOVE
Expand Down Expand Up @@ -632,12 +629,14 @@ function Base.getindex(arr::TimestepArray{FixedTimestep{FIRST, STEP}, T_data, N,
idxs1, ts_array, idxs2 = split_indices(idxs, ti)
LAST = FIRST + ((length(arr.data)-1) * STEP)
ts_idxs = _get_ts_indices(ts_array, [FIRST:STEP:LAST...])
ts_idxs = ts_idxs .- arr.data.indices[ti][1] + 1
return arr.data[idxs1..., ts_idxs, idxs2...]
end

function Base.getindex(arr::TimestepArray{VariableTimestep{TIMES}, T_data, N, ti}, idxs::Union{Array{TimestepValue{T_times},1}, AnyIndex}...) where {T_data, N, ti, TIMES, T_times}
idxs1, ts_array, idxs2 = split_indices(idxs, ti)
ts_idxs = _get_ts_indices(ts_array, TIMES)
ts_idxs = ts_idxs .- arr.data.indices[ti][1] + 1
return arr.data[idxs1..., ts_idxs, idxs2...]
end

Expand All @@ -651,12 +650,14 @@ function Base.setindex!(arr::TimestepArray{FixedTimestep{FIRST, STEP}, T_data, N
idxs1, ts_array, idxs2 = split_indices(idxs, ti)
LAST = FIRST + ((length(arr.data)-1) * STEP)
ts_idxs = _get_ts_indices(ts_array, [FIRST:STEP:LAST...])
ts_idxs = ts_idxs .- arr.data.indices[ti][1] + 1
setindex!(arr.data, vals, idxs1..., ts_idxs, idxs2...)
end

function Base.setindex!(arr::TimestepArray{VariableTimestep{TIMES}, T_data, N, ti}, vals, idxs::Union{Array{TimestepValue{T_times},1}, AnyIndex}...) where {T_data, N, ti, TIMES, T_times}
idxs1, ts_array, idxs2 = split_indices(idxs, ti)
ts_idxs = _get_ts_indices(ts_array, TIMES)
ts_idxs = ts_idxs .- arr.data.indices[ti][1] + 1
setindex!(arr.data, vals, idxs1..., ts_idxs, idxs2...)
end

Expand Down
Loading

0 comments on commit 542aa03

Please sign in to comment.