From 542aa030613651558e536ddf1d5e10a2f3d16507 Mon Sep 17 00:00:00 2001 From: lrennels Date: Sat, 20 Feb 2021 02:12:31 -0800 Subject: [PATCH] Add views and break everything --- src/core/build.jl | 28 +++++++--- src/core/dimensions.jl | 12 +++++ src/core/time_arrays.jl | 101 ++++++++++++++++++------------------ src/core/types/time.jl | 9 +++- test/test_components.jl | 5 +- test/test_firstlast.jl | 37 ++++++------- test/test_parametertypes.jl | 17 +++--- test/test_timesteps.jl | 12 +++-- 8 files changed, 130 insertions(+), 91 deletions(-) diff --git a/src/core/build.jl b/src/core/build.jl index e881d314a..7d40348a9 100644 --- a/src/core/build.jl +++ b/src/core/build.jl @@ -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) @@ -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)) @@ -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)) diff --git a/src/core/dimensions.jl b/src/core/dimensions.jl index bac53bad0..ca2f0dbd0 100644 --- a/src/core/dimensions.jl +++ b/src/core/dimensions.jl @@ -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 diff --git a/src/core/time_arrays.jl b/src/core/time_arrays.jl index bc6fb78fc..e3f73c51c 100644 --- a/src/core/time_arrays.jl +++ b/src/core/time_arrays.jl @@ -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) @@ -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} @@ -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 @@ -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 # @@ -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} @@ -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 @@ -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 @@ -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} @@ -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 @@ -509,14 +508,12 @@ 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} @@ -524,6 +521,7 @@ function Base.getindex(arr::TimestepArray{FixedTimestep{FIRST, STEP}, T_data, N, 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 @@ -531,6 +529,7 @@ function Base.getindex(arr::TimestepArray{VariableTimestep{TIMES}, T_data, N, ti _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 @@ -562,14 +561,12 @@ 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} @@ -577,6 +574,7 @@ function Base.setindex!(arr::TimestepArray{FixedTimestep{FIRST, STEP}, T_data, N 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 @@ -584,19 +582,18 @@ function Base.setindex!(arr::TimestepArray{VariableTimestep{TIMES}, T_data, N, t _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 @@ -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 @@ -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 diff --git a/src/core/types/time.jl b/src/core/types/time.jl index 422f86a79..7bdde8183 100644 --- a/src/core/types/time.jl +++ b/src/core/types/time.jl @@ -60,8 +60,15 @@ 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 +# data::S mutable struct TimestepArray{T_TS <: AbstractTimestep, T, N, ti} <: MimiStruct - data::Array{T, N} + data::Union{Array{T, N}, SubArray} + + function TimestepArray{T_TS, T, N, ti}(d::SubArray) where {T_TS, T, N, ti} + return new(d) + end function TimestepArray{T_TS, T, N, ti}(d::Array{T, N}) where {T_TS, T, N, ti} return new(d) diff --git a/test/test_components.jl b/test/test_components.jl index a654b951a..e9951bf63 100644 --- a/test/test_components.jl +++ b/test/test_components.jl @@ -137,7 +137,6 @@ ci = compinstance(m, :C) # Get the component instance m = Model() set_dimension!(m, :time, 2000:2100) - add_comp!(m, testcomp1, :C; first = 2010, last = 2090) cd = compdef(m.md, :C) # Get the component definition in the model @@ -145,14 +144,16 @@ cd = compdef(m.md, :C) # Get the component definition in the model @test cd.last == 2090 set_dimension!(m, :time, 2010:2090) - set_param!(m, :C, :par1, zeros(81)) Mimi.build!(m) # Build the model + ci = compinstance(m, :C) # Get the component instance @test ci.first == 2010 # The component instance's first and last values are the same as in the comp def @test ci.last == 2090 set_dimension!(m, :time, 2000:2200) # Reset the time dimension +update_param!(m, :par1, zeros(201)) # Have to reset the parameter to have the same width as the model time dimension + cd = compdef(m.md, :C) # Get the component definition in the model @test cd.first == 2010 # First and last values should still be the same @test cd.last == 2090 diff --git a/test/test_firstlast.jl b/test/test_firstlast.jl index d8532baa2..5ea74a152 100644 --- a/test/test_firstlast.jl +++ b/test/test_firstlast.jl @@ -73,9 +73,9 @@ run(m) # test that there are missing values in :emissions variables outside of the component's # run period, and no missing values in the :grosseconomy variables -@test ismissing(m[:emissions, :E][1]) -@test ismissing(m[:emissions, :E][20]) -@test sum(ismissing.(m[:emissions, :E][2:19])) == 0 +@test ismissing(m[:emissions, :E].parent[1]) +@test ismissing(m[:emissions, :E].parent[20]) +@test sum(ismissing.(m[:emissions, :E])) == 0 @test sum(ismissing.(m[:grosseconomy, :l])) == 0 # change the model dimension (widen it) @@ -99,9 +99,9 @@ run(m) # test that there are missing values in :emissions variables outside of the component's # run period, and no missing values in the :grosseconomy variables -@test ismissing(m[:emissions, :E][1]) -@test sum(ismissing.(m[:emissions, :E][20:21])) == 2 -@test sum(ismissing.(m[:emissions, :E][2:19])) == 0 +@test ismissing(m[:emissions, :E].parent[1]) +@test sum(ismissing.(m[:emissions, :E].parent[20:21])) == 2 +@test sum(ismissing.(m[:emissions, :E])) == 0 @test sum(ismissing.(m[:grosseconomy, :l])) == 0 # @@ -128,8 +128,8 @@ connect_param!(m, :emissions, :YGROSS, :grosseconomy, :YGROSS) run(m) # neither component should have a value for the first timestep -@test ismissing(m[:emissions, :E][1]) -@test ismissing(m[:grosseconomy, :YGROSS][1]) +@test ismissing(m[:emissions, :E].parent[1]) +@test ismissing(m[:grosseconomy, :YGROSS].parent[1]) # Test bounds - both end early @@ -154,8 +154,8 @@ connect_param!(m, :emissions, :YGROSS, :grosseconomy, :YGROSS) run(m) -@test ismissing(m[:emissions, :E][20]) -@test ismissing(m[:grosseconomy, :YGROSS][20]) +@test ismissing(m[:emissions, :E].parent[20]) +@test ismissing(m[:grosseconomy, :YGROSS].parent[20]) # # Test bounds - components starting or ending before/after the model @@ -207,9 +207,9 @@ set_dimension!(m2, :time, collect(1:10)) add_comp!(m2, MyComp, first = 2, last = 9) run(m2) -@test ismissing(m[:MyComp, :a][1]) -@test ismissing(m[:MyComp, :a][end]) -@test (m[:MyComp, :a])[2:9] == (m2[:MyComp, :a])[2:9] == [-999., 2., 3., 4., 5., 6., 7., 999.] +@test ismissing(m[:MyComp, :a].parent[1]) +@test ismissing(m[:MyComp, :a].parent[end]) +@test (m[:MyComp, :a]) == (m2[:MyComp, :a]) == [-999., 2., 3., 4., 5., 6., 7., 999.] # # TimestepIndex and TimestepValue @@ -231,7 +231,7 @@ add_comp!(m, MyComp, first = 5, last = 10) run(m) for i in collect(1:15) - @test m[:MyComp, :a][i] === m[:MyComp, :b][i] + @test m[:MyComp, :a].parent[i] === m[:MyComp, :b].parent[i] end # TimestepValue: Test Equality - should match up with the time index @@ -250,7 +250,7 @@ add_comp!(m, MyComp, first = 5, last = 10) run(m) for i in collect(1:15) - @test m[:MyComp, :a][i] === m[:MyComp, :b][i] + @test m[:MyComp, :a].parent[i] === m[:MyComp, :b].parent[i] end # TimestepIndex: Test that Get and Set Index are Relative to Component, not Model @@ -286,7 +286,8 @@ for year in collect(1995:1999) add_comp!(m, MyComp, first = year) run(m) idx = year - 1995 + 1 - @test m[:MyComp, :a][idx] == 1.0 + @test m[:MyComp, :a].parent[idx] == 1.0 + @test m[:MyComp, :a][1] == 1.0 end # TimestepValue: Test that Get and Set Index are Relative to Component, not Model @@ -306,7 +307,7 @@ for year in collect(1995:1999) set_dimension!(m, :time, collect(1995:2000)) add_comp!(m, MyComp, first = year) run(m) - @test m[:MyComp, :a][5] == 1.0 + @test m[:MyComp, :a].parent[5] == 1.0 end -end #module \ No newline at end of file +end #module diff --git a/test/test_parametertypes.jl b/test/test_parametertypes.jl index 2e6ffd7c7..101e6f78d 100644 --- a/test/test_parametertypes.jl +++ b/test/test_parametertypes.jl @@ -132,18 +132,17 @@ end # 1. Test with Fixed Timesteps m = Model() -set_dimension!(m, :time, 2000:2002) -add_comp!(m, MyComp2, first=2000, last=2002) -set_param!(m, :MyComp2, :x, [1, 2, 3]) - -set_dimension!(m, :time, 2000:2001) - -set_dimension!(m, :time, 2001:2002) +set_dimension!(m, :time, 2000:2004) +add_comp!(m, MyComp2, first=2001, last=2003) +set_param!(m, :MyComp2, :x, [1, 2, 3, 4, 5]) -update_param!(m, :x, [2, 3]) +@test_throws ErrorException set_dimension!(m, :time, 2002:2004) # model starts after component +@test_throws ErrorException set_dimension!(m, :time, 2000:2002) # model ends before component +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.data == [2., 3.] +@test x.values.data == [2., 3., 4.] run(m) @test m[:MyComp2, :y][1] == 2 # 2001 @test m[:MyComp2, :y][2] == 3 # 2002 diff --git a/test/test_timesteps.jl b/test/test_timesteps.jl index d406fc65d..987cfc3a5 100644 --- a/test/test_timesteps.jl +++ b/test/test_timesteps.jl @@ -150,16 +150,18 @@ set_param!(m, :Bar, :inputB, collect(1:length(years))) run(m) -@test length(m[:Foo, :output]) == length(years) +@test length(m[:Foo, :output].parent) == length(years) +@test length(m[:Bar, :output].parent) == length(years) + +@test length(m[:Foo, :output]) == length(first_foo:years[end]) @test length(m[:Bar, :output]) == length(years) yr_dim = Mimi.Dimension(years) idxs = yr_dim[first_foo]:yr_dim[years[end]] foo_output = m[:Foo, :output] -offset = first_foo - years[1] -for i in idxs - @test foo_output[i] == 5+(i-offset) # incorporate offset into i now because we set ts.t to match component not model +for i in 1:5 + @test foo_output[i] == 5+i end for i in 1:5 @@ -222,7 +224,7 @@ connect_param!(m2, :Foo2, :inputF, :Bar, :output) run(m2) -foo_output2 = m2[:Foo2, :output][yr_dim[first_foo]:yr_dim[years[end]]] +foo_output2 = m2[:Foo2, :output] for i in 1:6 @test foo_output2[i] == (i+5)^2 end