Skip to content
Merged
2 changes: 1 addition & 1 deletion docs/src/tutorials/tutorial_1.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ The next step is to run FUND. If you wish to first get more acquainted with the

Now open a julia REPL and type the following command to load the MimiFUND package into the current environment:

```jldoctest tutorial1; output = false
```jldoctest tutorial1; output = false, filter = r".*"s
using MimiFUND

# output
Expand Down
20 changes: 19 additions & 1 deletion docs/src/userguide.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ The API for using the fourth argument, represented as `t` in this explanation, i

To access the data in a parameter or to assign a value to a variable, you must use the appropriate index or indices (in this example, either the Timestep or region or both).

By default, all parameters and variables defined in the `@defcomp` will be allocated storage as scalars or Arrays of type `Float64.` For a description of other data type options, see **Advanced Topics: DataType specification of Parameters and Variables**.

## Constructing a Model

The first step in constructing a model is to set the values for each index of the model. Below is an example for setting the 'time' and 'regions' indexes. The time index expects either a numerical range or an array of numbers. If a single value is provided, say '100', then that index will be set from 1 to 100. Other indexes can have values of any type.
Expand Down Expand Up @@ -248,6 +250,22 @@ TimestepIndex(1):2:TimestepIndex(10) # explicit step of type Int
Both `TimestepIndex` and `TimestepArray` have methods to support addition and subtraction of integers. Note that the addition or subtraction is relative to the definition of the `time` dimension, so while `TimestepIndex(1) + 1 == TimestepIndex(2)`, `TimestepValue(2000) + 1` could be equivalent to `TimestepValue(2001)` **if** 2001 is the next year in the time dimension, or `TimestepValue(2005)` if the array has a step size of 5. Hence adding or subtracting is relative to the definition of the `time` dimension.


### DataType specification of Parameters and Variables

By default, the Parameters and Variables defined by a user will be allocated storage arrays of type `Float64` when a model is constructed. This default "number_type" can be overriden when a model is created, with the following syntax:
```
m = Model(Int64) # creates a model with default number type Int64
```
But you can also specify individual Parameters or Variables to have different data types with the following syntax in a `@defcomp` macro:
```
@defcomp example begin
p1 = Parameter{Bool}() # ScalarModelParameter that is a Bool
p2 = Parameter{Bool}(index = [regions]) # ArrayModelParameter with one dimension whose eltype is Bool
p3 = Parameter{Matrix{Int64}}() # ScalarModelParameter that is a Matrix of Integers
p4 = Parameter{Int64}(index = [time, regions]) # ArrayModelParameter with two dimensions whose eltype is Int64
end
```
If there are "index"s listed in the Parameter definition, then it will be an `ArrayModelParameter` whose `eltype` is the type specified in the curly brackets. If there are no "index"s listed, then the type specified in the curly brackets is the actual type of the parameter value, and it will be represent by Mimi as a `ScalarModelParameter`.

### Parameter connections between different length components

Expand All @@ -270,7 +288,7 @@ As mentioned above, a parameter can have no index (a scalar), or one or multiple
```julia
@defcomp MyComponent begin
p1 = Parameter(index=[4]) # an array of length 4
p2::Array{Float64, 2} = Parameter() # a two dimensional array of unspecified length
p2 = Parameter{Array{Float64, 2}}() # a two dimensional array of unspecified length
end
```

Expand Down
19 changes: 11 additions & 8 deletions src/core/defcomp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ function _generate_var_or_param(elt_type, name, datatype, dimensions, dflt, desc
return expr
end

function _generate_dims_expr(name, args, vartype)
function _generate_dims_expr(name, args, datum_type)
@debug " Index $name"

# Args are not permitted; we attempt capture only to check syntax
Expand All @@ -114,8 +114,8 @@ function _generate_dims_expr(name, args, vartype)
end

# Ditto types for Index, e.g., region::Foo = Index()
if vartype !== nothing
error("Index $name: Type specification ($vartype) is not supported")
if datum_type !== nothing
error("Index $name: Type specification ($datum_type) is not supported")
end

name_expr = (name isa Symbol) ? :($(QuoteNode(name))) : name
Expand Down Expand Up @@ -195,13 +195,16 @@ macro defcomp(comp_name, ex)
continue
end

if ! @capture(elt, (name_::vartype_ | name_) = elt_type_(args__))
error("Element syntax error: $elt")
if @capture(elt, name_::datum_type_ = elt_type_(args__))
msg = "The following syntax has been deprecated in @defcomp: \"$name::$datum_type = $elt_type(...)\". Use curly bracket syntax instead: \"$name = $elt_type{$datum_type}(...)\""
Base.depwarn("$msg\n$(reduce((x,y) -> "$x\n$y", stacktrace()))", :defcomp)
elseif ! @capture(elt, name_ = (elt_type_{datum_type_}(args__) | elt_type_(args__)))
error("Element syntax error: $elt")
end

# elt_type is one of {:Variable, :Parameter, :Index}
if elt_type == :Index
expr = _generate_dims_expr(name, args, vartype)
expr = _generate_dims_expr(name, args, datum_type)
push!(known_dims, name)
addexpr(expr)

Expand Down Expand Up @@ -266,8 +269,8 @@ macro defcomp(comp_name, ex)
end
end

vartype = (vartype === nothing ? Number : Main.eval(vartype))
addexpr(_generate_var_or_param(elt_type, name, vartype, dimensions, dflt, desc, unit))
datum_type = (datum_type === nothing ? Number : Main.eval(datum_type))
addexpr(_generate_var_or_param(elt_type, name, datum_type, dimensions, dflt, desc, unit))

else
error("Unrecognized element type: $elt_type")
Expand Down
2 changes: 1 addition & 1 deletion test/test_explorer_model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import Mimi:
c = Parameter(index=[regions])
d = Parameter()
e = Parameter(index=[four])
f::Array{Float64, 2} = Parameter()
f = Parameter{Array{Float64, 2}}()

x = Variable(index=[time, regions])

Expand Down
4 changes: 2 additions & 2 deletions test/test_main.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Mimi:
index1 = Index()

par1 = Parameter()
par2::Bool = Parameter(index=[time,index1], description="description par 1")
par2 = Parameter{Bool}(index=[time,index1], description="description par 1")
par3 = Parameter(index=[time])

var1 = Variable()
Expand All @@ -21,7 +21,7 @@ import Mimi:

idx3 = Index()
idx4 = Index()
var4::Bool = Variable(index=[idx3])
var4 = Variable{Bool}(index=[idx3])
var5 = Variable(index=[index1, idx4])
end

Expand Down
4 changes: 2 additions & 2 deletions test/test_main_variabletimestep.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Mimi:
index1 = Index()

par1 = Parameter()
par2::Bool = Parameter(index=[time,index1], description="description par 1")
par2 = Parameter{Bool}(index=[time,index1], description="description par 1")
par3 = Parameter(index=[time])

var1 = Variable()
Expand All @@ -21,7 +21,7 @@ import Mimi:

idx3 = Index()
idx4 = Index()
var4::Bool = Variable(index=[idx3])
var4 = Variable{Bool}(index=[idx3])
var5 = Variable(index=[index1, idx4])
end

Expand Down
16 changes: 8 additions & 8 deletions test/test_model_structure.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ import Mimi:
modeldef, modelinstance, compdef, getproperty, setproperty!, dimension, compdefs

@defcomp A begin
varA::Int = Variable(index=[time])
parA::Int = Parameter()
varA = Variable{Int}(index=[time])
parA = Parameter{Int}()

function run_timestep(p, v, d, t)
v.varA[t] = p.parA
end
end

@defcomp B begin
varB::Int = Variable()
varB = Variable{Int}()

function run_timestep(p, v, d, t)
if t.t < 10
Expand All @@ -32,8 +32,8 @@ end
end

@defcomp C begin
varC::Int = Variable()
parC::Int = Parameter()
varC = Variable{Int}()
parC = Parameter{Int}()

function run_timestep(p, v, d, t)
v.varC = p.parC
Expand Down Expand Up @@ -140,9 +140,9 @@ add_comp!(m, D)
##########################################

@defcomp E begin
varE::Int = Variable()
parE1::Int = Parameter()
parE2::Int = Parameter()
varE = Variable{Int}()
parE1 = Parameter{Int}()
parE2 = Parameter{Int}()

function init(p, v, d)
v.varE = p.parE1
Expand Down
10 changes: 5 additions & 5 deletions test/test_model_structure_variabletimestep.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ import Mimi:
dim_names, compdef, getproperty, setproperty!, dimension, compdefs

@defcomp A begin
varA::Int = Variable(index=[time])
parA::Int = Parameter()
varA = Variable{Int}(index=[time])
parA = Parameter{Int}()

function run_timestep(p, v, d, t)
v.varA[t] = p.parA
end
end

@defcomp B begin
varB::Int = Variable()
varB = Variable{Int}()

function run_timestep(p, v, d, t)
if t.t < 10
Expand All @@ -32,8 +32,8 @@ end
end

@defcomp C begin
varC::Int = Variable()
parC::Int = Parameter()
varC = Variable{Int}()
parC = Parameter{Int}()

function run_timestep(p, v, d, t)
v.varC = p.parC
Expand Down
29 changes: 16 additions & 13 deletions test/test_parametertypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,31 @@ expr = :(
)
@test_throws LoadError eval(expr)

#
# Test that the old type parameterization syntax errors
#
expr = :(
@defcomp BadComp3 begin
a::Int = Parameter()
function run_timestep(p, v, d, t)
end
end
)
eval(expr) # Just a deprecation warning for v0.10, then will change to error in v1.0
# @test_throws LoadError eval(expr)


@defcomp MyComp begin
a = Parameter(index=[time, regions], default=ones(101,3))
b = Parameter(index=[time], default=1:101)
c = Parameter(index=[regions])
d = Parameter()
e = Parameter(index=[four])
f::Array{Float64, 2} = Parameter()
g::Int = Parameter(default=10.0) # value should be Int despite Float64 default
f = Parameter{Array{Float64, 2}}()
g = Parameter{Int}(default=10.0) # value should be Int despite Float64 default
h = Parameter(default=10) # should be "numtype", despite Int default

x = Variable(index=[time, regions])

function run_timestep(p, v, d, t)
for r in d.regions
v.x[t, r] = 0
end
end
end

Expand All @@ -59,15 +67,10 @@ set_dimension!(m, :regions, 3)
set_dimension!(m, :four, 4)

add_comp!(m, MyComp)
# set_param!(m, :MyComp, :a, ones(101,3))
# set_param!(m, :MyComp, :b, 1:101)
set_param!(m, :MyComp, :c, [4,5,6])
set_param!(m, :MyComp, :d, 0.5) # 32-bit float constant
set_param!(m, :MyComp, :e, [1,2,3,4])
set_param!(m, :MyComp, :f, [1.0 2.0; 3.0 4.0])

# THIS FAILS: Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}} != Array{Float64,2}
# set_param!(m, :MyComp, :f, reshape(1:16, 4, 4))
set_param!(m, :MyComp, :f, reshape(1:16, 4, 4))

extpars = external_params(m)

Expand Down
2 changes: 1 addition & 1 deletion test/test_replace_comp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ end
end

@defcomp bad4 begin
x::Symbol = Parameter(index = [time]) # different datatype
x = Parameter{Symbol}(index = [time]) # different datatype
y = Variable() # different variable dimensions
end

Expand Down