diff --git a/contrib/test_all_models.jl b/contrib/test_all_models.jl index dbf1eccb7..cc039e079 100644 --- a/contrib/test_all_models.jl +++ b/contrib/test_all_models.jl @@ -15,7 +15,7 @@ pkg_that_errored = [] # first set of packages to test packages_to_test = [ - "MimiDICE2010" => ("https://github.com/anthofflab/MimiDICE2010.jl", "master") + "MimiDICE2010" => ("https://github.com/anthofflab/MimiDICE2010.jl", "master"), "MimiDICE2013" => ("https://github.com/anthofflab/MimiDICE2013.jl", "master"), "MimiDICE2016" => ("https://github.com/AlexandrePavlov/MimiDICE2016.jl", "master"), "MimiDICE2016R2" => ("https://github.com/anthofflab/MimiDICE2016R2.jl", "master"), diff --git a/src/core/build.jl b/src/core/build.jl index 18465bbc0..5c380719c 100644 --- a/src/core/build.jl +++ b/src/core/build.jl @@ -261,7 +261,8 @@ function _collect_params(md::ModelDef, var_dict::Dict{ComponentPath, Any}) ipcs = _get_leaf_level_ipcs(md, conn) src_vars = var_dict[ipcs[1].src_comp_path] var_value_obj = get_property_obj(src_vars, ipcs[1].src_var_name) - for ipc in ipcs + for ipc in ipcs + _check_attributes(md, ipc) pdict[(ipc.dst_comp_path, ipc.dst_par_name)] = var_value_obj end end diff --git a/src/core/connections.jl b/src/core/connections.jl index 803cafbea..b4775d3a5 100644 --- a/src/core/connections.jl +++ b/src/core/connections.jl @@ -87,7 +87,7 @@ function _check_attributes(obj::AbstractCompositeComponentDef, if ! isempty(param_dims) && size(param_dims) != size(model_dims) d1 = size(model_dims) d2 = size(param_dims) - error("Mismatched dimensions of parameter connection: Component: $(nameof(comp_def)) Parameter: $param_name ($d2) to Model Parameter ($d1)") + error("Mismatched dimensions of parameter connection: Component: $(nameof(comp_def)) Parameter: $param_name (size $d2) to Model Parameter (size $d1)") end # Don't check sizes for ConnectorComps since they won't match. @@ -108,6 +108,46 @@ function _check_attributes(obj::AbstractCompositeComponentDef, end end +""" + _check_attributes(obj::AbstractCompositeComponentDef, ipc::InternalParameterConnection) + +Check that the dimensions of the source variable match the attributes of the +destination Parameter in InternalParameterConnection `ipc` and an object `obj`. Note +that the names of the dimensions need not match, just the length of dimensions in +the same position. +""" +function _check_attributes(obj::AbstractCompositeComponentDef, ipc::InternalParameterConnection) + + var_def = Mimi.variable(Mimi.find_comp(obj, ipc.src_comp_path), ipc.src_var_name) + param_def = Mimi.parameter(Mimi.find_comp(obj, ipc.dst_comp_path), ipc.dst_par_name) + + param_dims = Mimi.dim_names(param_def) + var_dims = Mimi.dim_names(var_def) + + param_comp_name = nameof(Mimi.find_comp(obj, ipc.dst_comp_path)) + var_comp_name = nameof(Mimi.find_comp(obj, ipc.src_comp_path)) + + if size(param_dims) != size(var_dims) + d1 = size(var_dims) + d2 = size(param_dims) + error("Mismatched dimensions of internal parameter connection: ", + "DESTINATION: Component $(param_comp_name)'s Parameter $(ipc.dst_par_name) (size $d2) ", + "SOURCE: Component $(var_comp_name)'s Variable $(ipc.src_var_name) (size $d1).") + end + + for (i, dim) in enumerate(param_dims) + if isa(dim, Symbol) + param_dim_size = dim_count(obj,dim) + var_dim_size = dim_count(obj, var_dims[i]) + + if param_dim_size != var_dim_size + error("Mismatched data size for internal parameter connection: ", + "dimension :$dim in $(param_comp_name)'s Parameter $(ipc.dst_par_name) has $param_dim_size elements; ", + "while the same positioned (#$i) dimension for $(var_comp_name)'s Variable $(ipc.src_var_name) has $var_dim_size elements.") + end + end + end +end """ _check_attributes(obj::AbstractCompositeComponentDef, comp_def::AbstractComponentDef, param_name::Symbol, diff --git a/test/test_dimensions.jl b/test/test_dimensions.jl index 553b0915a..84702df7b 100644 --- a/test/test_dimensions.jl +++ b/test/test_dimensions.jl @@ -179,4 +179,53 @@ new_x_vals = model_params(m)[:x].values.data @test all(ismissing, new_x_vals[62:end]) run(m) + +# check internal parameter connection dimensions between parameters and variable_years +@defcomp comp1 begin + par1 = Parameter(index=[time]) + var1 = Variable(index=[time]) + function run_timestep(p,v,d,t) + v.var1[t] = p.par1[t] + end +end + +@defcomp comp2 begin + par2 = Parameter(index=[time, country]) + var2 = Variable(index=[time,country]) + function run_timestep(p,v,d,t) + v.var2[t] = p.par2[t] + end +end + +@defcomp comp3 begin + par3 = Parameter(index=[time, town]) + var3 = Variable(index=[time,town]) + function run_timestep(p,v,d,t) + v.var3[t,:] = p.par3[t,:] + end +end + +m = Model() +set_dimension!(m, :time, 2000:2010) +set_dimension!(m, :country, [:A, :B, :C]) +add_comp!(m, comp1) +add_comp!(m, comp2) +set_param!(m, :comp1, :par1, 1:11) +connect_param!(m, :comp2 => :par2, :comp1 => :var1) + +error_msg = (try eval(run(m)) catch err err end).msg +@test occursin("Mismatched dimensions of internal parameter connection", error_msg) + +m = Model() +set_dimension!(m, :time, 2000:2010) +set_dimension!(m, :country, [:A, :B, :C]) +set_dimension!(m, :town, ["a", "b", "c", "d"]) +add_comp!(m, comp2) +add_comp!(m, comp3) +set_param!(m, :comp2, :par2, zeros(11,3)) +connect_param!(m, :comp3 => :par3, :comp2 => :var2) + +error_msg = (try eval(run(m)) catch err err end).msg +@test occursin("Mismatched data size for internal parameter connection", error_msg) + end #module diff --git a/wip/dims_testing.jl b/wip/dims_testing.jl new file mode 100644 index 000000000..556a677db --- /dev/null +++ b/wip/dims_testing.jl @@ -0,0 +1,36 @@ +@defcomp comp1 begin + par1 = Parameter(index=[time]) + var1 = Variable(index=[time]) + + function run_timestep(p,v,d,t) + v.var1[t] = p.par1[t] + end +end + +@defcomp comp2 begin + par2 = Parameter(index=[time, country]) + var2 = Variable(index=[time,country]) + + function run_timestep(p,v,d,t) + v.var2[t] = p.par2[t] + end +end + +@defcomp comp3 begin + par3 = Parameter(index=[time, town]) + var3 = Variable(index=[time,town]) + + function run_timestep(p,v,d,t) + v.var3[t,:] = p.par3[t,:] + end +end + + m = Model() +set_dimension!(m, :time, 2000:2010) +set_dimension!(m, :country, [:A, :B, :C]) +set_dimension!(m, :town, ["a", "b", "c", "d"]) +add_comp!(m, comp2) +add_comp!(m, comp3) +set_param!(m, :comp2, :par2, zeros(11,3)) +connect_param!(m, :comp3 => :par3, :comp2 => :var2) +