Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions docs/src/userguide.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ Any Mimi model is made up of at least one component, so before you construct a m

A component can have any number of parameters and variables. Parameters are data values that will be provided to the component as input, and variables are values that the component will calculate in the `run_timestep` function when the model is run. The index of a parameter or variable determines the number of dimensions that parameter or variable has. They can be scalar values and have no index, such as parameter 'c' in the example below. They can be one-dimensional, such as the variable 'A' and the parameters 'd' and 'f' below. They can be two dimensional such as variable 'B' and parameter 'e' below. Note that any index other than 'time' must be declared at the top of the component, as shown by `regions = Index()` below.

Also note that if a `Variable` or `Parameter` has `time` as an index, it must be listed as the first index in the definition, eg. `B = Variable(index = [time, regions])` is allowed, but `B = Variable(index = [regions, time])` is not.

The user must define a `run_timestep` function for each component.

We define a component in the following way:
Expand Down
8 changes: 5 additions & 3 deletions src/core/build.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,21 @@ function _instance_datatype(md::ModelDef, def::DatumDef)
dims = dimensions(def)
num_dims = dim_count(def)

ti = get_time_index_position(def)

if num_dims == 0
T = ScalarModelParameter{dtype}

elseif dims[1] != :time
elseif ti == nothing # there's no time dimension
T = Array{dtype, num_dims}

else
if isuniform(md)
first, stepsize = first_and_step(md)
T = TimestepArray{FixedTimestep{first, stepsize}, Union{dtype, Missing}, num_dims}
T = TimestepArray{FixedTimestep{first, stepsize}, Union{dtype, Missing}, num_dims, ti}
else
times = time_labels(md)
T = TimestepArray{VariableTimestep{(times...,)}, Union{dtype, Missing}, num_dims}
T = TimestepArray{VariableTimestep{(times...,)}, Union{dtype, Missing}, num_dims, ti}
end
end

Expand Down
13 changes: 8 additions & 5 deletions src/core/connections.jl
Original file line number Diff line number Diff line change
Expand Up @@ -134,16 +134,17 @@ function connect_param!(md::ModelDef,
if dim_count == 0
values = backup
else
ti = get_time_index_position(dst_param)

if isuniform(md)
# use the first from the comp_def not the ModelDef
_, stepsize = first_and_step(md)
values = TimestepArray{FixedTimestep{first, stepsize}, T, dim_count}(backup)
values = TimestepArray{FixedTimestep{first, stepsize}, T, dim_count, ti}(backup)
else
times = time_labels(md)
# use the first from the comp_def
first_index = findfirst(isequal(first), times)
values = TimestepArray{VariableTimestep{(times[first_index:end]...,)}, T, dim_count}(backup)
values = TimestepArray{VariableTimestep{(times[first_index:end]...,)}, T, dim_count, ti}(backup)
end

end
Expand Down Expand Up @@ -293,10 +294,11 @@ end

function set_external_param!(md::ModelDef, name::Symbol, value::Union{AbstractArray, AbstractRange, Tuple};
param_dims::Union{Nothing,Array{Symbol}} = nothing)
if param_dims[1] == :time
ti = get_time_index_position(param_dims)
if ti != nothing
value = convert(Array{md.number_type}, value)
num_dims = length(param_dims)
values = get_timestep_array(md, eltype(value), num_dims, value)
values = get_timestep_array(md, eltype(value), num_dims, ti, value)
else
values = value
end
Expand Down Expand Up @@ -426,7 +428,8 @@ function _update_array_param!(md::ModelDef, name, value, update_timesteps, raise
if param.values isa TimestepArray
T = eltype(value)
N = length(size(value))
new_timestep_array = get_timestep_array(md, T, N, value)
ti = get_time_index_position(param)
new_timestep_array = get_timestep_array(md, T, N, ti, value)
md.external_params[name] = ArrayModelParameter(new_timestep_array, param.dimensions)
elseif raise_error
error("Cannot update timesteps; parameter $name is not a TimestepArray.")
Expand Down
4 changes: 0 additions & 4 deletions src/core/defcomp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -221,10 +221,6 @@ macro defcomp(comp_name, ex)
if !isempty(filter(x -> !(x isa Union{Int,Symbol}), dims))
error("Dimensions ($dims) must be defined by a Symbol placeholder or an Int")
end

if (:time in dims && dims[1] != :time)
error("$elt_type $name: time must be the first dimension ($dims)")
end

append!(dimensions, map(Symbol, dims)) # converts, e.g., 4 into Symbol("4")

Expand Down
18 changes: 10 additions & 8 deletions src/core/defs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -367,23 +367,25 @@ function set_param!(md::ModelDef, comp_name::Symbol, param_name::Symbol, value,
value = convert(Array{dtype, num_dims}, value)
end

if comp_param_dims[1] == :time
ti = get_time_index_position(md, comp_name, param_name)

if ti != nothing # there is a time dimension
T = eltype(value)

if num_dims == 0
if num_dims == 0
values = value
else
# Want to use the first from the comp_def if it has it, if not use ModelDef
first = first_period(md, comp_def)

if isuniform(md)
_, stepsize = first_and_step(md)
values = TimestepArray{FixedTimestep{first, stepsize}, T, num_dims}(value)
values = TimestepArray{FixedTimestep{first, stepsize}, T, num_dims, ti}(value)
else
times = time_labels(md)
#use the first from the comp_def
first_index = findfirst(isequal(first), times)
values = TimestepArray{VariableTimestep{(times[first_index:end]...,)}, T, num_dims}(value)
values = TimestepArray{VariableTimestep{(times[first_index:end]...,)}, T, num_dims, ti}(value)
end
end
else
Expand Down Expand Up @@ -748,12 +750,12 @@ function Base.copy(obj::TimestepVector{T_ts, T}) where {T_ts, T}
return TimestepVector{T_ts, T}(copy(obj.data))
end

function Base.copy(obj::TimestepMatrix{T_ts, T}) where {T_ts, T}
return TimestepMatrix{T_ts, T}(copy(obj.data))
function Base.copy(obj::TimestepMatrix{T_ts, T, ti}) where {T_ts, T, ti}
return TimestepMatrix{T_ts, T, ti}(copy(obj.data))
end

function Base.copy(obj::TimestepArray{T_ts, T, N}) where {T_ts, T, N}
return TimestepArray{T_ts, T, N}(copy(obj.data))
function Base.copy(obj::TimestepArray{T_ts, T, N, ti}) where {T_ts, T, N, ti}
return TimestepArray{T_ts, T, N, ti}(copy(obj.data))
end

"""
Expand Down
Loading