From c3fcfe65f879092d8868f36adc9ac31a447dcd07 Mon Sep 17 00:00:00 2001 From: lrennels Date: Tue, 3 Nov 2020 19:56:05 -0800 Subject: [PATCH 01/16] Support broadcasting in defsim --- src/mcs/montecarlo.jl | 51 ++++++++++++++++++++++++++++- wip/test.jl | 76 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 wip/test.jl diff --git a/src/mcs/montecarlo.jl b/src/mcs/montecarlo.jl index 1803a468e..1d69d683a 100644 --- a/src/mcs/montecarlo.jl +++ b/src/mcs/montecarlo.jl @@ -326,8 +326,11 @@ function _perturb_param!(param::ScalarModelParameter{T}, md::ModelDef, trans::Tr end end +# rvalue is an Array so we expect the dims to match and don't need to worry about +# broadcasting function _perturb_param!(param::ArrayModelParameter{T}, md::ModelDef, - trans::TransformSpec, rvalue::Union{Number, Array{<: Number, N}}) where {T, N} + trans::TransformSpec, rvalue::Array{<: Number, N}) where {T, N} + op = trans.op pvalue = value(param) indices = _param_indices(param, md, trans) @@ -340,6 +343,52 @@ function _perturb_param!(param::ArrayModelParameter{T}, md::ModelDef, else pvalue[indices...] += rvalue + + end +end + +# rvalue is a Number so we need to deal with broadcasting +function _perturb_param!(param::ArrayModelParameter{T}, md::ModelDef, + trans::TransformSpec, rvalue::Number) where {T, N} + op = trans.op + pvalue = value(param) + indices = _param_indices(param, md, trans) + + if op == :(*=) + pvalue[indices...] *= rvalue + + elseif op == :(+=) + pvalue[indices...] += rvalue + + else # op is = + _perturb_param_recurse!(pvalue, indices, rvalue) + + end + +end + +# special case of op == :(=) and rvalue is a Number: recurse throught the indices using +# two cases (split into methods for speed?): +# BASE CASE: the index is not an array +# RECURSIVE CASE: the index is an array, need to iterate through it +# +# NOTE: currently we have a clumsy try-catch because somestimes an array is appropriate +# ie. when there are more than one dimension to the parameter) +function _perturb_param_recurse!(pvalue, indices, rvalue) + + if isa(indices, Array) + try + pvalue[indices...] = rvalue + + catch + foreach(indices) do i + _perturb_param_recurse!(pvalue, i, rvalue) + end + + end + else + pvalue[indices] = rvalue + end end diff --git a/wip/test.jl b/wip/test.jl new file mode 100644 index 000000000..44fb43318 --- /dev/null +++ b/wip/test.jl @@ -0,0 +1,76 @@ +using Mimi +using Distributions + +@defcomp grosseconomy begin + YGROSS = Variable(index=[time]) # Gross output + K = Variable(index=[time]) # Capital + l = Parameter(index=[time]) # Labor + tfp = Parameter(index=[time]) # Total factor productivity + s = Parameter(index=[time]) # Savings rate + depk = Parameter() # Depreciation rate on capital - Note that it has no time index + k0 = Parameter() # Initial level of capital + share = Parameter() # Capital share + + function run_timestep(p, v, d, t) + # Define an equation for K + if is_first(t) + # Note the use of v. and p. to distinguish between variables and parameters + v.K[t] = p.k0 + else + v.K[t] = (1 - p.depk)^5 * v.K[t-1] + v.YGROSS[t-1] * p.s[t-1] * 5 + end + + # Define an equation for YGROSS + v.YGROSS[t] = p.tfp[t] * v.K[t]^p.share * p.l[t]^(1-p.share) + end +end + +@defcomp emissions begin + E = Variable(index=[time]) # Total greenhouse gas emissions + sigma = Parameter(index=[time]) # Emissions output ratio + YGROSS = Parameter(index=[time]) # Gross output - Note that YGROSS is now a parameter + + function run_timestep(p, v, d, t) + + # Define an equation for E + v.E[t] = p.YGROSS[t] * p.sigma[t] # Note the p. in front of YGROSS + end +end + +function construct_model() + m = Model() + + set_dimension!(m, :time, collect(2015:5:2110)) + + # Order matters here. If the emissions component were defined first, the model would not run. + add_comp!(m, grosseconomy) + add_comp!(m, emissions) + + # Set parameters for the grosseconomy component + set_param!(m, :grosseconomy, :l, [(1. + 0.015)^t *6404 for t in 1:20]) + set_param!(m, :grosseconomy, :tfp, [(1 + 0.065)^t * 3.57 for t in 1:20]) + set_param!(m, :grosseconomy, :s, ones(20).* 0.22) + set_param!(m, :grosseconomy, :depk, 0.1) + set_param!(m, :grosseconomy, :k0, 130.) + set_param!(m, :grosseconomy, :share, 0.3) + + # Set parameters for the emissions component + set_param!(m, :emissions, :sigma, [(1. - 0.05)^t *0.58 for t in 1:20]) + connect_param!(m, :emissions, :YGROSS, :grosseconomy, :YGROSS) + # Note that connect_param! was used here. + + return m + +end #end function + +# Run model +m = construct_model() +run(m) + +sd = @defsim begin + # assign RVs to model Parameters + share = Uniform(0.2, 0.8) + s[2015:5:2050] = Uniform(0.2, 0.3) +end + +si = run(sd, m, 10) From c8bc65e6a7ca30832aa3c6ab28cd2a04f79c91f3 Mon Sep 17 00:00:00 2001 From: lrennels Date: Tue, 3 Nov 2020 19:59:07 -0800 Subject: [PATCH 02/16] Clean up --- src/mcs/montecarlo.jl | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/mcs/montecarlo.jl b/src/mcs/montecarlo.jl index 1d69d683a..06c558ec0 100644 --- a/src/mcs/montecarlo.jl +++ b/src/mcs/montecarlo.jl @@ -354,17 +354,15 @@ function _perturb_param!(param::ArrayModelParameter{T}, md::ModelDef, pvalue = value(param) indices = _param_indices(param, md, trans) - if op == :(*=) + if op == :(=) + _perturb_param_recurse!(pvalue, indices, rvalue) + + elseif op == :(*=) pvalue[indices...] *= rvalue - elseif op == :(+=) + else pvalue[indices...] += rvalue - else # op is = - _perturb_param_recurse!(pvalue, indices, rvalue) - - end - end # special case of op == :(=) and rvalue is a Number: recurse throught the indices using From 7e84adfb853c349e0c9080aee434a94b0cd0e1b3 Mon Sep 17 00:00:00 2001 From: lrennels Date: Tue, 3 Nov 2020 20:13:51 -0800 Subject: [PATCH 03/16] Fix end bug --- src/mcs/montecarlo.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mcs/montecarlo.jl b/src/mcs/montecarlo.jl index 06c558ec0..f058b8b3a 100644 --- a/src/mcs/montecarlo.jl +++ b/src/mcs/montecarlo.jl @@ -362,7 +362,7 @@ function _perturb_param!(param::ArrayModelParameter{T}, md::ModelDef, else pvalue[indices...] += rvalue - + end end # special case of op == :(=) and rvalue is a Number: recurse throught the indices using From fdb336cb832ab0e2df433307bbc82ea72a3ea72b Mon Sep 17 00:00:00 2001 From: lrennels Date: Wed, 4 Nov 2020 10:41:30 -0800 Subject: [PATCH 04/16] Add tests and work on bugs --- src/mcs/montecarlo.jl | 38 +++++++++++++++++++------------------- test/mcs/test_defmcs.jl | 16 ++++++++++++++++ 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/mcs/montecarlo.jl b/src/mcs/montecarlo.jl index f058b8b3a..a2a25f140 100644 --- a/src/mcs/montecarlo.jl +++ b/src/mcs/montecarlo.jl @@ -347,7 +347,7 @@ function _perturb_param!(param::ArrayModelParameter{T}, md::ModelDef, end end -# rvalue is a Number so we need to deal with broadcasting +# rvalue is a Number so we might need to deal with broadcasting function _perturb_param!(param::ArrayModelParameter{T}, md::ModelDef, trans::TransformSpec, rvalue::Number) where {T, N} op = trans.op @@ -355,7 +355,11 @@ function _perturb_param!(param::ArrayModelParameter{T}, md::ModelDef, indices = _param_indices(param, md, trans) if op == :(=) - _perturb_param_recurse!(pvalue, indices, rvalue) + + # if there is no time index, we can do a normal broadcast with .= and if not + # we will need to loop through and be fancy + ti = get_time_index_position(param) + isnothing(ti) ? pvalue[indices...] .= rvalue : _perturb_param_handle_ti!(pvalue, indices, rvalue, ti) elseif op == :(*=) pvalue[indices...] *= rvalue @@ -365,28 +369,24 @@ function _perturb_param!(param::ArrayModelParameter{T}, md::ModelDef, end end -# special case of op == :(=) and rvalue is a Number: recurse throught the indices using -# two cases (split into methods for speed?): -# BASE CASE: the index is not an array -# RECURSIVE CASE: the index is an array, need to iterate through it -# -# NOTE: currently we have a clumsy try-catch because somestimes an array is appropriate -# ie. when there are more than one dimension to the parameter) -function _perturb_param_recurse!(pvalue, indices, rvalue) +# special case where we might need to loop through the time indices +function _perturb_param_handle_ti!(pvalue, indices, rvalue, ti) - if isa(indices, Array) - try - pvalue[indices...] = rvalue + indices1, ts, indices2 = split_indices(indices, ti) - catch - foreach(indices) do i - _perturb_param_recurse!(pvalue, i, rvalue) - end + # if the length of indices is just 1, then we won't need to use the broadcast + # operator + l = length(indices) + # array of timestep indices so need to loop through them + if isa(ts, Array) + for el in ts + l == 1 ? pvalue[indices1..., el, indices2...] = rvalue : pvalue[indices1..., el, indices2...] .= rvalue end - else - pvalue[indices] = rvalue + # just a single timestep index so proceed as usual + else + l == 1 ? pvalue[indices...] = rvalue : pvalue[indices...] .= rvalue end end diff --git a/test/mcs/test_defmcs.jl b/test/mcs/test_defmcs.jl index 87477eb6b..b4cdaf716 100644 --- a/test/mcs/test_defmcs.jl +++ b/test/mcs/test_defmcs.jl @@ -269,3 +269,19 @@ trial2 = copy(si2.sim_def.rvdict[:name1].dist.values) @test length(trial1) == length(trial2) @test trial1 != trial2 + +# test broadcasting examples with = +sd3 = @defsim begin + + # 1 dimension - these work + depk[:] = Uniform(0.1, 0.2) + k0[(Region2, Region3)] = Uniform(20, 30) + + # 2 dimensions + tfp[:, Region1] = Uniform(0.75, 1.25) + sigma[2020:5:2050, (Region2, Region3)] = Uniform(0.8, 1.2) + s[2020, :] = Uniform(0.2, 0.3) + +end + +si3 = run(sd3, m, N) From 87d5997bc24881975c91c66d0597c48910239598 Mon Sep 17 00:00:00 2001 From: lrennels Date: Wed, 4 Nov 2020 11:22:58 -0800 Subject: [PATCH 05/16] Fix bugs with try catch --- src/mcs/montecarlo.jl | 27 ++++++++++++++++++++------- test/mcs/test_defmcs.jl | 2 +- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/mcs/montecarlo.jl b/src/mcs/montecarlo.jl index a2a25f140..e4ccbfc26 100644 --- a/src/mcs/montecarlo.jl +++ b/src/mcs/montecarlo.jl @@ -359,7 +359,16 @@ function _perturb_param!(param::ArrayModelParameter{T}, md::ModelDef, # if there is no time index, we can do a normal broadcast with .= and if not # we will need to loop through and be fancy ti = get_time_index_position(param) - isnothing(ti) ? pvalue[indices...] .= rvalue : _perturb_param_handle_ti!(pvalue, indices, rvalue, ti) + + if isnothing(ti) + try + pvalue[indices...] = rvalue + catch + pvalue[indices...] .= rvalue + end + else + _perturb_param_handle_ti!(pvalue, indices, rvalue, ti) + end elseif op == :(*=) pvalue[indices...] *= rvalue @@ -374,19 +383,23 @@ function _perturb_param_handle_ti!(pvalue, indices, rvalue, ti) indices1, ts, indices2 = split_indices(indices, ti) - # if the length of indices is just 1, then we won't need to use the broadcast - # operator - l = length(indices) - # array of timestep indices so need to loop through them if isa(ts, Array) for el in ts - l == 1 ? pvalue[indices1..., el, indices2...] = rvalue : pvalue[indices1..., el, indices2...] .= rvalue + try + pvalue[indices1..., el, indices2...] = rvalue + catch + pvalue[indices1..., el, indices2...] .= rvalue + end end # just a single timestep index so proceed as usual else - l == 1 ? pvalue[indices...] = rvalue : pvalue[indices...] .= rvalue + try + pvalue[indices...] = rvalue + catch + pvalue[indices...] .= rvalue + end end end diff --git a/test/mcs/test_defmcs.jl b/test/mcs/test_defmcs.jl index b4cdaf716..b3d651700 100644 --- a/test/mcs/test_defmcs.jl +++ b/test/mcs/test_defmcs.jl @@ -273,7 +273,7 @@ trial2 = copy(si2.sim_def.rvdict[:name1].dist.values) # test broadcasting examples with = sd3 = @defsim begin - # 1 dimension - these work + # 1 dimension depk[:] = Uniform(0.1, 0.2) k0[(Region2, Region3)] = Uniform(20, 30) From 1863187555babbbb5b753cecc8a720fce9595149 Mon Sep 17 00:00:00 2001 From: lrennels Date: Wed, 4 Nov 2020 11:40:51 -0800 Subject: [PATCH 06/16] All tests passing --- test/mcs/test_defmcs.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/mcs/test_defmcs.jl b/test/mcs/test_defmcs.jl index b3d651700..d956f3ee5 100644 --- a/test/mcs/test_defmcs.jl +++ b/test/mcs/test_defmcs.jl @@ -270,7 +270,7 @@ trial2 = copy(si2.sim_def.rvdict[:name1].dist.values) @test length(trial1) == length(trial2) @test trial1 != trial2 -# test broadcasting examples with = +# test potential broadcasting examples sd3 = @defsim begin # 1 dimension @@ -280,8 +280,9 @@ sd3 = @defsim begin # 2 dimensions tfp[:, Region1] = Uniform(0.75, 1.25) sigma[2020:5:2050, (Region2, Region3)] = Uniform(0.8, 1.2) - s[2020, :] = Uniform(0.2, 0.3) - + s[2020, Region1] = Uniform(0.2, 0.3) + end +N = 5 si3 = run(sd3, m, N) From 113b609a61e450078d54aebe043db97612e3e933 Mon Sep 17 00:00:00 2001 From: lrennels Date: Thu, 5 Nov 2020 13:26:54 -0800 Subject: [PATCH 07/16] Remove test file --- wip/test.jl | 76 ----------------------------------------------------- 1 file changed, 76 deletions(-) delete mode 100644 wip/test.jl diff --git a/wip/test.jl b/wip/test.jl deleted file mode 100644 index 44fb43318..000000000 --- a/wip/test.jl +++ /dev/null @@ -1,76 +0,0 @@ -using Mimi -using Distributions - -@defcomp grosseconomy begin - YGROSS = Variable(index=[time]) # Gross output - K = Variable(index=[time]) # Capital - l = Parameter(index=[time]) # Labor - tfp = Parameter(index=[time]) # Total factor productivity - s = Parameter(index=[time]) # Savings rate - depk = Parameter() # Depreciation rate on capital - Note that it has no time index - k0 = Parameter() # Initial level of capital - share = Parameter() # Capital share - - function run_timestep(p, v, d, t) - # Define an equation for K - if is_first(t) - # Note the use of v. and p. to distinguish between variables and parameters - v.K[t] = p.k0 - else - v.K[t] = (1 - p.depk)^5 * v.K[t-1] + v.YGROSS[t-1] * p.s[t-1] * 5 - end - - # Define an equation for YGROSS - v.YGROSS[t] = p.tfp[t] * v.K[t]^p.share * p.l[t]^(1-p.share) - end -end - -@defcomp emissions begin - E = Variable(index=[time]) # Total greenhouse gas emissions - sigma = Parameter(index=[time]) # Emissions output ratio - YGROSS = Parameter(index=[time]) # Gross output - Note that YGROSS is now a parameter - - function run_timestep(p, v, d, t) - - # Define an equation for E - v.E[t] = p.YGROSS[t] * p.sigma[t] # Note the p. in front of YGROSS - end -end - -function construct_model() - m = Model() - - set_dimension!(m, :time, collect(2015:5:2110)) - - # Order matters here. If the emissions component were defined first, the model would not run. - add_comp!(m, grosseconomy) - add_comp!(m, emissions) - - # Set parameters for the grosseconomy component - set_param!(m, :grosseconomy, :l, [(1. + 0.015)^t *6404 for t in 1:20]) - set_param!(m, :grosseconomy, :tfp, [(1 + 0.065)^t * 3.57 for t in 1:20]) - set_param!(m, :grosseconomy, :s, ones(20).* 0.22) - set_param!(m, :grosseconomy, :depk, 0.1) - set_param!(m, :grosseconomy, :k0, 130.) - set_param!(m, :grosseconomy, :share, 0.3) - - # Set parameters for the emissions component - set_param!(m, :emissions, :sigma, [(1. - 0.05)^t *0.58 for t in 1:20]) - connect_param!(m, :emissions, :YGROSS, :grosseconomy, :YGROSS) - # Note that connect_param! was used here. - - return m - -end #end function - -# Run model -m = construct_model() -run(m) - -sd = @defsim begin - # assign RVs to model Parameters - share = Uniform(0.2, 0.8) - s[2015:5:2050] = Uniform(0.2, 0.3) -end - -si = run(sd, m, 10) From 9831bf23f1081844946657e3a3df6f261066c943 Mon Sep 17 00:00:00 2001 From: lrennels Date: Tue, 17 Nov 2020 21:10:56 -0800 Subject: [PATCH 08/16] Simplify control flow; remove try catch --- src/mcs/montecarlo.jl | 54 +++++++++++++++-------------------------- test/mcs/test_defmcs.jl | 2 +- 2 files changed, 21 insertions(+), 35 deletions(-) diff --git a/src/mcs/montecarlo.jl b/src/mcs/montecarlo.jl index e4ccbfc26..270d36d50 100644 --- a/src/mcs/montecarlo.jl +++ b/src/mcs/montecarlo.jl @@ -355,19 +355,30 @@ function _perturb_param!(param::ArrayModelParameter{T}, md::ModelDef, indices = _param_indices(param, md, trans) if op == :(=) - - # if there is no time index, we can do a normal broadcast with .= and if not - # we will need to loop through and be fancy + + # first we check for a time index ti = get_time_index_position(param) + # If there is no time index we have all methods needed to broadcast normally if isnothing(ti) - try - pvalue[indices...] = rvalue - catch - pvalue[indices...] .= rvalue - end + broadcast_flag = sum(map(x -> length(x) > 1, indices)) > 0 + broadcast_flag ? pvalue[indices...] .= rvalue : pvalue[indices...] = rvalue + else - _perturb_param_handle_ti!(pvalue, indices, rvalue, ti) + indices1, ts, indices2 = split_indices(indices, ti) + non_ts_indices = [indices1..., indices2...] + broadcast_flag = isempty(non_ts_indices) ? false : sum(map(x -> length(x) > 1, non_ts_indices)) > 0 + + # Loop over the Array of TimestepIndex + if isa(ts, Array) + for el in ts + broadcast_flag ? pvalue[indices1..., el, indices2...] .= rvalue : pvalue[indices1..., el, indices2...] = rvalue + end + + # The time is just a single TimestepIndex and we can proceed with broadcast + else + broadcast_flag ? pvalue[indices...] .= rvalue : pvalue[indices...] = rvalue + end end elseif op == :(*=) @@ -378,31 +389,6 @@ function _perturb_param!(param::ArrayModelParameter{T}, md::ModelDef, end end -# special case where we might need to loop through the time indices -function _perturb_param_handle_ti!(pvalue, indices, rvalue, ti) - - indices1, ts, indices2 = split_indices(indices, ti) - - # array of timestep indices so need to loop through them - if isa(ts, Array) - for el in ts - try - pvalue[indices1..., el, indices2...] = rvalue - catch - pvalue[indices1..., el, indices2...] .= rvalue - end - end - - # just a single timestep index so proceed as usual - else - try - pvalue[indices...] = rvalue - catch - pvalue[indices...] .= rvalue - end - end -end - """ _perturb_params!(sim_inst::SimulationInstance{T}, trialnum::Int) diff --git a/test/mcs/test_defmcs.jl b/test/mcs/test_defmcs.jl index d956f3ee5..0c908c395 100644 --- a/test/mcs/test_defmcs.jl +++ b/test/mcs/test_defmcs.jl @@ -270,7 +270,7 @@ trial2 = copy(si2.sim_def.rvdict[:name1].dist.values) @test length(trial1) == length(trial2) @test trial1 != trial2 -# test potential broadcasting examples +# test broadcasting examples sd3 = @defsim begin # 1 dimension From a17d45b2933e819a50b869c4e35de1fb8009867a Mon Sep 17 00:00:00 2001 From: lrennels Date: Wed, 16 Dec 2020 12:15:48 -0800 Subject: [PATCH 09/16] Remove problematic doctests --- docs/src/tutorials/tutorial_5.md | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/docs/src/tutorials/tutorial_5.md b/docs/src/tutorials/tutorial_5.md index cdacb8ffc..8b7be3157 100644 --- a/docs/src/tutorials/tutorial_5.md +++ b/docs/src/tutorials/tutorial_5.md @@ -287,7 +287,7 @@ Case: We want to do an SCC calculation with `MimiDICE2010`, which consists of ru The beginning steps for this case are identical to those above. We first define the typical variables for a simulation, including the number of trials `N` and the simulation definition `sd`. In this case we only define one random variable, `t2xco2`, but note there could be any number of random variables defined here. -```jldoctest tutorial5; output = false, filter = r".*"s +```julia using Mimi using MimiDICE2010 using Distributions @@ -299,15 +299,12 @@ N = 100 sd = @defsim begin t2xco2 = Truncated(Gamma(6.47815626,0.547629469), 1.0, Inf) # a dummy distribution end - -# output - ``` #### Payload object Simulation definitions can hold a user-defined payload object which is not used or modified by Mimi. In this example, we will use the payload to hold an array of pre-computed discount factors that we will use in the SCC calculation, as well as a storage array for saving the SCC values. -```jldoctest tutorial5; output = false, filter = r".*"s +```julia # Choose what year to calculate the SCC for scc_year = 2015 year_idx = findfirst(isequal(scc_year), MimiDICE2010.model_years) @@ -323,9 +320,6 @@ scc_results = zeros(N, length(discount_rates)) # Set the payload object in the simulation definition my_payload_object = (discount_factors, scc_results) # In this case, the payload object is a tuple which holds both both arrays Mimi.set_payload!(sd, my_payload_object) - -# output - ``` #### Post-trial function From 929bf8ed7ea61eca686da75d47c238e75596fb4b Mon Sep 17 00:00:00 2001 From: lrennels Date: Wed, 16 Dec 2020 13:03:23 -0800 Subject: [PATCH 10/16] Revert tutorial changes --- docs/src/tutorials/tutorial_5.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/src/tutorials/tutorial_5.md b/docs/src/tutorials/tutorial_5.md index 8b7be3157..cdacb8ffc 100644 --- a/docs/src/tutorials/tutorial_5.md +++ b/docs/src/tutorials/tutorial_5.md @@ -287,7 +287,7 @@ Case: We want to do an SCC calculation with `MimiDICE2010`, which consists of ru The beginning steps for this case are identical to those above. We first define the typical variables for a simulation, including the number of trials `N` and the simulation definition `sd`. In this case we only define one random variable, `t2xco2`, but note there could be any number of random variables defined here. -```julia +```jldoctest tutorial5; output = false, filter = r".*"s using Mimi using MimiDICE2010 using Distributions @@ -299,12 +299,15 @@ N = 100 sd = @defsim begin t2xco2 = Truncated(Gamma(6.47815626,0.547629469), 1.0, Inf) # a dummy distribution end + +# output + ``` #### Payload object Simulation definitions can hold a user-defined payload object which is not used or modified by Mimi. In this example, we will use the payload to hold an array of pre-computed discount factors that we will use in the SCC calculation, as well as a storage array for saving the SCC values. -```julia +```jldoctest tutorial5; output = false, filter = r".*"s # Choose what year to calculate the SCC for scc_year = 2015 year_idx = findfirst(isequal(scc_year), MimiDICE2010.model_years) @@ -320,6 +323,9 @@ scc_results = zeros(N, length(discount_rates)) # Set the payload object in the simulation definition my_payload_object = (discount_factors, scc_results) # In this case, the payload object is a tuple which holds both both arrays Mimi.set_payload!(sd, my_payload_object) + +# output + ``` #### Post-trial function From 9b1f5e8db8e28df36ebbf820e024ada15eac196c Mon Sep 17 00:00:00 2001 From: lrennels Date: Wed, 16 Dec 2020 15:04:39 -0800 Subject: [PATCH 11/16] Remove doctests from tutorial 3 --- docs/src/tutorials/tutorial_3.md | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/docs/src/tutorials/tutorial_3.md b/docs/src/tutorials/tutorial_3.md index 7c58cbbe9..f52d89615 100644 --- a/docs/src/tutorials/tutorial_3.md +++ b/docs/src/tutorials/tutorial_3.md @@ -54,13 +54,11 @@ You have now successfully downloaded MimiDICE2010 to your local machine. The next step is to run DICE using the provided API for the package: -```jldoctest tutorial2; output = false, filter = r".*"s +```julia using MimiDICE2010 m = MimiDICE2010.get_model() run(m) -# output - ``` These steps should be relatively consistent across models, where a repository for `ModelX` should contain a primary file `ModelX.jl` which exports, at minimum, a function named something like `get_model` or `construct_model` which returns a version of the model, and can allow for model customization within the call. @@ -77,35 +75,26 @@ Thus there are no required arguments, although the user can input `params`, a di In the case that you wish to alter an exogenous parameter, you may use the [`update_param!`](@ref) function. Per usual, you will start by importing the Mimi package to your space with -```jldoctest tutorial2; output = false +```julia using Mimi - -# output - ``` In DICE the parameter `fco22x` is the forcings of equilibrium CO2 doubling in watts per square meter, and exists in the components `climatedynamics` and `radiativeforcing`. We can change this value from its default value of `3.200` to `3.000` in both components, using the following code: -```jldoctest tutorial2; output = false, filter = r".*"s +```julia update_param!(m, :fco22x, 3.000) run(m) - -# output - ``` A more complex example may be a situation where you want to update several parameters, including some with a `:time` dimension, in conjunction with altering the time index of the model itself. DICE uses a default time horizon of 2005 to 2595 with 10 year increment timesteps. If you wish to change this, say, to 2000 to 2500 by 10 year increment timesteps and use parameters that match this time, you could use the following code: First you upate the `time` dimension of the model as follows: -```jldoctest tutorial2; output = false, filter = r".*"s +```julia const ts = 10 const years = collect(2000:ts:2500) nyears = length(years) set_dimension!(m, :time, years) - -# output - ``` Now that you have changed the time dimension, you have a mismatch between the time labels attached to your parameters and the time labels used by the model. Thus, **you must update at least all parameters with a `:time`** dimension and use the explicit `update_timesteps=true` flag to get the time labels on the parameters to match those in the model. This is required even in cases where you do not want to change the parameter values themselves (see the forum question [here](https://forum.mimiframework.org/t/update-time-index/134/5)) for an in-depth explanation of this case. You may of course also update parameters without a `:time` dimension as desired. From 4be282031f56cf813a7b7a44e661701ef9a75399 Mon Sep 17 00:00:00 2001 From: lrennels Date: Wed, 16 Dec 2020 15:31:54 -0800 Subject: [PATCH 12/16] Try adding doctests back in --- docs/src/tutorials/tutorial_3.md | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/docs/src/tutorials/tutorial_3.md b/docs/src/tutorials/tutorial_3.md index f52d89615..4f7021bae 100644 --- a/docs/src/tutorials/tutorial_3.md +++ b/docs/src/tutorials/tutorial_3.md @@ -54,11 +54,13 @@ You have now successfully downloaded MimiDICE2010 to your local machine. The next step is to run DICE using the provided API for the package: -```julia +```jldoctest tutorial2; output = false, filter = r".*"s using MimiDICE2010 m = MimiDICE2010.get_model() run(m) +# output + ``` These steps should be relatively consistent across models, where a repository for `ModelX` should contain a primary file `ModelX.jl` which exports, at minimum, a function named something like `get_model` or `construct_model` which returns a version of the model, and can allow for model customization within the call. @@ -75,26 +77,35 @@ Thus there are no required arguments, although the user can input `params`, a di In the case that you wish to alter an exogenous parameter, you may use the [`update_param!`](@ref) function. Per usual, you will start by importing the Mimi package to your space with -```julia +```jldoctest tutorial2; output = false, filter = r".*"s using Mimi + +# output + ``` In DICE the parameter `fco22x` is the forcings of equilibrium CO2 doubling in watts per square meter, and exists in the components `climatedynamics` and `radiativeforcing`. We can change this value from its default value of `3.200` to `3.000` in both components, using the following code: -```julia +```jldoctest tutorial2; output = false, filter = r".*"s update_param!(m, :fco22x, 3.000) run(m) + +# output + ``` A more complex example may be a situation where you want to update several parameters, including some with a `:time` dimension, in conjunction with altering the time index of the model itself. DICE uses a default time horizon of 2005 to 2595 with 10 year increment timesteps. If you wish to change this, say, to 2000 to 2500 by 10 year increment timesteps and use parameters that match this time, you could use the following code: First you upate the `time` dimension of the model as follows: -```julia +```jldoctest tutorial2; output = false, filter = r".*"s const ts = 10 const years = collect(2000:ts:2500) nyears = length(years) set_dimension!(m, :time, years) + +# output + ``` Now that you have changed the time dimension, you have a mismatch between the time labels attached to your parameters and the time labels used by the model. Thus, **you must update at least all parameters with a `:time`** dimension and use the explicit `update_timesteps=true` flag to get the time labels on the parameters to match those in the model. This is required even in cases where you do not want to change the parameter values themselves (see the forum question [here](https://forum.mimiframework.org/t/update-time-index/134/5)) for an in-depth explanation of this case. You may of course also update parameters without a `:time` dimension as desired. From 495db1c0df7f280ba87efd6998ec036607e32922 Mon Sep 17 00:00:00 2001 From: lrennels Date: Wed, 16 Dec 2020 20:33:38 -0800 Subject: [PATCH 13/16] Remove doctests from tutorial 3 for CI --- docs/src/tutorials/tutorial_3.md | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/docs/src/tutorials/tutorial_3.md b/docs/src/tutorials/tutorial_3.md index 4f7021bae..1ce670bce 100644 --- a/docs/src/tutorials/tutorial_3.md +++ b/docs/src/tutorials/tutorial_3.md @@ -54,13 +54,10 @@ You have now successfully downloaded MimiDICE2010 to your local machine. The next step is to run DICE using the provided API for the package: -```jldoctest tutorial2; output = false, filter = r".*"s +```julia using MimiDICE2010 m = MimiDICE2010.get_model() run(m) - -# output - ``` These steps should be relatively consistent across models, where a repository for `ModelX` should contain a primary file `ModelX.jl` which exports, at minimum, a function named something like `get_model` or `construct_model` which returns a version of the model, and can allow for model customization within the call. @@ -77,35 +74,26 @@ Thus there are no required arguments, although the user can input `params`, a di In the case that you wish to alter an exogenous parameter, you may use the [`update_param!`](@ref) function. Per usual, you will start by importing the Mimi package to your space with -```jldoctest tutorial2; output = false, filter = r".*"s +```julia using Mimi - -# output - ``` In DICE the parameter `fco22x` is the forcings of equilibrium CO2 doubling in watts per square meter, and exists in the components `climatedynamics` and `radiativeforcing`. We can change this value from its default value of `3.200` to `3.000` in both components, using the following code: -```jldoctest tutorial2; output = false, filter = r".*"s +```julia update_param!(m, :fco22x, 3.000) run(m) - -# output - ``` A more complex example may be a situation where you want to update several parameters, including some with a `:time` dimension, in conjunction with altering the time index of the model itself. DICE uses a default time horizon of 2005 to 2595 with 10 year increment timesteps. If you wish to change this, say, to 2000 to 2500 by 10 year increment timesteps and use parameters that match this time, you could use the following code: First you upate the `time` dimension of the model as follows: -```jldoctest tutorial2; output = false, filter = r".*"s +```julia const ts = 10 const years = collect(2000:ts:2500) nyears = length(years) set_dimension!(m, :time, years) - -# output - ``` Now that you have changed the time dimension, you have a mismatch between the time labels attached to your parameters and the time labels used by the model. Thus, **you must update at least all parameters with a `:time`** dimension and use the explicit `update_timesteps=true` flag to get the time labels on the parameters to match those in the model. This is required even in cases where you do not want to change the parameter values themselves (see the forum question [here](https://forum.mimiframework.org/t/update-time-index/134/5)) for an in-depth explanation of this case. You may of course also update parameters without a `:time` dimension as desired. From 8272931df73d03dd2a5364f9de47ad52d73f6bf0 Mon Sep 17 00:00:00 2001 From: lrennels Date: Mon, 21 Dec 2020 12:21:53 -0800 Subject: [PATCH 14/16] Put doctests back --- docs/src/tutorials/tutorial_3.md | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/docs/src/tutorials/tutorial_3.md b/docs/src/tutorials/tutorial_3.md index 1ce670bce..d4678c309 100644 --- a/docs/src/tutorials/tutorial_3.md +++ b/docs/src/tutorials/tutorial_3.md @@ -54,10 +54,13 @@ You have now successfully downloaded MimiDICE2010 to your local machine. The next step is to run DICE using the provided API for the package: -```julia +```jldoctest tutorial2; output = false, filter = r".*"s using MimiDICE2010 m = MimiDICE2010.get_model() run(m) + +# output + ``` These steps should be relatively consistent across models, where a repository for `ModelX` should contain a primary file `ModelX.jl` which exports, at minimum, a function named something like `get_model` or `construct_model` which returns a version of the model, and can allow for model customization within the call. @@ -74,26 +77,35 @@ Thus there are no required arguments, although the user can input `params`, a di In the case that you wish to alter an exogenous parameter, you may use the [`update_param!`](@ref) function. Per usual, you will start by importing the Mimi package to your space with -```julia +```jldoctest tutorial2; output = false, filter = r".*"s using Mimi + +# output + ``` In DICE the parameter `fco22x` is the forcings of equilibrium CO2 doubling in watts per square meter, and exists in the components `climatedynamics` and `radiativeforcing`. We can change this value from its default value of `3.200` to `3.000` in both components, using the following code: -```julia +```jldoctest tutorial2; output = false, filter = r".*"s update_param!(m, :fco22x, 3.000) run(m) + +# output + ``` A more complex example may be a situation where you want to update several parameters, including some with a `:time` dimension, in conjunction with altering the time index of the model itself. DICE uses a default time horizon of 2005 to 2595 with 10 year increment timesteps. If you wish to change this, say, to 2000 to 2500 by 10 year increment timesteps and use parameters that match this time, you could use the following code: First you upate the `time` dimension of the model as follows: -```julia +```jldoctest tutorial2; output = false, filter = r".*"s const ts = 10 const years = collect(2000:ts:2500) nyears = length(years) set_dimension!(m, :time, years) + +# output + ``` Now that you have changed the time dimension, you have a mismatch between the time labels attached to your parameters and the time labels used by the model. Thus, **you must update at least all parameters with a `:time`** dimension and use the explicit `update_timesteps=true` flag to get the time labels on the parameters to match those in the model. This is required even in cases where you do not want to change the parameter values themselves (see the forum question [here](https://forum.mimiframework.org/t/update-time-index/134/5)) for an in-depth explanation of this case. You may of course also update parameters without a `:time` dimension as desired. From 19fc3edac5399da0f934e13c10f136ed54546da4 Mon Sep 17 00:00:00 2001 From: Lisa Rennels <31779240+lrennels@users.noreply.github.com> Date: Mon, 21 Dec 2020 12:38:41 -0800 Subject: [PATCH 15/16] Update tutorial_3.md --- docs/src/tutorials/tutorial_3.md | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/docs/src/tutorials/tutorial_3.md b/docs/src/tutorials/tutorial_3.md index d4678c309..15da86697 100644 --- a/docs/src/tutorials/tutorial_3.md +++ b/docs/src/tutorials/tutorial_3.md @@ -54,13 +54,10 @@ You have now successfully downloaded MimiDICE2010 to your local machine. The next step is to run DICE using the provided API for the package: -```jldoctest tutorial2; output = false, filter = r".*"s +```julai using MimiDICE2010 m = MimiDICE2010.get_model() run(m) - -# output - ``` These steps should be relatively consistent across models, where a repository for `ModelX` should contain a primary file `ModelX.jl` which exports, at minimum, a function named something like `get_model` or `construct_model` which returns a version of the model, and can allow for model customization within the call. @@ -77,35 +74,26 @@ Thus there are no required arguments, although the user can input `params`, a di In the case that you wish to alter an exogenous parameter, you may use the [`update_param!`](@ref) function. Per usual, you will start by importing the Mimi package to your space with -```jldoctest tutorial2; output = false, filter = r".*"s +```julia using Mimi - -# output - ``` In DICE the parameter `fco22x` is the forcings of equilibrium CO2 doubling in watts per square meter, and exists in the components `climatedynamics` and `radiativeforcing`. We can change this value from its default value of `3.200` to `3.000` in both components, using the following code: -```jldoctest tutorial2; output = false, filter = r".*"s +```julia update_param!(m, :fco22x, 3.000) run(m) - -# output - ``` A more complex example may be a situation where you want to update several parameters, including some with a `:time` dimension, in conjunction with altering the time index of the model itself. DICE uses a default time horizon of 2005 to 2595 with 10 year increment timesteps. If you wish to change this, say, to 2000 to 2500 by 10 year increment timesteps and use parameters that match this time, you could use the following code: First you upate the `time` dimension of the model as follows: -```jldoctest tutorial2; output = false, filter = r".*"s +```julia const ts = 10 const years = collect(2000:ts:2500) nyears = length(years) set_dimension!(m, :time, years) - -# output - ``` Now that you have changed the time dimension, you have a mismatch between the time labels attached to your parameters and the time labels used by the model. Thus, **you must update at least all parameters with a `:time`** dimension and use the explicit `update_timesteps=true` flag to get the time labels on the parameters to match those in the model. This is required even in cases where you do not want to change the parameter values themselves (see the forum question [here](https://forum.mimiframework.org/t/update-time-index/134/5)) for an in-depth explanation of this case. You may of course also update parameters without a `:time` dimension as desired. From 205cd85ca02a3819c35f7f41de0a9e82b5be6184 Mon Sep 17 00:00:00 2001 From: Lisa Rennels <31779240+lrennels@users.noreply.github.com> Date: Mon, 21 Dec 2020 12:52:08 -0800 Subject: [PATCH 16/16] Fix typo --- docs/src/tutorials/tutorial_3.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/tutorials/tutorial_3.md b/docs/src/tutorials/tutorial_3.md index 15da86697..1ce670bce 100644 --- a/docs/src/tutorials/tutorial_3.md +++ b/docs/src/tutorials/tutorial_3.md @@ -54,7 +54,7 @@ You have now successfully downloaded MimiDICE2010 to your local machine. The next step is to run DICE using the provided API for the package: -```julai +```julia using MimiDICE2010 m = MimiDICE2010.get_model() run(m)