From b7e3adf6f8b5fb557261888c427076a1128580a5 Mon Sep 17 00:00:00 2001 From: lrennels Date: Mon, 30 Sep 2019 16:13:25 -0700 Subject: [PATCH 01/63] Start including doctests --- docs/src/faq.md | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/docs/src/faq.md b/docs/src/faq.md index d92058ebe..fc75e8abc 100644 --- a/docs/src/faq.md +++ b/docs/src/faq.md @@ -1,5 +1,18 @@ # Frequently asked questions +```@meta +DocTestSeup = + using Pkg + Pkg.add("Mimi") + Pkg.add("DelimitedFiles") + Pkg.add("Distributions") + + using Mimi + using DelimitedFiles + using Distributions + +end +``` ## What's up with the name? The name is probably an acronym for "Modular Integrated Modeling Interface", but we are not sure. What is certain is that it came up during a dinner that [Bob](http://www.bobkopp.net/), [David](http://www.david-anthoff.com/) and [Sol](http://www.solomonhsiang.com/) had in 2015. David thinks that Bob invented the name, Bob doesn't remember and Sol thinks the waiter might have come up with it (although we can almost certainly rule that option out). It certainly is better than the previous name "IAMF". We now use "Mimi" purely as a name of the package, not as an acronym. @@ -11,10 +24,13 @@ covariance between estimated coefficient parameters. For example, an estimated polynomial can be represented as a multivariate Normal distribution, with a variance-covariance matrix. To use this, define the parameter in the component with a vector type, like here: -``` + +```jldoctest @defcomp example begin - cubiccoeffs::Vector{Float64} = Parameter() + cubiccoeff::Vector{Float64} = Parameter() end + + # output ``` Then in the model construction, set the parameter with a multivariate @@ -28,7 +44,7 @@ Here, `../data/cubicparams.csv` is a parameter definition file that looks someth ``` # Example estimated polynomial parameter # First line: linear, quadratic, cubic -# Lines 2-4: covariance matrix +# Lines 2-5: covariance matrix -3.233303,1.911123,-.1018884 1.9678593,-.57211657,.04413228 -.57211657,.17500949,-.01388863 @@ -56,3 +72,7 @@ The line `set_param!(model, :MyComponent, :myparameter, myvalue)` can be written ## References in place of `connect_param!` The line `connect_param!(model, :MyComponent, :myparameter, :YourComponent, :yourparameter)` can be written as `mycomponent[:myparameter] = yourcomponent[:yourparameter]`, where `mycomponent` and `yourcomponent` are component references. + +```@meta +DocTestSetup = nothing +``` \ No newline at end of file From 4fbffd7b410503cf44e34463699a1990ec56c216 Mon Sep 17 00:00:00 2001 From: lrennels Date: Tue, 1 Oct 2019 14:06:08 -0700 Subject: [PATCH 02/63] Add doctests to faq --- docs/Project.toml | 4 +++ docs/src/faq.md | 67 +++++++++++++++++++++++++++++++++-------------- 2 files changed, 52 insertions(+), 19 deletions(-) diff --git a/docs/Project.toml b/docs/Project.toml index ce87d1572..161cfae50 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,5 +1,9 @@ [deps] +Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +Mimi = "e4e893b0-ee5e-52ea-8111-44b3bdec128c" [compat] +Distributions = "0.21" Documenter = "~0.21" +Mimi = "0.9.3" diff --git a/docs/src/faq.md b/docs/src/faq.md index fc75e8abc..0cb9aee3d 100644 --- a/docs/src/faq.md +++ b/docs/src/faq.md @@ -2,15 +2,8 @@ ```@meta DocTestSeup = - using Pkg - Pkg.add("Mimi") - Pkg.add("DelimitedFiles") - Pkg.add("Distributions") - using Mimi - using DelimitedFiles using Distributions - end ``` ## What's up with the name? @@ -25,8 +18,8 @@ polynomial can be represented as a multivariate Normal distribution, with a variance-covariance matrix. To use this, define the parameter in the component with a vector type, like here: -```jldoctest -@defcomp example begin +```jldoctest; output = false +@defcomp MyComp begin cubiccoeff::Vector{Float64} = Parameter() end @@ -34,17 +27,37 @@ end ``` Then in the model construction, set the parameter with a multivariate -distribution (here the parameters are loaded from a CSV file): -``` -cubicparams = readdlm("../data/cubicparams.csv", ',') -set_param!(m, :example, :cubiccoeff, MvNormal(squeeze(cubicparams[1,:], 1), cubicparams[2:4,:])) +distribution: + +```jldoctest; output = false; setup = @defcomp MyComp begin cubiccoeff::Vector{Float64} = Parameter() end +# First line: linear, quadratic, cubic +# Lines 2-4: covariance matrix +cubicparams = [ + [-3.233303 1.911123 -0.1018884]; + [ 1.9678593 -0.57211657 0.04413228]; + [-0.57211657 0.17500949 -0.01388863]; + [ 0.04413228 -0.01388863 0.00111965] +] + +m = Model() +set_dimension!(m, :time, collect(2015:5:2110)) +add_comp!(m, MyComp) + +set_param!(m, :MyComp, :cubiccoeff, MvNormal(cubicparams[1,:], cubicparams[2:4,:])) + +# output ``` -Here, `../data/cubicparams.csv` is a parameter definition file that looks something like this: +Note that we could also load the data fom a file with: + +```julia +cubicparams = readdlm("../data/cubicparams.csv", ',') ``` +where `../data/cubicparams.csv` would be a parameter definition file that looks something like this: +```julia # Example estimated polynomial parameter # First line: linear, quadratic, cubic -# Lines 2-5: covariance matrix +# Lines 2-4: covariance matrix -3.233303,1.911123,-.1018884 1.9678593,-.57211657,.04413228 -.57211657,.17500949,-.01388863 @@ -54,13 +67,29 @@ Here, `../data/cubicparams.csv` is a parameter definition file that looks someth ## How do I use component references? Component references allow you to write cleaner model code when connecting components. The `add_comp!` function returns a reference to the component that you just added: -``` -mycomponent = add_comp!(model, MyComponent) + +```jldoctest; output = false; setup = @defcomp MyComp begin cubiccoeff::Vector{Float64} = Parameter() end +m = Model() +set_dimension!(m, :time, collect(2015:5:2110)) + +mycomponent = add_comp!(m, MyComp) + +# output +Mimi.ComponentReference(1-component Mimi.Model: + MyComp::Main.MyComp +, :MyComp) ``` If you want to get a reference to a component after the `add_comp!` call has been made, you can construct the reference as: -``` -mycomponent = ComponentReference(model, :MyComponent) +```jldoctest; setup = @defcomp MyComp begin cubiccoeff::Vector{Float64} = Parameter() end; m = Model(); set_dimension!(m, :time, collect(2015:5:2110)); add_comp!(m, MyComp) + +mycomponent = Mimi.ComponentReference(m, :MyComp) + +#output +Mimi.ComponentReference(1-component Mimi.Model: + MyComp::Main.MyComp +, :MyComp) + ``` You can use this component reference in place of the `set_param!` and `connect_param!` calls. From 76c95d47fe7f06360ea5b706725f0f7600464872 Mon Sep 17 00:00:00 2001 From: lrennels Date: Tue, 1 Oct 2019 17:04:15 -0700 Subject: [PATCH 03/63] Add continuous doctest scope; improve consistency of docs --- docs/src/faq.md | 35 +++++++++------- docs/src/installation.md | 12 +++++- docs/src/userguide.md | 87 ++++++++++++++++++++++------------------ 3 files changed, 78 insertions(+), 56 deletions(-) diff --git a/docs/src/faq.md b/docs/src/faq.md index 0cb9aee3d..8c5a43471 100644 --- a/docs/src/faq.md +++ b/docs/src/faq.md @@ -1,7 +1,7 @@ # Frequently asked questions ```@meta -DocTestSeup = +DocTestSeup = quote using Mimi using Distributions end @@ -18,7 +18,7 @@ polynomial can be represented as a multivariate Normal distribution, with a variance-covariance matrix. To use this, define the parameter in the component with a vector type, like here: -```jldoctest; output = false +```jldoctest faq1; output = false @defcomp MyComp begin cubiccoeff::Vector{Float64} = Parameter() end @@ -26,10 +26,16 @@ end # output ``` -Then in the model construction, set the parameter with a multivariate +Then construct a model and set the parameter with a multivariate distribution: -```jldoctest; output = false; setup = @defcomp MyComp begin cubiccoeff::Vector{Float64} = Parameter() end +```jldoctest faq1; output = false + +# construct a model and add the component +m = Model() +set_dimension!(m, :time, collect(2015:5:2110)) +add_comp!(m, MyComp) + # First line: linear, quadratic, cubic # Lines 2-4: covariance matrix cubicparams = [ @@ -39,10 +45,6 @@ cubicparams = [ [ 0.04413228 -0.01388863 0.00111965] ] -m = Model() -set_dimension!(m, :time, collect(2015:5:2110)) -add_comp!(m, MyComp) - set_param!(m, :MyComp, :cubiccoeff, MvNormal(cubicparams[1,:], cubicparams[2:4,:])) # output @@ -68,11 +70,16 @@ where `../data/cubicparams.csv` would be a parameter definition file that looks Component references allow you to write cleaner model code when connecting components. The `add_comp!` function returns a reference to the component that you just added: -```jldoctest; output = false; setup = @defcomp MyComp begin cubiccoeff::Vector{Float64} = Parameter() end +```jldoctest faq2; output = false +# create a component +@defcomp MyComp begin + # empty +end + +# construct a model and add the component m = Model() set_dimension!(m, :time, collect(2015:5:2110)) - -mycomponent = add_comp!(m, MyComp) +add_comp!(m, MyComp) # output Mimi.ComponentReference(1-component Mimi.Model: @@ -81,15 +88,13 @@ Mimi.ComponentReference(1-component Mimi.Model: ``` If you want to get a reference to a component after the `add_comp!` call has been made, you can construct the reference as: -```jldoctest; setup = @defcomp MyComp begin cubiccoeff::Vector{Float64} = Parameter() end; m = Model(); set_dimension!(m, :time, collect(2015:5:2110)); add_comp!(m, MyComp) - +```jldoctest; faq2 mycomponent = Mimi.ComponentReference(m, :MyComp) -#output +# output Mimi.ComponentReference(1-component Mimi.Model: MyComp::Main.MyComp , :MyComp) - ``` You can use this component reference in place of the `set_param!` and `connect_param!` calls. diff --git a/docs/src/installation.md b/docs/src/installation.md index 2f271960a..b6ca19eb7 100644 --- a/docs/src/installation.md +++ b/docs/src/installation.md @@ -1,5 +1,11 @@ # Installation Guide +```@meta +DocTestSeup = quote + using Mimi +end +``` + This guide will briefly explain how to install julia and Mimi. ## Installing julia @@ -25,7 +31,7 @@ This will update *all* installed packages to their latest version (not just the ## Using Mimi When you start a new julia command prompt, Mimi is not yet loaded into that julia session. To load Mimi, issue the following command: -```julia +```jldoctest julia> using Mimi ``` You will have to run this command every time you want to use Mimi in julia. You would typically also add `using Mimi` to the top of any julia code file that for example defines Mimi components. @@ -45,3 +51,7 @@ The best way to get started with Mimi is to work through the **Tutorials**. The [Mimi](https://github.com/mimiframework/Mimi.jl) github repository also has links to various models that are based on Mimi, and looking through their code can be instructive. Finally, when in doubt, ask your question in the [Mimi Framework forum](https://forum.mimiframework.org) or post an [Issue](https://github.com/mimiframework/Mimi.jl/issues) to the Github repository if you have a specific request for the development team. Don't be shy about either option, we would much prefer to be inundated with lots of questions and help people out than people give up on Mimi! + +```@meta +DocTestSetup = nothing +``` diff --git a/docs/src/userguide.md b/docs/src/userguide.md index d94e05cba..552c19ee4 100644 --- a/docs/src/userguide.md +++ b/docs/src/userguide.md @@ -1,5 +1,11 @@ # User Guide +```@meta +DocTestSetup = quote + using Mimi +end +``` + ## Overview See the Tutorials for in-depth examples of Mimi's functionality. @@ -24,9 +30,7 @@ The user must define a `run_timestep` function for each component. We define a component in the following way: -```julia -using Mimi - +```jldoctest; output = false @defcomp MyComponentName begin regions = Index() @@ -44,9 +48,9 @@ using Mimi v.B[t, r] = p.f[r] * p.e[t, r] end end - end +# output ``` The `run_timestep` function is responsible for calculating values for each variable in that component. Note that the component state (defined by the first three arguments) has fields for the Parameters, Variables, and Dimensions of the component you defined. You can access each parameter, variable, or dimension using dot notation as shown above. The fourth argument is an `AbstractTimestep`, i.e., either a `FixedTimestep` or a `VariableTimestep`, which represents which timestep the model is at. @@ -59,22 +63,22 @@ To access the data in a parameter or to assign a value to a variable, you must u 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. -```julia -mymodel = Model() -set_dimension!(mymodel, :time, 1850:2200) -set_dimension!(mymodel, :regions, ["USA", "EU", "LATAM"]) +```jldoctest; output = false +m = Model() +set_dimension!(m, :time, 1850:2200) +set_dimension!(m, :regions, ["USA", "EU", "LATAM"]) +# output ``` *A Note on Time Indexes:* It is important to note that the values used for the time index are the *start times* of the timesteps. If the range or array of time values has a uniform timestep length, the model will run *through* the last year of the range with a last timestep period length consistent with the other timesteps. If the time values are provided as an array with non-uniform timestep lengths, the model will run *through* the last year in the array with a last timestep period length *assumed to be one*. The next step is to add components to the model. This is done by the following syntax: -```julia -add_comp!(mymodel, ComponentA, :GDP) -add_comp!(mymodel, ComponentB; first=2010) -add_comp!(mymodel, ComponentC; first=2010, last=2100) - +```julia +add_comp!(m, ComponentA, :GDP) +add_comp!(m, ComponentB; first=2010) +add_comp!(m, ComponentC; first=2010, last=2100) ``` The first argument to `add_comp!` is the model, the second is the name of the ComponentId defined by `@defcomp`. If an optional third symbol is provided (as in the first line above), this will be used as the name of the component in this model. This allows you to add multiple versions of the same component to a model, with different names. You can also have components that do not run for the full length of the model. You can specify custom first and last times with the optional keyword arguments as shown above. If no first or last time is provided, the component will assume the first or last time of the model's time index values that were specified in `set_dimension!`. @@ -84,22 +88,23 @@ The next step is to set the values for all the parameters in the components. Par To make an external connection, the syntax is as follows: ```julia -set_param!(mymodel, :ComponentName, :parametername, 0.8) # a scalar parameter -set_param!(mymodel, :ComponentName, :parametername2, rand(351, 3)) # a two-dimensional parameter - +set_param!(m, :ComponentName, :ParameterName, 0.8) # a scalar parameter +set_param!(m, :ComponentName, :ParameterName2, rand(351, 3)) # a two-dimensional parameter ``` To make an internal connection, the syntax is as follows. ```julia -connect_param!(mymodel, :TargetComponent=>:parametername, :SourceComponent=>:variablename) -connect_param!(mymodel, :TargetComponent=>:parametername, :SourceComponent=>:variablename) +connect_param!(m, :TargetComponent=>:ParameterName, :SourceComponent=>:VariableName) +connect_param!(m, :TargetComponent=>:ParameterName, :SourceComponent=>:VariableName) ``` If you wish to delete a component that has already been added, do the following: + ```julia -delete!(mymodel, :ComponentName) +delete!(m, :ComponentName) ``` + This will delete the component from the model and remove any existing connections it had. Thus if a different component was previously connected to this component, you will need to connect its parameter(s) to something else. ## Running a Model @@ -107,8 +112,7 @@ This will delete the component from the model and remove any existing connection After all components have been added to your model and all parameters have been connected to either external values or internally to another component, then the model is ready to be run. Note: at each timestep, the model will run the components in the order you added them. So if one component is going to rely on the value of another component, then the user must add them to the model in the appropriate order. ```julia -run(mymodel) - +run(m) ``` ## Accessing Results @@ -118,20 +122,19 @@ After a model has been run, you can access the results (the calculated variable You can use the `getindex` syntax as follows: ```julia -mymodel[:ComponentName, :VariableName] # returns the whole array of values -mymodel[:ComponentName, :VariableName][100] # returns just the 100th value - +m[:ComponentName, :VariableName] # returns the whole array of values +m[:ComponentName, :VariableName][100] # returns just the 100th value ``` + Indexing into a model with the name of the component and variable will return an array with values from each timestep. You can index into this array to get one value (as in the second line, which returns just the 100th value). Note that if the requested variable is two-dimensional, then a 2-D array will be returned. You can also get data in the form of a dataframe, which will display the corresponding index labels rather than just a raw array. The syntax for this is: ```julia -getdataframe(mymodel, :ComponentName=>:Variable) # request one variable from one component -getdataframe(mymodel, :ComponentName=>(:Variable1, :Variable2)) # request multiple variables from the same component -getdataframe(mymodel, :Component1=>:Var1, :Component2=>:Var2) # request variables from different components - +getdataframe(m, :ComponentName=>:Variable) # request one variable from one component +getdataframe(m, :ComponentName=>(:Variable1, :Variable2)) # request multiple variables from the same component +getdataframe(m, :Component1=>:Var1, :Component2=>:Var2) # request variables from different components ``` ## Plotting and the Explorer UI @@ -151,8 +154,8 @@ Other plotting support is provided by the **Explorer UI**, rooted in `VegaLite`. In order to invoke the explorer UI and explore all of the variables and parameters in a model, simply call the function `explore` with the model run as the required argument, and a window title as an optional keyword argument, as shown below. This will produce a new browser window containing a selectable list of parameters and variables, organized by component, each of which produces a graphic. The exception here being that if the parameter or variable is a single scalar value, the value will appear alongside the name in the left-hand list. ```julia -run(mymodel) - explore(mymodel, title = "run1 results") +run(m) +explore(m, title = "run1 results") ``` ![Explorer Model Example](figs/explorer_model_example.png) @@ -161,11 +164,10 @@ Alternatively, in order to view just one parameter or variable, call the (unexpo ```julia using VegaLite -run(mymodel) -p = Mimi.plot(mymodel, :component1, :parameter1) +run(m) +p = Mimi.plot(m, :ComponentName, :ParameterName) save("figure.svg", p) ``` - ![Plot Model Example](figs/plot_model_example.png) These two functions, `explore` and `plot` also have methods applicable to the sensitivity analysis support described in the next section. Details can be found in the linked [internals documentation](https://github.com/mimiframework/Mimi.jl/blob/master/docs/src/internals/montecarlo.md) as well as [Tutorial 4: Sensitivity Analysis (SA) Support](@ref). @@ -206,7 +208,7 @@ As mentioned earlier, it is possible for some components to start later or end s ```julia backup = rand(100) # data array of the proper size -connect_param!(mymodel, :LongComponent=>:parametername, :ShortComponent=>:variablename, backup) +connect_param!(m, :LongComponent=>:ParameterName, :ShortComponent=>:VariableName, backup) ``` Note: for now, to avoid discrepancy with timing and alignment, the backup data must be the length of the whole component's first to last time, even though it will only be used for values not found in the shorter component. @@ -221,6 +223,7 @@ As mentioned above, a parameter can have no index (a scalar), or one or multiple p2::Array{Float64, 2} = Parameter() # a two dimensional array of unspecified length end ``` + In both of these cases, the parameter's values are stored of as an array (p1 is one dimensional, and p2 is two dimensional). But with respect to the model, they are considered "scalar" parameters, simply because they do not use any of the model's indices (namely 'time', or 'regions'). ### Updating an external parameter @@ -228,8 +231,8 @@ In both of these cases, the parameter's values are stored of as an array (p1 is When `set_param!` is called, it creates an external parameter by the name provided, and stores the provided scalar or array value. It is possible to later change the value associated with that parameter name using the functions described below. If the external parameter has a `:time` dimension, use the optional argument `update_timesteps=true` to indicate that the time keys (i.e., year labels) associated with the parameter should be updated in addition to updating the parameter values. ```julia -update_param!(mymodel, :parametername, newvalues) # update values only -update_param!(mymodel, :parametername, newvalues, update_timesteps=true) # also update time keys +update_param!(m, :ParameterName, newvalues) # update values only +update_param!(m, :ParameterName, newvalues, update_timesteps=true) # also update time keys ``` Note: `newvalues` must be the same size and type (or be able to convert to the type) of the old values stored in that parameter. @@ -239,7 +242,7 @@ Note: `newvalues` must be the same size and type (or be able to convert to the t In larger models it can be beneficial to set some of the external parameters using a dictionary of values. To do this, use the following function: ```julia -set_leftover_params!(mymodel, parameters) +set_leftover_params!(m, parameters) ``` Where `parameters` is a dictionary of type `Dict{String, Any}` where the keys are strings that match the names of the unset parameters in the model, and the values are the values to use for those parameters. @@ -253,11 +256,11 @@ When a user sets a parameter, Mimi checks that the size and dimensions match wha When you call the run function on your model, first the internal `build` function is called, which produces a ModelInstance, and then the ModelInstance is run. A model instance is an instantiated version of the model you have designed where all of the component constructors have been called and all of the data arrays have been allocated. If you wish to create and run multiple versions of your model, you can use the intermediate build function and store the separate ModelInstances. This may be useful if you want to change some parameter values, while keeping the model's structure mostly the same. For example: ```julia -instance1 = Mimi.build(mymodel) +instance1 = Mimi.build(m) run(instance1) -update_param!(mymodel, paramname, newvalue) -instance2 = Mimi.build(mymodel) +update_param!(m, ParameterName, newvalue) +instance2 = Mimi.build(m) run(instance2) result1 = instance1[:Comp, :Var] @@ -288,3 +291,7 @@ If defined for a specific component, this function will run **before** the times end ``` + +```@meta +DocTestSetup = nothing +``` From 59efb5cee0e5864a8d51d93087e62a6bf5622ca5 Mon Sep 17 00:00:00 2001 From: lrennels Date: Tue, 1 Oct 2019 17:19:42 -0700 Subject: [PATCH 04/63] Add doctests to testing suite --- Project.toml | 15 ++++++++------- test/runtests.jl | 5 +++++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Project.toml b/Project.toml index 8d1d453f0..96d8f7425 100644 --- a/Project.toml +++ b/Project.toml @@ -16,6 +16,7 @@ FilePaths = "8fc22ac5-c921-52a6-82fd-178b2807b824" GlobalSensitivityAnalysis = "1b10255b-6da3-57ce-9089-d24e8517b87e" GraphPlot = "a2cc645c-3eea-5389-862e-a155d0052231" IterTools = "c8e1da08-722c-5040-9ed9-7db0dc04731e" +IteratorInterfaceExtensions = "82899510-4779-5014-852e-03e436cf321d" JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" LightGraphs = "093fc24a-ae57-5d10-9952-331d41423f4d" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" @@ -32,16 +33,15 @@ StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" StringBuilders = "db12335b-fddc-5e1b-b0ee-42071d21ae50" TableTraits = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c" VegaLite = "112f6efa-9a02-5b7d-90c0-432ed331239a" -IteratorInterfaceExtensions = "82899510-4779-5014-852e-03e436cf321d" [compat] +CSVFiles = "0.16.0" +DataFrames = "0.19.1" +Electron = "0.2, 0.3, 0.4, 1" GraphPlot = "0.3, 0.4" -julia = "1" IteratorInterfaceExtensions = "^0.1.1, ^1" TableTraits = "^0.4.1, ^1" -Electron = "0.2, 0.3, 0.4, 1" -DataFrames = "0.19.1" -CSVFiles = "0.16.0" +julia = "1" [extras] DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" @@ -50,11 +50,12 @@ ExcelReaders = "c04bee98-12a5-510c-87df-2a230cb6e075" MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" NamedArrays = "86f7a689-2022-50b4-a561-43c23ac3c673" Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +Query = "1a8c2f83-1ff3-5112-b086-8aa67b057ba1" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" ZipFile = "a5390f91-8eb1-5f08-bee0-b1d1ffed6cea" -Query = "1a8c2f83-1ff3-5112-b086-8aa67b057ba1" +Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" [targets] -test = ["Pkg", "Statistics", "NamedArrays", "ExcelFiles", "ExcelReaders", "DelimitedFiles", "Random", "Test", "ZipFile", "MacroTools", "Query"] +test = ["Pkg", "Statistics", "NamedArrays", "ExcelFiles", "ExcelReaders", "DelimitedFiles", "Documenter", "Random", "Test", "ZipFile", "MacroTools", "Query"] diff --git a/test/runtests.jl b/test/runtests.jl index 69a45a7ee..6f74f9d56 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,9 +1,11 @@ using Mimi using Test +using Documenter # reduce the chatter during testing Mimi.set_defcomp_verbosity(false) +# run tests @testset "Mimi" begin @info("test_main.jl") @@ -102,3 +104,6 @@ Mimi.set_defcomp_verbosity(false) run(`$(Base.julia_cmd()) --startup-file=no --project=$(joinpath(@__DIR__, "dependencies", ".")) $(joinpath(@__DIR__, "dependencies", "run_dependency_tests.jl"))`) end end + +# run doctests +doctest(Mimi) From c4bdefa71738fcee02fa9415af127f7506106a1d Mon Sep 17 00:00:00 2001 From: lrennels Date: Tue, 1 Oct 2019 17:46:38 -0700 Subject: [PATCH 05/63] Debug doctests --- docs/src/faq.md | 6 +++--- docs/src/installation.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/src/faq.md b/docs/src/faq.md index 8c5a43471..80de545de 100644 --- a/docs/src/faq.md +++ b/docs/src/faq.md @@ -22,8 +22,8 @@ in the component with a vector type, like here: @defcomp MyComp begin cubiccoeff::Vector{Float64} = Parameter() end - - # output + +# output ``` Then construct a model and set the parameter with a multivariate @@ -88,7 +88,7 @@ Mimi.ComponentReference(1-component Mimi.Model: ``` If you want to get a reference to a component after the `add_comp!` call has been made, you can construct the reference as: -```jldoctest; faq2 +```jldoctest faq2; output = false mycomponent = Mimi.ComponentReference(m, :MyComp) # output diff --git a/docs/src/installation.md b/docs/src/installation.md index b6ca19eb7..827d2ee8a 100644 --- a/docs/src/installation.md +++ b/docs/src/installation.md @@ -1,7 +1,7 @@ # Installation Guide ```@meta -DocTestSeup = quote +DocTestSetup = quote using Mimi end ``` From 42d64e092378be260dfd1fb42f3e63bacf7bd74a Mon Sep 17 00:00:00 2001 From: lrennels Date: Tue, 1 Oct 2019 19:40:04 -0700 Subject: [PATCH 06/63] Fix typo --- docs/src/faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/faq.md b/docs/src/faq.md index 80de545de..d778c013b 100644 --- a/docs/src/faq.md +++ b/docs/src/faq.md @@ -1,7 +1,7 @@ # Frequently asked questions ```@meta -DocTestSeup = quote +DocTestSetup = quote using Mimi using Distributions end From be5eec4dcbdcae0268bb517459153ad180355f63 Mon Sep 17 00:00:00 2001 From: lrennels Date: Tue, 1 Oct 2019 19:56:13 -0700 Subject: [PATCH 07/63] add blank lines after output --- docs/src/faq.md | 13 ++++++++++--- docs/src/userguide.md | 2 ++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/docs/src/faq.md b/docs/src/faq.md index d778c013b..4821d6351 100644 --- a/docs/src/faq.md +++ b/docs/src/faq.md @@ -24,11 +24,13 @@ in the component with a vector type, like here: end # output + ``` Then construct a model and set the parameter with a multivariate distribution: + ```jldoctest faq1; output = false # construct a model and add the component @@ -45,9 +47,11 @@ cubicparams = [ [ 0.04413228 -0.01388863 0.00111965] ] -set_param!(m, :MyComp, :cubiccoeff, MvNormal(cubicparams[1,:], cubicparams[2:4,:])) +# LFR TODO - this line errors, should this test be removed? +# set_param!(m, :MyComp, :cubiccoeff, MvNormal(cubicparams[1,:], cubicparams[2:4,:])) # output + ``` Note that we could also load the data fom a file with: @@ -83,18 +87,21 @@ add_comp!(m, MyComp) # output Mimi.ComponentReference(1-component Mimi.Model: - MyComp::Main.MyComp + MyComp::MyComp , :MyComp) + ``` If you want to get a reference to a component after the `add_comp!` call has been made, you can construct the reference as: + ```jldoctest faq2; output = false mycomponent = Mimi.ComponentReference(m, :MyComp) # output Mimi.ComponentReference(1-component Mimi.Model: - MyComp::Main.MyComp + MyComp::MyComp , :MyComp) + ``` You can use this component reference in place of the `set_param!` and `connect_param!` calls. diff --git a/docs/src/userguide.md b/docs/src/userguide.md index 552c19ee4..6cf6c64aa 100644 --- a/docs/src/userguide.md +++ b/docs/src/userguide.md @@ -51,6 +51,7 @@ We define a component in the following way: end # output + ``` The `run_timestep` function is responsible for calculating values for each variable in that component. Note that the component state (defined by the first three arguments) has fields for the Parameters, Variables, and Dimensions of the component you defined. You can access each parameter, variable, or dimension using dot notation as shown above. The fourth argument is an `AbstractTimestep`, i.e., either a `FixedTimestep` or a `VariableTimestep`, which represents which timestep the model is at. @@ -69,6 +70,7 @@ set_dimension!(m, :time, 1850:2200) set_dimension!(m, :regions, ["USA", "EU", "LATAM"]) # output + ``` *A Note on Time Indexes:* It is important to note that the values used for the time index are the *start times* of the timesteps. If the range or array of time values has a uniform timestep length, the model will run *through* the last year of the range with a last timestep period length consistent with the other timesteps. If the time values are provided as an array with non-uniform timestep lengths, the model will run *through* the last year in the array with a last timestep period length *assumed to be one*. From 878ecd42790215ef0c17e37232b99be2340e9ed4 Mon Sep 17 00:00:00 2001 From: lrennels Date: Tue, 1 Oct 2019 20:06:23 -0700 Subject: [PATCH 08/63] Debug doctests, tests passing --- docs/src/faq.md | 4 +++- docs/src/userguide.md | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/src/faq.md b/docs/src/faq.md index 4821d6351..dcbd32865 100644 --- a/docs/src/faq.md +++ b/docs/src/faq.md @@ -86,6 +86,7 @@ set_dimension!(m, :time, collect(2015:5:2110)) add_comp!(m, MyComp) # output + Mimi.ComponentReference(1-component Mimi.Model: MyComp::MyComp , :MyComp) @@ -97,7 +98,8 @@ If you want to get a reference to a component after the `add_comp!` call has bee ```jldoctest faq2; output = false mycomponent = Mimi.ComponentReference(m, :MyComp) -# output +# output + Mimi.ComponentReference(1-component Mimi.Model: MyComp::MyComp , :MyComp) diff --git a/docs/src/userguide.md b/docs/src/userguide.md index 6cf6c64aa..404f6ff42 100644 --- a/docs/src/userguide.md +++ b/docs/src/userguide.md @@ -50,7 +50,7 @@ We define a component in the following way: end end -# output +# output ``` From 40f9edd6630ff2796bf79e05a5989ddedd75a627 Mon Sep 17 00:00:00 2001 From: lrennels Date: Wed, 2 Oct 2019 01:58:17 -0700 Subject: [PATCH 09/63] Add doctests to tutorial 3 --- docs/src/tutorials/tutorial_3.md | 255 ++++++++++++++++++++----------- 1 file changed, 169 insertions(+), 86 deletions(-) diff --git a/docs/src/tutorials/tutorial_3.md b/docs/src/tutorials/tutorial_3.md index 4b1fb7d91..3b3f04705 100644 --- a/docs/src/tutorials/tutorial_3.md +++ b/docs/src/tutorials/tutorial_3.md @@ -1,5 +1,11 @@ # Tutorial 3: Create a Model +```@meta +DocTestSetup = quote + using Mimi +end +``` + This tutorial walks through the steps to create a new model, first a one-region model and then a more complex two-region model. While we will walk through the code step by step below, the full code for implementation is also available in the `examples/tutorial` folder in the [Mimi](https://github.com/mimiframework/Mimi.jl) github repository. @@ -22,7 +28,11 @@ There are two main steps to creating a component, both within the `@defcomp` ma Starting with the economy component, each variable and parameter is listed. If either variables or parameters have a time-dimension, that must be set with `(index=[time])`. -```julia +Next, the `run_timestep` function must be defined along with the various equations of the `grosseconomy` component. In this step, the variables and parameters are linked to this component and must be identified as either a variable or a parameter in each equation. For this example, `v` will refer to variables while `p` refers to parameters. + +It is important to note that `t` below is an `AbstractTimestep`, and the specific API for using this argument are described in detail in the **userguide** in **Advanced Topics: Timesteps and available functions**. + +```jldoctest tutorial3; output = false using Mimi @defcomp grosseconomy begin @@ -35,13 +45,6 @@ using Mimi k0 = Parameter() # Initial level of capital share = Parameter() # Capital share -``` - -Next, the `run_timestep` function must be defined along with the various equations of the `grosseconomy` component. In this step, the variables and parameters are linked to this component and must be identified as either a variable or a parameter in each equation. For this example, `v` will refer to variables while `p` refers to parameters. - -It is important to note that `t` below is an `AbstractTimestep`, and the specific API for using this argument are described in detail in the **userguide** in **Advanced Topics: Timesteps and available functions**. - -```julia function run_timestep(p, v, d, t) # Define an equation for K if is_first(t) @@ -55,11 +58,14 @@ It is important to note that `t` below is an `AbstractTimestep`, and the specifi v.YGROSS[t] = p.tfp[t] * v.K[t]^p.share * p.l[t]^(1-p.share) end end + +# output + ``` Next, the component for greenhouse gas emissions must be created. Although the steps are the same as for the `grosseconomy` component, there is one minor difference. While `YGROSS` was a variable in the `grosseconomy` component, it now enters the `emissions` component as a parameter. This will be true for any variable that becomes a parameter for another component in the model. -```julia +```jldoctest tutorial3; output = false @defcomp emissions begin E = Variable(index=[time]) # Total greenhouse gas emissions sigma = Parameter(index=[time]) # Emissions output ratio @@ -71,6 +77,9 @@ Next, the component for greenhouse gas emissions must be created. Although the v.E[t] = p.YGROSS[t] * p.sigma[t] # Note the p. in front of YGROSS end end + +# output + ``` We can now use Mimi to construct a model that binds the `grosseconomy` and `emissions` components together in order to solve for the emissions level of the global economy over time. In this example, we will run the model for twenty periods with a timestep of five years between each period. @@ -83,7 +92,7 @@ We can now use Mimi to construct a model that binds the `grosseconomy` and `emis * To access model results, use `model_name[:component, :variable_name]`. * To observe model results in a graphical form , [`explore`](@ref) as either `explore(model_name)` to open the UI window, or use `Mimi.plot(model_name, :component_name, :variable_name)` or `Mimi.plot(model_name, :component_name, :parameter_name)` to plot a specific parameter or variable. -```julia +```jldoctest tutorial3; output = false using Mimi @@ -113,13 +122,17 @@ function construct_model() end #end function +# output + +construct_model (generic function with 1 method) + ``` Note that as an alternative to using many of the `set_param!` calls above, one may use the `default` keyword argument in `@defcomp` when first defining a `Variable` or `Parameter`, as shown in `examples/tutorial/01-one-region-model/one-region-model-defaults.jl`. Now we can run the model and examine the results: -```julia +```jldoctest tutorial3; output = false # Run model m = construct_model() run(m) @@ -127,13 +140,37 @@ run(m) # Check model results m[:emissions, :E] +# output + +20-element Array{Union{Missing, Float64},1}: + 4211.090591062387 + 15079.467021779814 + 23922.34250656177 + 30255.835991903466 + 35175.69763623216 + 39293.007327689294 + 42947.659714791596 + 46344.92375399115 + 49617.22023134532 + 52854.33568269569 + 56119.657629233516 + 59459.60027273144 + 62909.41007665139 + 66496.902005524 + 70244.9426237597 + 74173.13994450058 + 78299.0143500136 + 82638.82192356508 + 87208.1411195294 + 92022.29655492865 +``` +Finally we can visualize the results: +```julia # Plot model results -Mimi.plot(m, :emissions, :E) +Mimi.plot(m, :emissions, :E); # Observe all model result graphs in UI explore(m) - - ``` ## Constructing A Multi-Region Model @@ -150,110 +187,119 @@ To create a three-regional model, we will again start by constructing the grosse As this model is also more complex and spread across several files, we will also take this as a chance to introduce the custom of using [Modules](https://docs.julialang.org/en/v1/manual/modules/index.html) to package Mimi models, as shown below. -```julia +```jldoctest tutorial3; output = false using Mimi - @defcomp grosseconomy begin - regions = Index() #Note that a regional index is defined here - - YGROSS = Variable(index=[time, regions]) # Gross output - K = Variable(index=[time, regions]) # Capital - l = Parameter(index=[time, regions]) # Labor - tfp = Parameter(index=[time, regions]) # Total factor productivity - s = Parameter(index=[time, regions]) # Savings rate - depk = Parameter(index=[regions]) # Depreciation rate on capital - Note that it only has a region index - k0 = Parameter(index=[regions]) # Initial level of capital - share = Parameter() # Capital share - - function run_timestep(p, v, d, t) - - # Note that the regional dimension is used below and parameters and - variables are indexed by 'r' + regions = Index() #Note that a regional index is defined here + + YGROSS = Variable(index=[time, regions]) #Gross output + K = Variable(index=[time, regions]) #Capital + l = Parameter(index=[time, regions]) #Labor + tfp = Parameter(index=[time, regions]) #Total factor productivity + s = Parameter(index=[time, regions]) #Savings rate + depk = Parameter(index=[regions]) #Depreciation rate on capital - Note that it only has a region index + k0 = Parameter(index=[regions]) #Initial level of capital + share = Parameter() #Capital share + + function run_timestep(p, v, d, t) + # Note that the regional dimension is defined in d and parameters and variables are indexed by 'r' + + # Define an equation for K + for r in d.regions + if is_first(t) + v.K[t,r] = p.k0[r] + else + v.K[t,r] = (1 - p.depk[r])^5 * v.K[t-1,r] + v.YGROSS[t-1,r] * p.s[t-1,r] * 5 + end + end + + # Define an equation for YGROSS + for r in d.regions + v.YGROSS[t,r] = p.tfp[t,r] * v.K[t,r]^p.share * p.l[t,r]^(1-p.share) + end + end +end - # Define an equation for K - for r in d.regions - if is_first(t) - v.K[t,r] = p.k0[r] - else - v.K[t,r] = (1 - p.depk[r])^5 * v.K[t-1,r] + v.YGROSS[t-1,r] * p.s[t-1,r] * 5 - end - end +# output - # Define an equation for YGROSS - for r in d.regions - v.YGROSS[t,r] = p.tfp[t,r] * v.K[t,r]^p.share * p.l[t,r]^(1-p.share) - end - end -end ``` Save this component as **`gross_economy.jl`** -```julia +```jldoctest tutorial3; output = false using Mimi #Make sure to call Mimi again @defcomp emissions begin - regions = Index() # The regions index must be specified for each component + regions = Index() # The regions index must be specified for each component + + E = Variable(index=[time, regions]) # Total greenhouse gas emissions + E_Global = Variable(index=[time]) # Global emissions (sum of regional emissions) + sigma = Parameter(index=[time, regions]) # Emissions output ratio + YGROSS = Parameter(index=[time, regions]) # Gross output - Note that YGROSS is now a parameter + + # function init(p, v, d) + # end + + function run_timestep(p, v, d, t) + # Define an equation for E + for r in d.regions + v.E[t,r] = p.YGROSS[t,r] * p.sigma[t,r] + end + + # Define an equation for E_Global + for r in d.regions + v.E_Global[t] = sum(v.E[t,:]) + end + end - E = Variable(index=[time, regions]) # Total greenhouse gas emissions - E_Global = Variable(index=[time]) # Global emissions (sum of regional emissions) - sigma = Parameter(index=[time, regions]) # Emissions output ratio - YGROSS = Parameter(index=[time, regions]) # Gross output - Note that YGROSS is now a parameter - - function run_timestep(p, v, d, t) +end - # Define an eqation for E - for r in d.regions - v.E[t,r] = p.YGROSS[t,r] * p.sigma[t,r] - end +# output - # Define an equation for E_Global - for r in d.regions - v.E_Global[t] = sum(v.E[t,:]) - end - end -end ``` Save this component as **`emissions.jl`** Let's create a file with all of our parameters that we can call into our model. This will help keep things organized as the number of components and regions increases. Each column refers to parameter values for a region, reflecting differences in initial parameter values and growth rates between the three regions. -```julia -l = Array(Float64,20,3) +```jldoctest tutorial3; output = false +l = Array{Float64}(undef, 20, 3) for t in 1:20 - l[t,1] = (1. + 0.015)^t *2000 - l[t,2] = (1. + 0.02)^t * 1250 - l[t,3] = (1. + 0.03)^t * 1700 + l[t,1] = (1. + 0.015)^t *2000 + l[t,2] = (1. + 0.02)^t * 1250 + l[t,3] = (1. + 0.03)^t * 1700 end -tfp = Array(Float64,20,3) +tfp = Array{Float64}(undef, 20, 3) for t in 1:20 - tfp[t,1] = (1 + 0.06)^t * 3.2 - tfp[t,2] = (1 + 0.03)^t * 1.8 - tfp[t,3] = (1 + 0.05)^t * 2.5 + tfp[t,1] = (1 + 0.06)^t * 3.2 + tfp[t,2] = (1 + 0.03)^t * 1.8 + tfp[t,3] = (1 + 0.05)^t * 2.5 end -s = Array(Float64,20,3) +s = Array{Float64}(undef, 20, 3) for t in 1:20 - s[t,1] = 0.21 - s[t,2] = 0.15 - s[t,3] = 0.28 + s[t,1] = 0.21 + s[t,2] = 0.15 + s[t,3] = 0.28 end depk = [0.11, 0.135 ,0.15] -k0 = [50.5, 22., 33.5] +k0 = [50.5, 22., 33.5] -sigma = Array(Float64,20,3) +sigma = Array{Float64}(undef, 20, 3) for t in 1:20 - sigma[t,1] = (1. - 0.05)^t * 0.58 - sigma[t,2] = (1. - 0.04)^t * 0.5 - sigma[t,3] = (1. - 0.045)^t * 0.6 + sigma[t,1] = (1. - 0.05)^t * 0.58 + sigma[t,2] = (1. - 0.04)^t * 0.5 + sigma[t,3] = (1. - 0.045)^t * 0.6 end + +# output + ``` Save this file as **`region_parameters.jl`** -The final step is to create a module. +The final step is to create a module: ```julia module MyModel @@ -265,7 +311,8 @@ include("gross_economy.jl") include("emissions.jl") export construct_MyModel - +``` +```jldoctest tutorial3; output = false function construct_MyModel() m = Model() @@ -287,13 +334,18 @@ function construct_MyModel() set_param!(m, :emissions, :sigma, sigma) connect_param!(m, :emissions, :YGROSS, :grosseconomy, :YGROSS) - return m + return m +end -end #function +# output -end #end module +construct_MyModel (generic function with 1 method) ``` +```julia +end #module +``` + Save this file as **`MyModel.jl`** We can now run the model and evaluate the results. @@ -303,13 +355,44 @@ using Mimi include("MyModel.jl") using .MyModel +``` +```jldoctest tutorial3; output = false m = construct_MyModel() run(m) # Check results m[:emissions, :E_Global] +# output + +20-element Array{Union{Missing, Float64},1}: + 2392.079742190377 + 7740.882236708259 + 11842.440651248193 + 14629.668992409268 + 16686.547618646313 + 18338.39368484932 + 19763.668705801665 + 21066.519405994735 + 22310.85541553882 + 23537.444423151617 + 24773.181203244094 + 26036.421133213866 + 27340.180766955593 + 28694.115410299266 + 30105.7665949292 + 31581.36120424167 + 33126.32978664035 + 34745.64653516074 + 36444.054899836294 + 38226.21934898662 +``` +```julia # Observe model result graphs explore(m) ``` + +```@meta +DocTestSetup = nothing +``` From 8d14a3cb029e0b1d27d3840b2efec6892e02a8ba Mon Sep 17 00:00:00 2001 From: lrennels Date: Sun, 6 Oct 2019 14:12:10 -0700 Subject: [PATCH 10/63] Add Project.toml packages; add doctests to Tutorial 1 --- .travis.yml | 1 + docs/Project.toml | 6 +++ docs/src/faq.md | 64 +------------------------------ docs/src/tutorials/tutorial_1.md | 66 +++++++++++++++++++++++++------- 4 files changed, 61 insertions(+), 76 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1922e79cd..fe7bd27f9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,6 +34,7 @@ jobs: julia: 1.1 os: linux script: + - julia --project=docs/ -e 'using Pkg; Pkg.Registry.add(RegistrySpec(url = "https://github.com/mimiframework/MimiRegistry.git"))' - julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()' - julia --project=docs/ --color=yes docs/make.jl after_success: skip diff --git a/docs/Project.toml b/docs/Project.toml index 161cfae50..e6e673bb1 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -2,8 +2,14 @@ Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" Mimi = "e4e893b0-ee5e-52ea-8111-44b3bdec128c" +MimiDICE2010 = "4f2c5d70-42a7-11e9-1de8-c370bd984083" +MimiFUND = "b3ba11de-429f-11e9-29f7-cb478ab96e7c" +StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" [compat] Distributions = "0.21" Documenter = "~0.21" Mimi = "0.9.3" +MimiDICE2010 = "0.1" +MimiFUND = "3.11" +StatsBase = "0.32" diff --git a/docs/src/faq.md b/docs/src/faq.md index dcbd32865..3a0bf9a3e 100644 --- a/docs/src/faq.md +++ b/docs/src/faq.md @@ -10,71 +10,11 @@ end The name is probably an acronym for "Modular Integrated Modeling Interface", but we are not sure. What is certain is that it came up during a dinner that [Bob](http://www.bobkopp.net/), [David](http://www.david-anthoff.com/) and [Sol](http://www.solomonhsiang.com/) had in 2015. David thinks that Bob invented the name, Bob doesn't remember and Sol thinks the waiter might have come up with it (although we can almost certainly rule that option out). It certainly is better than the previous name "IAMF". We now use "Mimi" purely as a name of the package, not as an acronym. -## How do I use a multivariate distribution for a parameter within a component? - -You might want to use a multivariate distribution to capture the -covariance between estimated coefficient parameters. For example, an estimated -polynomial can be represented as a multivariate Normal distribution, -with a variance-covariance matrix. To use this, define the parameter -in the component with a vector type, like here: - -```jldoctest faq1; output = false -@defcomp MyComp begin - cubiccoeff::Vector{Float64} = Parameter() -end - -# output - -``` - -Then construct a model and set the parameter with a multivariate -distribution: - - -```jldoctest faq1; output = false - -# construct a model and add the component -m = Model() -set_dimension!(m, :time, collect(2015:5:2110)) -add_comp!(m, MyComp) - -# First line: linear, quadratic, cubic -# Lines 2-4: covariance matrix -cubicparams = [ - [-3.233303 1.911123 -0.1018884]; - [ 1.9678593 -0.57211657 0.04413228]; - [-0.57211657 0.17500949 -0.01388863]; - [ 0.04413228 -0.01388863 0.00111965] -] - -# LFR TODO - this line errors, should this test be removed? -# set_param!(m, :MyComp, :cubiccoeff, MvNormal(cubicparams[1,:], cubicparams[2:4,:])) - -# output - -``` - -Note that we could also load the data fom a file with: - -```julia -cubicparams = readdlm("../data/cubicparams.csv", ',') -``` -where `../data/cubicparams.csv` would be a parameter definition file that looks something like this: -```julia -# Example estimated polynomial parameter -# First line: linear, quadratic, cubic -# Lines 2-4: covariance matrix --3.233303,1.911123,-.1018884 -1.9678593,-.57211657,.04413228 --.57211657,.17500949,-.01388863 -.04413228,-.01388863,.00111965 -``` - ## How do I use component references? Component references allow you to write cleaner model code when connecting components. The `add_comp!` function returns a reference to the component that you just added: -```jldoctest faq2; output = false +```jldoctest faq1; output = false # create a component @defcomp MyComp begin # empty @@ -95,7 +35,7 @@ Mimi.ComponentReference(1-component Mimi.Model: If you want to get a reference to a component after the `add_comp!` call has been made, you can construct the reference as: -```jldoctest faq2; output = false +```jldoctest faq1; output = false mycomponent = Mimi.ComponentReference(m, :MyComp) # output diff --git a/docs/src/tutorials/tutorial_1.md b/docs/src/tutorials/tutorial_1.md index 49965e9b8..46291f83f 100644 --- a/docs/src/tutorials/tutorial_1.md +++ b/docs/src/tutorials/tutorial_1.md @@ -1,5 +1,11 @@ # Tutorial 1: Run an Existing Model +```@meta +DocTestSetup = quote + using Mimi +end +``` + This tutorial walks through the steps to download, run, and view the output of an existing model. There are several existing models publically available on Github for the purposes of this tutorial we will use [The Climate Framework for Uncertainty, Negotiation and Distribution (FUND)](http://www.fund-model.org), available on Github [here](https://github.com/fund-model/fund). Working through the following tutorial will require: @@ -30,34 +36,43 @@ In order to run FUND, you will need to have the packages `Distributions` and `St Now open a julia REPL and type -``` +```jldoctest tutorial1; output = false using MimiFUND -``` -to access the public API to FUND, which currently includes the function `getfund`, a function that returns a version of fund allowing for different user specifications. + +# output ``` -m = getfund() +to access the public API to FUND, which currently includes the function `MimiFUND.get_model` (which can also be called with the exported and identical function `getfund`). This function returns a version of fund allowing for different user specifications. + +```jldoctest tutorial1; output = false +m = MimiFUND.get_model() run(m) + +# output + ``` -Note that 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 `getModelX` or `construct_ModelX` which returns a version of the model, and can allow for model customization within the call. +Note that 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. -In this case, the function `getfund` has the signature -``` -getfund(; nsteps = default_nsteps, datadir = default_datadir, params = default_params) +In this case, the function `get_model` has the signature +```julia +MimiFUND.get_model(; nsteps = default_nsteps, datadir = default_datadir, params = default_params) ``` Thus there are no required arguments, although the user can input `nsteps` to define the number of timesteps (years in this case) the model runs for, `datadir` to define the location of the input data, and `params`, a dictionary definining the parameters of the model. For example, if you wish to see only the first 100 timesteps,you may use: -``` +```julia using MimiFUND -m = getfund(nsteps = 100) +m = MimiFUND.get_model(nsteps = 100) run(m) ``` ### Step 3. Access Results: Values After the model has been run, you may access the results (the calculated variable values in each component) in a few different ways. Start off by importing the Mimi package to your space with -``` +```jldoctest tutorial1; output = false using Mimi + +# output + ``` First of all, you may use the `getindex` syntax as follows: @@ -68,9 +83,14 @@ m[:ComponentName, :VariableName][100] # returns just the 100th value ``` Indexing into a model with the name of the component and variable will return an array with values from each timestep. You may index into this array to get one value (as in the second line, which returns just the 100th value). Note that if the requested variable is two-dimensional, then a 2-D array will be returned. For example, try taking a look at the `income` variable of the `socioeconomic` component using the code below: -``` +```jldoctest tutorial1; output = false m[:socioeconomic, :income] m[:socioeconomic, :income][100] + +# output + +20980.834204000927 + ``` You may also get data in the form of a dataframe, which will display the corresponding index labels rather than just a raw array. The syntax for this uses [`getdataframe`](@ref) as follows: @@ -83,8 +103,22 @@ getdataframe(m, :Component1=>:Var1, :Component2=>:Var2) # request variables from ``` Try doing this for the `income` variable of the `socioeconomic` component using: -``` +```jldoctest tutorial1; output = false getdataframe(m, :socioeconomic=>:income) # request one variable from one component +getdataframe(m, :socioeconomic=>:income)[1:5,:] # first five rows + +# output + +5×3 DataFrames.DataFrame +│ Row │ time │ regions │ income │ +│ │ Int64 │ String │ Float64⍰ │ +├─────┼───────┼─────────┼──────────┤ +│ 1 │ 1950 │ USA │ 1643.9 │ +│ 2 │ 1950 │ CAN │ 84.8225 │ +│ 3 │ 1950 │ WEU │ 1913.32 │ +│ 4 │ 1950 │ JPK │ 616.022 │ +│ 5 │ 1950 │ ANZ │ 119.058 │ + ``` ### Step 4. Access Results: Plots and Graphs @@ -98,7 +132,7 @@ Mimi provides support for plotting using [VegaLite](https://github.com/vega/vega If you wish to explore the results graphically, use the explorer UI, described [here](https://www.mimiframework.org/Mimi.jl/stable/userguide/#Plotting-and-the-Explorer-UI-1) in Section 5 of the Mimi User Guide. To explore all variables and parameters of FUND in a dynamic UI app window, use the [`explore`](@ref) function called with the model as the required first argument, and the optional argument of the `title` The menu on the left hand side will list each element in a label formatted as `component: variable/parameter`. -``` +```julia explore(m, title = "My Window") ``` Alternatively, in order to view just one parameter or variable, call the function [`explore`](@ref) as below to return a plot object and automatically display the plot in a viewer, assuming [`explore`](@ref) is the last command executed. This call will return the type `VegaLite.VLSpec`, which you may interact with using the API described in the [VegaLite.jl](https://github.com/fredo-dedup/VegaLite.jl) documentation. For example, [VegaLite.jl](https://github.com/fredo-dedup/VegaLite.jl) plots can be saved as [PNG](https://en.wikipedia.org/wiki/Portable_Network_Graphics), [SVG](https://en.wikipedia.org/wiki/Scalable_Vector_Graphics), [PDF](https://en.wikipedia.org/wiki/PDF) and [EPS](https://en.wikipedia.org/wiki/Encapsulated_PostScript) files. You may save a plot using the `save` function. Note that saving an interactive plot in a non-interactive file format, such as .pdf or .svg will result in a warning `WARN Can not resolve event source: window`, but the plot will be saved as a static image. If you wish to preserve interactive capabilities, you may save it using the .vegalite file extension. If you then open this file in Jupyter lab, the interactive aspects will be preserved. @@ -127,3 +161,7 @@ plot_comp_graph(m, "MyFilePath.png") ### Step 4. Tutorial 2 Next, feel free to move on to the second tutorial, which will go into depth on how to **modify** an existing model such as FUND! + +```@meta +DocTestSetup = nothing +``` From 0760c0f1cc605edd8e64afa192ce70fac3114fa5 Mon Sep 17 00:00:00 2001 From: lrennels Date: Sun, 6 Oct 2019 15:27:28 -0700 Subject: [PATCH 11/63] Add more doctesting --- docs/src/tutorials/tutorial_1.md | 6 +-- docs/src/tutorials/tutorial_2.md | 37 ++++++++++++----- docs/src/tutorials/tutorial_4.md | 62 ++++++++++++++++++++++------- docs/src/tutorials/tutorial_main.md | 10 ++--- 4 files changed, 83 insertions(+), 32 deletions(-) diff --git a/docs/src/tutorials/tutorial_1.md b/docs/src/tutorials/tutorial_1.md index 46291f83f..0df8f0dc2 100644 --- a/docs/src/tutorials/tutorial_1.md +++ b/docs/src/tutorials/tutorial_1.md @@ -11,7 +11,7 @@ This tutorial walks through the steps to download, run, and view the output of a Working through the following tutorial will require: - [Julia v1.1.0](https://julialang.org/downloads/) or higher -- [Mimi v0.8.0](https://github.com/mimiframework/Mimi.jl) +- [Mimi v0.9.4](https://github.com/mimiframework/Mimi.jl) If you have not yet prepared these, go back to the main tutorial page and follow the instructions for their download. @@ -56,7 +56,7 @@ Note that these steps should be relatively consistent across models, where a rep In this case, the function `get_model` has the signature ```julia -MimiFUND.get_model(; nsteps = default_nsteps, datadir = default_datadir, params = default_params) +get_model(; nsteps = default_nsteps, datadir = default_datadir, params = default_params) ``` Thus there are no required arguments, although the user can input `nsteps` to define the number of timesteps (years in this case) the model runs for, `datadir` to define the location of the input data, and `params`, a dictionary definining the parameters of the model. For example, if you wish to see only the first 100 timesteps,you may use: ```julia @@ -90,7 +90,6 @@ m[:socioeconomic, :income][100] # output 20980.834204000927 - ``` You may also get data in the form of a dataframe, which will display the corresponding index labels rather than just a raw array. The syntax for this uses [`getdataframe`](@ref) as follows: @@ -118,7 +117,6 @@ getdataframe(m, :socioeconomic=>:income)[1:5,:] # first five rows │ 3 │ 1950 │ WEU │ 1913.32 │ │ 4 │ 1950 │ JPK │ 616.022 │ │ 5 │ 1950 │ ANZ │ 119.058 │ - ``` ### Step 4. Access Results: Plots and Graphs diff --git a/docs/src/tutorials/tutorial_2.md b/docs/src/tutorials/tutorial_2.md index 3b06f37cc..28b275536 100644 --- a/docs/src/tutorials/tutorial_2.md +++ b/docs/src/tutorials/tutorial_2.md @@ -1,11 +1,17 @@ # Tutorial 2: Modify an Existing Model +```@meta +DocTestSetup = quote + using Mimi +end +``` + This tutorial walks through the steps to modify an existing model. There are several existing models publically available on Github, and for the purposes of this tutorial we will use MimiDICE2010, available on Github [here](https://github.com/anthofflab/MimiDICE2010.jl). Working through the following tutorial will require: - [Julia v1.1.0](https://julialang.org/downloads/) or higher -- [Mimi v0.8.0](https://github.com/mimiframework/Mimi.jl) +- [Mimi v0.9.4](https://github.com/mimiframework/Mimi.jl) If you have not yet prepared these, go back to the main tutorial page and follow the instructions for their download. @@ -53,17 +59,20 @@ You have now successfully downloaded DICE to your local machine. The next step is to run DICE. If you wish to first get more aquainted with the model itself, take a look at the provided online documentation. Now run DICE using the provided API for the package: -``` +```jldoctest tutorial2; output = false using MimiDICE2010 -m = construct_dice() +m = MimiDICE2010.get_model() run(m) + +# output + ``` -Note that 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 `getModelX` or `construct_ModelX` which returns a version of the model, and can allow for model customization within the call. +Note that 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. -In this case, the function `construct_dice` has the signature +In this case, the function `MimiDICE2010.get_model()` has the signature ``` -construct_dice(params=nothing) +get_model(params=nothing) ``` Thus there are no required arguments, although the user can input `params`, a dictionary definining the parameters of the model. @@ -71,19 +80,25 @@ 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. For example, 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`. If you wanted to change this value from its default value of `3.200` to `3.000` in both components,you would use the following code: -```julia +```jldoctest tutorial2; output = false update_param!(m, :fco22x, 3.000) run(m) + +# output + ``` A more complex example may 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 const ts = 10 const years = collect(2000:ts:2500) nyears = length(years) set_dimension!(m, :time, years) + +# output + ``` Next, create a dictionary `params` with one entry (k, v) per external parameter by name k to value v. Each key k must be a symbol or convert to a symbol matching the name of an external parameter that already exists in the model definition. Part of this dictionary may look like: @@ -99,7 +114,7 @@ params[:S] = repeat([0.23], nyears) Now you simply update the parameters listen in `params` and re-run the model with -``` +```julia update_params!(m, params, update_timesteps=true) run(m) ``` @@ -119,3 +134,7 @@ If you wish to modify the component structure we recommend you also look into th ## Component and Structural Modifications: DICE Example This example is in progress and will be built out soon. + +```@meta +DocTestSetup = nothing +``` diff --git a/docs/src/tutorials/tutorial_4.md b/docs/src/tutorials/tutorial_4.md index b00cd85a8..430bda03b 100644 --- a/docs/src/tutorials/tutorial_4.md +++ b/docs/src/tutorials/tutorial_4.md @@ -1,11 +1,18 @@ # Tutorial 4: Sensitivity Analysis (SA) Support +```@meta +DocTestSetup = quote + using Mimi + using Distributions +end +``` + This tutorial walks through the sensitivity analysis (SA) functionality of Mimi, including core routines and examples. We will start with looking at using the SA routines with the Mimi two-region model provided in the Mimi repository at `examples/tutorial/02-two-region-model`, and then build out to examine its use on [The Climate Framework for Uncertainty, Negotiation and Distribution (FUND)](http://www.fund-model.org), available on Github [here](https://github.com/fund-model/fund), Working through the following tutorial will require: -- [Julia v1.0.0](https://julialang.org/downloads/) or higher -- [Mimi v0.6.0](https://github.com/mimiframework/Mimi.jl) +- [Julia v1.1.0](https://julialang.org/downloads/) or higher +- [Mimi v0.9.4](https://github.com/mimiframework/Mimi.jl) If you have not yet prepared these, go back to the main tutorial page and follow the instructions for their download. @@ -37,7 +44,7 @@ The `@defsim` macro, which defines random variables (RVs) which are assigned dis simple random sampling being the default. Other options include Latin Hypercube Sampling, and Sobol Sampling. -```julia +```jldoctest tutorial4; output = false sd = @defsim begin # Define random variables. The rv() is required to disambiguate an # RV definition name = Dist(args...) from application of a distribution @@ -72,19 +79,28 @@ sd = @defsim begin # assignment of RVs, above. save(grosseconomy.K, grosseconomy.YGROSS, emissions.E, emissions.E_Global) -end +end; + +# output + +LHSData(Tuple{Symbol,Symbol,Float64}[(:name1, :name2, 0.7), (:name1, :name3, 0.5)]) + ``` ### Step 3. Optional User-Defined Functions Next, create the user-defined `print_result` function, which can be called as a post-trial function by `run`. - ```julia + ```jldoctest tutorial4; output = false # Optional user functions can be called just before or after a trial is run function print_result(m::Model, sim_inst::SimulationInstance, trialnum::Int) ci = Mimi.compinstance(m.mi, :emissions) value = Mimi.get_variable_value(ci, :E_Global) println("$(ci.comp_id).E_Global: $value") end + +# output + +print_result (generic function with 1 method) ``` where `tup` is a tuple of scenario arguments representing one element in the cross-product @@ -246,45 +262,59 @@ Case: We want to do an SCC calculation across a base and marginal model of `Mimi 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 `sim_def`. In this case we only define one random variable, `t2xco2`, but note there could be any number of random variables defined here. -```julia +```jldoctest tutorial4; output = false using Mimi using MimiDICE2010 +using Distributions -# define your trial number +# define your trial number and discount rates N = 1000000 +discount_rates = [0.3, 0.5, 0.7] # define your simulation (defaults to Monte Carlo sampling) sd = @defsim begin - t2xco2 = MyDistribution() + t2xco2 = Truncated(Gamma(6.47815626,0.547629469), 1.0, Inf) # a dummy distribution end + +# output + +MCSData() ``` Next, we prepare our post-trial calculations by setting up a `scc_results` array to hold the results. We then define a `post_trial_function` called `my_scc_calculation` which will calculate the SCC for that run. -```julia +```jldoctest tutorial4; output = false scc_results = zeros(N, length(discount_rates)) function my_scc_calculation(sim_inst::SimulationInstance, trialnum::Int, ntimesteps::Int, tup::Tuple) - base, marginal = sim_inst.models + base = sim_inst.models[1] + marginal = sim_inst.models[2] base_damages = base[:neteconomy, :DAMAGES] marg_damages = marginal[:neteconomy, :DAMAGES] for (i, df) in enumerate(dfs) scc_results[trialnum, i] = sum(df .* (marg_damages .- base_damages)) end end + +# output + +my_scc_calculation (generic function with 1 method) ``` Now that we have our post-trial function, we can proceed to obtain our two models and run the simulation. ```julia # Build the base model -base = construct_dice() +base = MimiDICE2010.get_model() -#Build the marginal model, which here involves a dummy function `construct_marginal_dice()` that you will need to write -marginal = construct_marginal_dice(year) +#Build the marginal model +mm = MimiDICE2010.get_marginal_model(m, year = 2015) # Run -si = run(sd, [base, marginal], N; trials_output_filename = "ecs_sample.csv", post_trial_func = my_scc_calculation) +si = run(sd, [mm.base, mm.marginal], N; trials_output_filename = "ecs_sample.csv", post_trial_func = my_scc_calculation) + +# output + ``` ## Simulation Modification Functions A small set of unexported functions are available to modify an existing `SimulationDefinition`. The functions include: @@ -297,3 +327,7 @@ A small set of unexported functions are available to modify an existing `Simulat * `addSave!` * `set_payload!` * `payload` + +```@meta +DocTestSetup = nothing +``` diff --git a/docs/src/tutorials/tutorial_main.md b/docs/src/tutorials/tutorial_main.md index 0d15a8892..de7b70bc5 100644 --- a/docs/src/tutorials/tutorial_main.md +++ b/docs/src/tutorials/tutorial_main.md @@ -33,13 +33,13 @@ _Additional AERE Workshop Tutorials: The Mimi developement team recently partici ## Requirements and Initial Setup -These tutorials require [Julia v1.0.0](https://julialang.org/downloads/) and [Mimi v0.6.0](https://github.com/mimiframework/Mimi.jl), or later. +These tutorials require [Julia v1.1.0](https://julialang.org/downloads/) and [Mimi v0.6.0](https://github.com/mimiframework/Mimi.jl), or later. To use the following tutorials, follow the steps below. -1. Download the latest version of Julia [here](https://julialang.org/downloads/), making sure that your downloaded version is v1.0.0 or later. +1. Download the latest version of Julia [here](https://julialang.org/downloads/), making sure that your downloaded version is v1.1.0 or later. -2. Open a Julia REPL, and enter `]` to enter the [Pkg REPL](https://docs.julialang.org/en/v1/stdlib/Pkg/index.html) mode, and then type `add Mimi` to install the latest tagged version of Mimi, which must be version 0.6.0 or later. +2. Open a Julia REPL, and enter `]` to enter the [Pkg REPL](https://docs.julialang.org/en/v1/stdlib/Pkg/index.html) mode, and then type `add Mimi` to install the latest tagged version of Mimi, which must be version 0.9.4 or later. ``` pkg> add Mimi @@ -53,10 +53,10 @@ pkg> registry add https://github.com/mimiframework/MimiRegistry.git You only need to run this command once on a computer. -From there you will be add any of the registered packages, such as MimiRICE2010.jl by running the following command at the julia package REPL: +From there you will be add any of the registered packages, such as MimiDICE2010.jl by running the following command at the julia package REPL: ```julia -pkg> add MimiRICE2010 +pkg> add MimiDICE2010 ``` 5. We also recommend that you frequently update your packages and requirements using the `update` command, which can be abbreviated `up`: From 234b02f3881470d4d80f0b41c8b91742b8797959 Mon Sep 17 00:00:00 2001 From: lrennels Date: Mon, 7 Oct 2019 11:15:06 -0700 Subject: [PATCH 12/63] Clean up doctests; all tests passing --- docs/src/faq.md | 13 ++++--------- docs/src/tutorials/tutorial_1.md | 1 + docs/src/tutorials/tutorial_2.md | 2 ++ docs/src/tutorials/tutorial_3.md | 2 +- docs/src/tutorials/tutorial_4.md | 2 ++ docs/src/userguide.md | 1 + 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/docs/src/faq.md b/docs/src/faq.md index 3a0bf9a3e..109ce2b29 100644 --- a/docs/src/faq.md +++ b/docs/src/faq.md @@ -3,7 +3,6 @@ ```@meta DocTestSetup = quote using Mimi - using Distributions end ``` ## What's up with the name? @@ -24,26 +23,22 @@ end m = Model() set_dimension!(m, :time, collect(2015:5:2110)) add_comp!(m, MyComp) +typeof(MyComp) # note the type is a Mimi Component Definition # output -Mimi.ComponentReference(1-component Mimi.Model: - MyComp::MyComp -, :MyComp) - +Mimi.ComponentDef ``` If you want to get a reference to a component after the `add_comp!` call has been made, you can construct the reference as: ```jldoctest faq1; output = false mycomponent = Mimi.ComponentReference(m, :MyComp) +typeof(mycomponent) # note the type is a Mimi Component Reference # output -Mimi.ComponentReference(1-component Mimi.Model: - MyComp::MyComp -, :MyComp) - +Mimi.ComponentReference ``` You can use this component reference in place of the `set_param!` and `connect_param!` calls. diff --git a/docs/src/tutorials/tutorial_1.md b/docs/src/tutorials/tutorial_1.md index 0df8f0dc2..95da7bf88 100644 --- a/docs/src/tutorials/tutorial_1.md +++ b/docs/src/tutorials/tutorial_1.md @@ -3,6 +3,7 @@ ```@meta DocTestSetup = quote using Mimi + using MimiFUND end ``` diff --git a/docs/src/tutorials/tutorial_2.md b/docs/src/tutorials/tutorial_2.md index 28b275536..c88c9f51f 100644 --- a/docs/src/tutorials/tutorial_2.md +++ b/docs/src/tutorials/tutorial_2.md @@ -3,6 +3,7 @@ ```@meta DocTestSetup = quote using Mimi + using MimiDICE2010 end ``` @@ -99,6 +100,7 @@ set_dimension!(m, :time, years) # output +[2000, 2010, 2020, 2030, 2040, 2050, 2060, 2070, 2080, 2090 … 2400, 2410, 2420, 2430, 2440, 2450, 2460, 2470, 2480, 2490, 2500] ``` Next, create a dictionary `params` with one entry (k, v) per external parameter by name k to value v. Each key k must be a symbol or convert to a symbol matching the name of an external parameter that already exists in the model definition. Part of this dictionary may look like: diff --git a/docs/src/tutorials/tutorial_3.md b/docs/src/tutorials/tutorial_3.md index 3b3f04705..cae00a55f 100644 --- a/docs/src/tutorials/tutorial_3.md +++ b/docs/src/tutorials/tutorial_3.md @@ -13,7 +13,7 @@ While we will walk through the code step by step below, the full code for implem Working through the following tutorial will require: - [Julia v1.1.0](https://julialang.org/downloads/) or higher -- [Mimi v0.8.0](https://github.com/mimiframework/Mimi.jl) +- [Mimi v0.9.4](https://github.com/mimiframework/Mimi.jl) If you have not yet prepared these, go back to the main tutorial page and follow the instructions for their download. diff --git a/docs/src/tutorials/tutorial_4.md b/docs/src/tutorials/tutorial_4.md index 430bda03b..43e1fa84a 100644 --- a/docs/src/tutorials/tutorial_4.md +++ b/docs/src/tutorials/tutorial_4.md @@ -3,6 +3,8 @@ ```@meta DocTestSetup = quote using Mimi + using MimiFUND + using MimiDICE2010 using Distributions end ``` diff --git a/docs/src/userguide.md b/docs/src/userguide.md index 404f6ff42..0d2b68146 100644 --- a/docs/src/userguide.md +++ b/docs/src/userguide.md @@ -71,6 +71,7 @@ set_dimension!(m, :regions, ["USA", "EU", "LATAM"]) # output +["USA", "EU", "LATAM"] ``` *A Note on Time Indexes:* It is important to note that the values used for the time index are the *start times* of the timesteps. If the range or array of time values has a uniform timestep length, the model will run *through* the last year of the range with a last timestep period length consistent with the other timesteps. If the time values are provided as an array with non-uniform timestep lengths, the model will run *through* the last year in the array with a last timestep period length *assumed to be one*. From 9735f5720845d76a69449d6f184bc3f61ef59042 Mon Sep 17 00:00:00 2001 From: Cora Kingdon Date: Mon, 7 Oct 2019 16:51:24 -0400 Subject: [PATCH 13/63] start updating tutorial 4 --- docs/src/tutorials/tutorial_4.md | 98 ++++++++++++-------------------- 1 file changed, 35 insertions(+), 63 deletions(-) diff --git a/docs/src/tutorials/tutorial_4.md b/docs/src/tutorials/tutorial_4.md index 430bda03b..34a35dd68 100644 --- a/docs/src/tutorials/tutorial_4.md +++ b/docs/src/tutorials/tutorial_4.md @@ -4,10 +4,12 @@ DocTestSetup = quote using Mimi using Distributions + include("../../../examples/tutorial/02-two-region-model/main.jl") + m = model end ``` -This tutorial walks through the sensitivity analysis (SA) functionality of Mimi, including core routines and examples. We will start with looking at using the SA routines with the Mimi two-region model provided in the Mimi repository at `examples/tutorial/02-two-region-model`, and then build out to examine its use on [The Climate Framework for Uncertainty, Negotiation and Distribution (FUND)](http://www.fund-model.org), available on Github [here](https://github.com/fund-model/fund), +This tutorial walks through the sensitivity analysis (SA) functionality of Mimi, including core routines and examples. We will start with looking at using the SA routines with the Mimi two-region model provided in the Mimi repository at `examples/tutorial/02-two-region-model`, and then build out to examine its use on [The Climate Framework for Uncertainty, Negotiation and Distribution (FUND)](http://www.fund-model.org), available on Github [here](https://github.com/fund-model/fund). Working through the following tutorial will require: @@ -16,7 +18,7 @@ Working through the following tutorial will require: If you have not yet prepared these, go back to the main tutorial page and follow the instructions for their download. -Futhermore, if you are not yet comfortable with downloading (only needs to be done once) and running FUND, refer to Tutorial 1 for instructions. Carry out **Steps 1 and 2** from Tutorial 1, and then return to continue with this tutorial. Note that FUND is only requred for the second example in this tutorial. +Futhermore, if you are not yet comfortable with downloading (only needs to be done once) and running FUND, refer to Tutorial 1 for instructions. Carry out **Steps 1 and 2** from Tutorial 1 and then return to continue with this tutorial. Note that FUND is only required for the second example in this tutorial. ## The API @@ -26,7 +28,7 @@ These are described further below. We will refer separately to two types, `Simul ## Two-Region Model Example -This section will walk through the simple example provided in `"Mimi.jl/test/sim/test_defsim.jl"`. +This section will walk through a simple example of how to define a simulation, run the simulation for a given model, and access the outputs. ### Step 1. Setup First, set up for the tutorial as follows with the necessary packages and `main.jl` script for the two-region example. You should have `Mimi` installed by now, and if you do not have `Distributions`, take a moment to add that package using by entering `]` to enter the [Pkg REPL](https://docs.julialang.org/en/v1/stdlib/Pkg/index.html) mode and then typing `add Distributions`. @@ -40,9 +42,11 @@ m = model # defined by 2-region model ``` ### Step 2. Define Random Variables -The `@defsim` macro, which defines random variables (RVs) which are assigned distributions and associated with model parameters, is the first step in the process. It also selects the sampling method, with -simple random sampling being the default. Other options include Latin Hypercube Sampling, and Sobol -Sampling. +The `@defsim` macro is the first step in the process, and returns a SimulationDefinition. The following syntax allows users to define random variables (RVs) as distributions, +and associate model parameters with the defined random variables. + +The `@defsim` macro also selects the sampling method. Simple random sampling (also called Monte Carlo sampling) is the default. +Other options include Latin Hypercube sampling and Sobol sampling. ```jldoctest tutorial4; output = false sd = @defsim begin @@ -84,71 +88,24 @@ end; # output LHSData(Tuple{Symbol,Symbol,Float64}[(:name1, :name2, 0.7), (:name1, :name3, 0.5)]) - -``` - -### Step 3. Optional User-Defined Functions -Next, create the user-defined `print_result` function, which can be called as a post-trial function by `run`. - - ```jldoctest tutorial4; output = false -# Optional user functions can be called just before or after a trial is run -function print_result(m::Model, sim_inst::SimulationInstance, trialnum::Int) - ci = Mimi.compinstance(m.mi, :emissions) - value = Mimi.get_variable_value(ci, :E_Global) - println("$(ci.comp_id).E_Global: $value") -end - -# output - -print_result (generic function with 1 method) ``` -where `tup` is a tuple of scenario arguments representing one element in the cross-product -of all scenario value vectors. In situations in which you want the SA loop to run only -some of the models, the remainder of the runs can be handled using a `pre_trial_func` or -`post_trial_func`. +### Step 3. Run Simulation -### Step 4. Run Simulation - - Finally, use `run` which runs a simulation, indicating the `sim_def`, the `models` is a model, marginal model, or list of models to be run by your `sim_def` simulation, and `samplesize` the number of samples to use. - - In it's simplest use, the `run` function generates and iterates over generated trial data, perturbing a chosen subset of Mimi's "external parameters", based on the defined distributions, and then runs the given Mimi model(s). The function retuns an instance of `SimulationInstance`, holding a copy of the original `SimulationDef` in addition to trials information (`trials`, `current_trial`, and `current_data`), the model list`models`, and results information in `results`. Optionally, trial values and/or model results are saved to CSV files. Optionally, trial values and/or model results are saved to CSV files. Note that if there is concern about in-memory storage space for the results, use the `results_in_memory` flag set to `false` to incrementally clear the results from memory. View the internals documentation for **critical and useful details on the full signature of this function**: - -``` -function Base.run(sim_def::SimulationDef{T}, models::Union{Vector{Model}, Model}, samplesize::Int; - ntimesteps::Int=typemax(Int), - trials_output_filename::Union{Nothing, AbstractString}=nothing, - results_output_dir::Union{Nothing, AbstractString}=nothing, - pre_trial_func::Union{Nothing, Function}=nothing, - post_trial_func::Union{Nothing, Function}=nothing, - scenario_func::Union{Nothing, Function}=nothing, - scenario_placement::ScenarioLoopPlacement=OUTER, - scenario_args=nothing, - results_in_memory::Bool=true) where T <: AbstractSimulationData -``` +Next, use the `run` function to run the simulation for the specified SimulationDefinition, model (or list of models), and number of trials. View the internals documentation [here](https://github.com/mimiframework/Mimi.jl/blob/master/docs/src/internals/montecarlo.md) for **critical and useful details on the full signature of the `run` function**. Here, we first employ `run` to obtain results: -```julia +```jldoctest tutorial4; output = false -# Run 100 trials and save results to the indicated directories, one CSV file per RV for the results +# Run 100 trials, and optionally save results to the indicated directories si = run(sd, m, 100; trials_output_filename = "/tmp/trialdata.csv", results_output_dir="/tmp/Mimi") # Explore the results saved in-memory -results = si[:grosseconomy, :K] # model index chosen defaults to 1 -``` - -and then again using our user-defined post-trial function as the `post_trial_func` parameter: - -```julia -# Same thing but with a post-trial function -si = run(sd, m, 100; trials_output_filename = "/tmp/trialdata.csv", results_output_dir="/tmp/Mimi", post_trial_func=print_result) - -# Explore the results saved in-memory -results = si[:grosseconomy, :K] # model index chosen defaults to 1 +results = si[:grosseconomy, :K] ``` -### Step 5. Explore and Plot Results +### Step 4. Explore and Plot Results As described in the internals documentation [here](https://github.com/mimiframework/Mimi.jl/blob/master/docs/src/internals/montecarlo.md), Mimi provides both `explore` and `Mimi.plot` to explore the results of both a run `Model` and a run `SimulationInstance`. @@ -177,9 +134,24 @@ p = Mimi.plot(si, :grosseconomy, :K) save("MyFigure.png", p) ``` -## Advanced Post-trial Functions +## Advanced Features + +While the model above employed a fairly simple `post_trial_func` that printed out results, the post-trial functions can be used for more complex calculations that need to be made for each simulation run. This can be especially useful, for example, for calculating net present value of damages or the social cost of carbon (SCC) for each run. -While the model above employed a fairly simple `post_trial_func` that printed out results, the post-trial functions can be used for more complex calculations that need to be made for each simulation run. This can be especially usefu, for example,for calculating net present value of damages or the social cost of carbon (SCC) for each run. +In it's simplest use, the `run` function generates and iterates over generated trial data, perturbing a chosen subset of Mimi's "external parameters", based on the defined distributions, and then runs the given Mimi model(s). The function returns a `SimulationInstance`, holding a copy of the original `SimulationDef` in addition to trials information (`trials`, `current_trial`, and `current_data`), the model list`models`, and results information in `results`. Optionally, trial values and/or model results are saved to CSV files. Optionally, trial values and/or model results are saved to CSV files. Note that if there is concern about in-memory storage space for the results, use the `results_in_memory` flag set to `false` to incrementally clear the results from memory. View the internals documentation for **critical and useful details on the full signature of this function**: + +``` +function Base.run(sim_def::SimulationDef{T}, models::Union{Vector{Model}, Model}, samplesize::Int; + ntimesteps::Int=typemax(Int), + trials_output_filename::Union{Nothing, AbstractString}=nothing, + results_output_dir::Union{Nothing, AbstractString}=nothing, + pre_trial_func::Union{Nothing, Function}=nothing, + post_trial_func::Union{Nothing, Function}=nothing, + scenario_func::Union{Nothing, Function}=nothing, + scenario_placement::ScenarioLoopPlacement=OUTER, + scenario_args=nothing, + results_in_memory::Bool=true) where T <: AbstractSimulationData +``` ### NPV of Damages @@ -267,8 +239,8 @@ using Mimi using MimiDICE2010 using Distributions -# define your trial number and discount rates -N = 1000000 +# define your number of trials and discount rates +N = 1000 discount_rates = [0.3, 0.5, 0.7] # define your simulation (defaults to Monte Carlo sampling) From ec8373cfc66732ca343fed7bd9e96d192f7ad016 Mon Sep 17 00:00:00 2001 From: lrennels Date: Mon, 7 Oct 2019 14:20:00 -0700 Subject: [PATCH 14/63] Update Documenter version --- docs/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Project.toml b/docs/Project.toml index e6e673bb1..6bc748bc0 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -8,7 +8,7 @@ StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" [compat] Distributions = "0.21" -Documenter = "~0.21" +Documenter = "0.23" Mimi = "0.9.3" MimiDICE2010 = "0.1" MimiFUND = "3.11" From 306ba46c4cdbc861caad555ca52a15d05dbd7126 Mon Sep 17 00:00:00 2001 From: lrennels Date: Mon, 7 Oct 2019 22:00:45 -0700 Subject: [PATCH 15/63] Use setdocmeta! per v0.23 breaking change --- docs/make.jl | 2 ++ docs/src/faq.md | 9 --------- docs/src/installation.md | 10 ---------- docs/src/tutorials/tutorial_1.md | 11 ----------- docs/src/tutorials/tutorial_2.md | 11 ----------- docs/src/tutorials/tutorial_3.md | 10 ---------- docs/src/tutorials/tutorial_4.md | 13 ------------- docs/src/userguide.md | 10 ---------- 8 files changed, 2 insertions(+), 74 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index 6439365db..4d58fe423 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,5 +1,7 @@ using Documenter, Mimi +DocMeta.setdocmeta!(Mimi, :DocTestSetup, :(using Mimi; using Distributions; using MimiDICE2010; using MimiFUND); recursive=true) + makedocs( modules = [Mimi], sitename = "Mimi.jl", diff --git a/docs/src/faq.md b/docs/src/faq.md index 109ce2b29..928468af9 100644 --- a/docs/src/faq.md +++ b/docs/src/faq.md @@ -1,10 +1,5 @@ # Frequently asked questions -```@meta -DocTestSetup = quote - using Mimi -end -``` ## What's up with the name? The name is probably an acronym for "Modular Integrated Modeling Interface", but we are not sure. What is certain is that it came up during a dinner that [Bob](http://www.bobkopp.net/), [David](http://www.david-anthoff.com/) and [Sol](http://www.solomonhsiang.com/) had in 2015. David thinks that Bob invented the name, Bob doesn't remember and Sol thinks the waiter might have come up with it (although we can almost certainly rule that option out). It certainly is better than the previous name "IAMF". We now use "Mimi" purely as a name of the package, not as an acronym. @@ -50,7 +45,3 @@ The line `set_param!(model, :MyComponent, :myparameter, myvalue)` can be written ## References in place of `connect_param!` The line `connect_param!(model, :MyComponent, :myparameter, :YourComponent, :yourparameter)` can be written as `mycomponent[:myparameter] = yourcomponent[:yourparameter]`, where `mycomponent` and `yourcomponent` are component references. - -```@meta -DocTestSetup = nothing -``` \ No newline at end of file diff --git a/docs/src/installation.md b/docs/src/installation.md index 827d2ee8a..04833d597 100644 --- a/docs/src/installation.md +++ b/docs/src/installation.md @@ -1,11 +1,5 @@ # Installation Guide -```@meta -DocTestSetup = quote - using Mimi -end -``` - This guide will briefly explain how to install julia and Mimi. ## Installing julia @@ -51,7 +45,3 @@ The best way to get started with Mimi is to work through the **Tutorials**. The [Mimi](https://github.com/mimiframework/Mimi.jl) github repository also has links to various models that are based on Mimi, and looking through their code can be instructive. Finally, when in doubt, ask your question in the [Mimi Framework forum](https://forum.mimiframework.org) or post an [Issue](https://github.com/mimiframework/Mimi.jl/issues) to the Github repository if you have a specific request for the development team. Don't be shy about either option, we would much prefer to be inundated with lots of questions and help people out than people give up on Mimi! - -```@meta -DocTestSetup = nothing -``` diff --git a/docs/src/tutorials/tutorial_1.md b/docs/src/tutorials/tutorial_1.md index 95da7bf88..ee79afb2d 100644 --- a/docs/src/tutorials/tutorial_1.md +++ b/docs/src/tutorials/tutorial_1.md @@ -1,12 +1,5 @@ # Tutorial 1: Run an Existing Model -```@meta -DocTestSetup = quote - using Mimi - using MimiFUND -end -``` - This tutorial walks through the steps to download, run, and view the output of an existing model. There are several existing models publically available on Github for the purposes of this tutorial we will use [The Climate Framework for Uncertainty, Negotiation and Distribution (FUND)](http://www.fund-model.org), available on Github [here](https://github.com/fund-model/fund). Working through the following tutorial will require: @@ -160,7 +153,3 @@ plot_comp_graph(m, "MyFilePath.png") ### Step 4. Tutorial 2 Next, feel free to move on to the second tutorial, which will go into depth on how to **modify** an existing model such as FUND! - -```@meta -DocTestSetup = nothing -``` diff --git a/docs/src/tutorials/tutorial_2.md b/docs/src/tutorials/tutorial_2.md index c88c9f51f..08830364d 100644 --- a/docs/src/tutorials/tutorial_2.md +++ b/docs/src/tutorials/tutorial_2.md @@ -1,12 +1,5 @@ # Tutorial 2: Modify an Existing Model -```@meta -DocTestSetup = quote - using Mimi - using MimiDICE2010 -end -``` - This tutorial walks through the steps to modify an existing model. There are several existing models publically available on Github, and for the purposes of this tutorial we will use MimiDICE2010, available on Github [here](https://github.com/anthofflab/MimiDICE2010.jl). Working through the following tutorial will require: @@ -136,7 +129,3 @@ If you wish to modify the component structure we recommend you also look into th ## Component and Structural Modifications: DICE Example This example is in progress and will be built out soon. - -```@meta -DocTestSetup = nothing -``` diff --git a/docs/src/tutorials/tutorial_3.md b/docs/src/tutorials/tutorial_3.md index cae00a55f..76db63a2f 100644 --- a/docs/src/tutorials/tutorial_3.md +++ b/docs/src/tutorials/tutorial_3.md @@ -1,11 +1,5 @@ # Tutorial 3: Create a Model -```@meta -DocTestSetup = quote - using Mimi -end -``` - This tutorial walks through the steps to create a new model, first a one-region model and then a more complex two-region model. While we will walk through the code step by step below, the full code for implementation is also available in the `examples/tutorial` folder in the [Mimi](https://github.com/mimiframework/Mimi.jl) github repository. @@ -392,7 +386,3 @@ m[:emissions, :E_Global] explore(m) ``` - -```@meta -DocTestSetup = nothing -``` diff --git a/docs/src/tutorials/tutorial_4.md b/docs/src/tutorials/tutorial_4.md index f1ab42579..6f46ef656 100644 --- a/docs/src/tutorials/tutorial_4.md +++ b/docs/src/tutorials/tutorial_4.md @@ -1,14 +1,5 @@ # Tutorial 4: Sensitivity Analysis (SA) Support -```@meta -DocTestSetup = quote - using Mimi - using MimiFUND - using MimiDICE2010 - using Distributions -end -``` - This tutorial walks through the sensitivity analysis (SA) functionality of Mimi, including core routines and examples. We will start with looking at using the SA routines with the Mimi two-region model provided in the Mimi repository at `examples/tutorial/02-two-region-model`, and then build out to examine its use on [The Climate Framework for Uncertainty, Negotiation and Distribution (FUND)](http://www.fund-model.org), available on Github [here](https://github.com/fund-model/fund), Working through the following tutorial will require: @@ -329,7 +320,3 @@ A small set of unexported functions are available to modify an existing `Simulat * `add_save!` * `set_payload!` * `payload` - -```@meta -DocTestSetup = nothing -``` diff --git a/docs/src/userguide.md b/docs/src/userguide.md index 0d2b68146..0c8cc2554 100644 --- a/docs/src/userguide.md +++ b/docs/src/userguide.md @@ -1,11 +1,5 @@ # User Guide -```@meta -DocTestSetup = quote - using Mimi -end -``` - ## Overview See the Tutorials for in-depth examples of Mimi's functionality. @@ -294,7 +288,3 @@ If defined for a specific component, this function will run **before** the times end ``` - -```@meta -DocTestSetup = nothing -``` From 136b0a7c23f81daaf892336ef5f9599b208f1f80 Mon Sep 17 00:00:00 2001 From: lrennels Date: Tue, 8 Oct 2019 00:48:44 -0700 Subject: [PATCH 16/63] Add using statements to docstrings; metadata not working --- docs/src/faq.md | 2 ++ docs/src/tutorials/tutorial_2.md | 11 ++++++++++- docs/src/tutorials/tutorial_3.md | 2 +- docs/src/tutorials/tutorial_4.md | 10 ++++++++-- docs/src/userguide.md | 4 ++++ 5 files changed, 25 insertions(+), 4 deletions(-) diff --git a/docs/src/faq.md b/docs/src/faq.md index 928468af9..a3ec6f3ed 100644 --- a/docs/src/faq.md +++ b/docs/src/faq.md @@ -9,6 +9,8 @@ The name is probably an acronym for "Modular Integrated Modeling Interface", but Component references allow you to write cleaner model code when connecting components. The `add_comp!` function returns a reference to the component that you just added: ```jldoctest faq1; output = false +using Mimi + # create a component @defcomp MyComp begin # empty diff --git a/docs/src/tutorials/tutorial_2.md b/docs/src/tutorials/tutorial_2.md index 08830364d..6317183d5 100644 --- a/docs/src/tutorials/tutorial_2.md +++ b/docs/src/tutorials/tutorial_2.md @@ -72,7 +72,16 @@ Thus there are no required arguments, although the user can input `params`, a di ### Step 3. Altering Parameters -In the case that you wish to alter an exogenous parameter, you may use the [`update_param!`](@ref) function. For example, 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`. If you wanted to change this value from its default value of `3.200` to `3.000` in both components,you would use the following code: +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 +using Mimi + +# output + +``` + +For example, 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`. If you wanted to change this value from its default value of `3.200` to `3.000` in both components,you would use the following code: ```jldoctest tutorial2; output = false update_param!(m, :fco22x, 3.000) diff --git a/docs/src/tutorials/tutorial_3.md b/docs/src/tutorials/tutorial_3.md index 76db63a2f..0894f7ccd 100644 --- a/docs/src/tutorials/tutorial_3.md +++ b/docs/src/tutorials/tutorial_3.md @@ -27,7 +27,7 @@ Next, the `run_timestep` function must be defined along with the various equatio It is important to note that `t` below is an `AbstractTimestep`, and the specific API for using this argument are described in detail in the **userguide** in **Advanced Topics: Timesteps and available functions**. ```jldoctest tutorial3; output = false -using Mimi +using Mimi # start by importing the Mimi package to your space @defcomp grosseconomy begin YGROSS = Variable(index=[time]) # Gross output diff --git a/docs/src/tutorials/tutorial_4.md b/docs/src/tutorials/tutorial_4.md index 6f46ef656..6168ec111 100644 --- a/docs/src/tutorials/tutorial_4.md +++ b/docs/src/tutorials/tutorial_4.md @@ -24,10 +24,16 @@ This section will walk through the simple example provided in `"Mimi.jl/test/sim ### Step 1. Setup First, set up for the tutorial as follows with the necessary packages and `main.jl` script for the two-region example. You should have `Mimi` installed by now, and if you do not have `Distributions`, take a moment to add that package using by entering `]` to enter the [Pkg REPL](https://docs.julialang.org/en/v1/stdlib/Pkg/index.html) mode and then typing `add Distributions`. -```julia -cd() # Mimi-directory-path is a placeholder for the string describing the path of the Mimi directory +```jldoctest tutorial4; output = false +using Mimi using Distributions +# output + +``` + +```julia +cd() # Mimi-directory-path is a placeholder for the string describing the path of the Mimi directory include("examples/tutorial/02-two-region-model/main.jl") m = model # defined by 2-region model ``` diff --git a/docs/src/userguide.md b/docs/src/userguide.md index 0c8cc2554..573fd8fe1 100644 --- a/docs/src/userguide.md +++ b/docs/src/userguide.md @@ -25,6 +25,8 @@ The user must define a `run_timestep` function for each component. We define a component in the following way: ```jldoctest; output = false +using Mimi + @defcomp MyComponentName begin regions = Index() @@ -59,6 +61,8 @@ To access the data in a parameter or to assign a value to a variable, you must u 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. ```jldoctest; output = false +using Mimi + m = Model() set_dimension!(m, :time, 1850:2200) set_dimension!(m, :regions, ["USA", "EU", "LATAM"]) From 14d6512ddc563d14153164d79453f0ac1761118d Mon Sep 17 00:00:00 2001 From: lrennels Date: Tue, 8 Oct 2019 00:55:30 -0700 Subject: [PATCH 17/63] Add compat for Documenter --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index 3f50622bc..249d2f30f 100644 --- a/Project.toml +++ b/Project.toml @@ -43,6 +43,7 @@ GraphPlot = "0.3, 0.4" IteratorInterfaceExtensions = "^0.1.1, ^1" TableTraits = "^0.4.1, ^1" julia = "1" +Documenter = "0.23" [extras] DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" From af24d03595cea79cef24b04928ec8fb42242e22d Mon Sep 17 00:00:00 2001 From: lrennels Date: Tue, 8 Oct 2019 01:41:26 -0700 Subject: [PATCH 18/63] Remove Documenter from compat --- Project.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Project.toml b/Project.toml index 249d2f30f..3f50622bc 100644 --- a/Project.toml +++ b/Project.toml @@ -43,7 +43,6 @@ GraphPlot = "0.3, 0.4" IteratorInterfaceExtensions = "^0.1.1, ^1" TableTraits = "^0.4.1, ^1" julia = "1" -Documenter = "0.23" [extras] DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" From dee6c540d897a62b541c697757343f4621bd9a19 Mon Sep 17 00:00:00 2001 From: Cora Kingdon Date: Tue, 8 Oct 2019 09:34:03 -0400 Subject: [PATCH 19/63] remove include statement from tutorial 4 --- docs/src/tutorials/tutorial_4.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/src/tutorials/tutorial_4.md b/docs/src/tutorials/tutorial_4.md index aacf89bbf..3552f6390 100644 --- a/docs/src/tutorials/tutorial_4.md +++ b/docs/src/tutorials/tutorial_4.md @@ -6,7 +6,6 @@ DocTestSetup = quote using MimiFUND using MimiDICE2010 using Distributions - include("../../../examples/tutorial/02-two-region-model/main.jl") m = model end ``` From f4ce8682209e05c1dbb4d5338f3abcb4a4de2899 Mon Sep 17 00:00:00 2001 From: lrennels Date: Tue, 8 Oct 2019 09:45:39 -0700 Subject: [PATCH 20/63] Remvoe doctest from runtests.jl file --- test/runtests.jl | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 2fb180577..36988f539 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -103,6 +103,3 @@ using Documenter run(`$(Base.julia_cmd()) --startup-file=no --project=$(joinpath(@__DIR__, "dependencies", ".")) $(joinpath(@__DIR__, "dependencies", "run_dependency_tests.jl"))`) end end - -# run doctests -doctest(Mimi) From ec563fa208f7244b59f2a2e3061e456fc5e14617 Mon Sep 17 00:00:00 2001 From: Cora Kingdon Date: Tue, 8 Oct 2019 14:11:27 -0400 Subject: [PATCH 21/63] updates to tutorial_main --- docs/src/tutorials/tutorial_main.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/tutorials/tutorial_main.md b/docs/src/tutorials/tutorial_main.md index de7b70bc5..bad4983ef 100644 --- a/docs/src/tutorials/tutorial_main.md +++ b/docs/src/tutorials/tutorial_main.md @@ -12,8 +12,6 @@ The following terminology is used throughout the documentation. ## Available Tutorials -_Additional AERE Workshop Tutorials: The Mimi developement team recently participated in the 2019 Association of Environmental and Resource Economists (AERE) summer conference during the pre-conference workshop on Advances in Integrated Assessment Models. This included both a presentation and a hands-on session demonstrating various use cases for Mimi. The Github repository [here](https://github.com/davidanthoff/teaching-2019-aere-workshop) contains a) all slides from the workshop and b) all the code from the hands on sessions, which may be of interest to Mimi users. Importantly note that the linked code represents as a snapwhot of Mimi at the time of the workshop, and **will not** be updated to reflect new changes._ - 1. **Run an Existing Model** [Tutorial 1: Run an Existing Model](@ref) steps through the tasks to download, run, and view the results of a registered model such as [FUND](http://www.fund-model.org). It should be usable for all users, including first-time users, and is a good place to start when learning to use Mimi. @@ -31,9 +29,11 @@ _Additional AERE Workshop Tutorials: The Mimi developement team recently partici [Tutorial 4: Sensitivity Analysis (SA) Support](@ref) explores Mimi's Sensitivity Analysis support, using both the simple 2-Region tutorial model and [FUND](http://www.fund-model.org) examples. +_Additional AERE Workshop Tutorials: The Mimi developement team recently participated in the 2019 Association of Environmental and Resource Economists (AERE) summer conference during the pre-conference workshop on Advances in Integrated Assessment Models. This included both a presentation and a hands-on session demonstrating various use cases for Mimi. The Github repository [here](https://github.com/davidanthoff/teaching-2019-aere-workshop) contains a) all slides from the workshop and b) all the code from the hands on sessions, which may be of interest to Mimi users. Importantly note that the linked code represents as a snapshot of Mimi at the time of the workshop, and **will not** be updated to reflect new changes._ + ## Requirements and Initial Setup -These tutorials require [Julia v1.1.0](https://julialang.org/downloads/) and [Mimi v0.6.0](https://github.com/mimiframework/Mimi.jl), or later. +These tutorials require [Julia v1.1.0](https://julialang.org/downloads/) and [Mimi v0.9.4](https://github.com/mimiframework/Mimi.jl), or later. To use the following tutorials, follow the steps below. From 2841be9818ab290489e5d7723cad07408c7cd833 Mon Sep 17 00:00:00 2001 From: Cora Kingdon Date: Tue, 8 Oct 2019 14:13:50 -0400 Subject: [PATCH 22/63] fix spacing in compdefs --- docs/src/tutorials/tutorial_3.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/src/tutorials/tutorial_3.md b/docs/src/tutorials/tutorial_3.md index 0894f7ccd..8c8455496 100644 --- a/docs/src/tutorials/tutorial_3.md +++ b/docs/src/tutorials/tutorial_3.md @@ -31,13 +31,13 @@ using Mimi # start by importing the Mimi package to your space @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 + 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 @@ -61,7 +61,7 @@ Next, the component for greenhouse gas emissions must be created. Although the ```jldoctest tutorial3; output = false @defcomp emissions begin - E = Variable(index=[time]) # Total greenhouse gas emissions + 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 From 71f953731a4e7499a7807b8dae704b1aec277e0d Mon Sep 17 00:00:00 2001 From: Cora Kingdon Date: Tue, 8 Oct 2019 14:28:23 -0400 Subject: [PATCH 23/63] rename two-region-model to multi-region-model --- benchmark/RegionTutorialBenchmarks.jl | 6 +++--- benchmark/benchmarks.jl | 2 +- docs/src/internals/montecarlo.md | 2 +- docs/src/tutorials/tutorial_3.md | 2 +- docs/src/tutorials/tutorial_4.md | 8 ++++---- .../emissions.jl | 0 .../gross_economy.jl | 0 .../main.jl | 2 +- .../multi-region-model.jl} | 0 .../region_parameters.jl | 0 test/mcs/test-model-2/main.jl | 2 +- .../{two-region-model.jl => multi-region-model.jl} | 0 test/mcs/test-model/main.jl | 2 +- test/mcs/test_defmcs.jl | 2 +- test/mcs/test_defmcs_sobol.jl | 2 +- test/test_explorer_sim.jl | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) rename examples/tutorial/{02-two-region-model => 02-multi-region-model}/emissions.jl (100%) rename examples/tutorial/{02-two-region-model => 02-multi-region-model}/gross_economy.jl (100%) rename examples/tutorial/{02-two-region-model => 02-multi-region-model}/main.jl (79%) rename examples/tutorial/{02-two-region-model/two-region-model.jl => 02-multi-region-model/multi-region-model.jl} (100%) rename examples/tutorial/{02-two-region-model => 02-multi-region-model}/region_parameters.jl (100%) rename test/mcs/test-model-2/{two-region-model.jl => multi-region-model.jl} (100%) diff --git a/benchmark/RegionTutorialBenchmarks.jl b/benchmark/RegionTutorialBenchmarks.jl index 13fa1e7ad..a77d88645 100644 --- a/benchmark/RegionTutorialBenchmarks.jl +++ b/benchmark/RegionTutorialBenchmarks.jl @@ -1,11 +1,11 @@ const tutorialpath = normpath(joinpath(@__DIR__, "..", "examples", "tutorial")) -const tworegionpath = joinpath(tutorialpath, "02-two-region-model") +const multiregionpath = joinpath(tutorialpath, "02-multi-region-model") const oneregionpath = joinpath(tutorialpath, "01-one-region-model") function run_oneregion() include(joinpath(oneregionpath, "one-region-model.jl")) end -function run_tworegion() - include(joinpath(tworegionpath, "main.jl")) +function run_multiregion() + include(joinpath(multiregionpath, "main.jl")) end diff --git a/benchmark/benchmarks.jl b/benchmark/benchmarks.jl index e9a6089d8..6ec12225b 100644 --- a/benchmark/benchmarks.jl +++ b/benchmark/benchmarks.jl @@ -5,5 +5,5 @@ include("getindex.jl") const SUITE = BenchmarkGroup() SUITE["one_region"] = @benchmarkable run_oneregion() -SUITE["two_regions"] = @benchmarkable run_tworegion() +SUITE["multi_regions"] = @benchmarkable run_multiregion() SUITE["getindex"] = @benchmarkable run_getindex() \ No newline at end of file diff --git a/docs/src/internals/montecarlo.md b/docs/src/internals/montecarlo.md index 6c5924d76..12065c014 100644 --- a/docs/src/internals/montecarlo.md +++ b/docs/src/internals/montecarlo.md @@ -311,7 +311,7 @@ sd = @defsim begin end Mimi.reset_compdefs() -include("../../examples/tutorial/02-two-region-model/main.jl") +include("../../examples/tutorial/02-multi-region-model/main.jl") m = model diff --git a/docs/src/tutorials/tutorial_3.md b/docs/src/tutorials/tutorial_3.md index 8c8455496..a9a01f391 100644 --- a/docs/src/tutorials/tutorial_3.md +++ b/docs/src/tutorials/tutorial_3.md @@ -1,6 +1,6 @@ # Tutorial 3: Create a Model -This tutorial walks through the steps to create a new model, first a one-region model and then a more complex two-region model. +This tutorial walks through the steps to create a new model, first a one-region model and then a more complex multi-region model. While we will walk through the code step by step below, the full code for implementation is also available in the `examples/tutorial` folder in the [Mimi](https://github.com/mimiframework/Mimi.jl) github repository. diff --git a/docs/src/tutorials/tutorial_4.md b/docs/src/tutorials/tutorial_4.md index 33c944063..49c1ee51b 100644 --- a/docs/src/tutorials/tutorial_4.md +++ b/docs/src/tutorials/tutorial_4.md @@ -1,6 +1,6 @@ # Tutorial 4: Sensitivity Analysis (SA) Support -This tutorial walks through the sensitivity analysis (SA) functionality of Mimi, including core routines and examples. We will start with looking at using the SA routines with the Mimi two-region model provided in the Mimi repository at `examples/tutorial/02-two-region-model`, and then build out to examine its use on [The Climate Framework for Uncertainty, Negotiation and Distribution (FUND)](http://www.fund-model.org), available on Github [here](https://github.com/fund-model/fund). +This tutorial walks through the sensitivity analysis (SA) functionality of Mimi, including core routines and examples. We will start with looking at using the SA routines with the Mimi multi-region model provided in the Mimi repository at `examples/tutorial/02-multi-region-model`, and then build out to examine its use on [The Climate Framework for Uncertainty, Negotiation and Distribution (FUND)](http://www.fund-model.org), available on Github [here](https://github.com/fund-model/fund). Working through the following tutorial will require: @@ -17,12 +17,12 @@ The best current documentation on the SA API is the internals documentation [her These are described further below. We will refer separately to two types, `SimulationDef` and `SimulationInstance`. They are referred to as `sim_def` and `sim_inst` respectively as function arguments, and `sd` and `si` respectively as local variables. -## Two-Region Model Example +## Multi-Region Model Example This section will walk through a simple example of how to define a simulation, run the simulation for a given model, and access the outputs. ### Step 1. Setup -First, set up for the tutorial as follows with the necessary packages and `main.jl` script for the two-region example. You should have `Mimi` installed by now, and if you do not have `Distributions`, take a moment to add that package using by entering `]` to enter the [Pkg REPL](https://docs.julialang.org/en/v1/stdlib/Pkg/index.html) mode and then typing `add Distributions`. +First, set up for the tutorial as follows with the necessary packages and `main.jl` script for the multi-region example. You should have `Mimi` installed by now, and if you do not have `Distributions`, take a moment to add that package using by entering `]` to enter the [Pkg REPL](https://docs.julialang.org/en/v1/stdlib/Pkg/index.html) mode and then typing `add Distributions`. ```jldoctest tutorial4; output = false using Mimi @@ -34,7 +34,7 @@ using Distributions ```julia cd() # Mimi-directory-path is a placeholder for the string describing the path of the Mimi directory -include("examples/tutorial/02-two-region-model/main.jl") +include("examples/tutorial/02-multi-region-model/main.jl") m = model # defined by 2-region model ``` diff --git a/examples/tutorial/02-two-region-model/emissions.jl b/examples/tutorial/02-multi-region-model/emissions.jl similarity index 100% rename from examples/tutorial/02-two-region-model/emissions.jl rename to examples/tutorial/02-multi-region-model/emissions.jl diff --git a/examples/tutorial/02-two-region-model/gross_economy.jl b/examples/tutorial/02-multi-region-model/gross_economy.jl similarity index 100% rename from examples/tutorial/02-two-region-model/gross_economy.jl rename to examples/tutorial/02-multi-region-model/gross_economy.jl diff --git a/examples/tutorial/02-two-region-model/main.jl b/examples/tutorial/02-multi-region-model/main.jl similarity index 79% rename from examples/tutorial/02-two-region-model/main.jl rename to examples/tutorial/02-multi-region-model/main.jl index 2da8d679f..ff7de8f0b 100644 --- a/examples/tutorial/02-two-region-model/main.jl +++ b/examples/tutorial/02-multi-region-model/main.jl @@ -1,6 +1,6 @@ using Mimi -include("two-region-model.jl") +include("multi-region-model.jl") using .MyModel model = construct_MyModel() diff --git a/examples/tutorial/02-two-region-model/two-region-model.jl b/examples/tutorial/02-multi-region-model/multi-region-model.jl similarity index 100% rename from examples/tutorial/02-two-region-model/two-region-model.jl rename to examples/tutorial/02-multi-region-model/multi-region-model.jl diff --git a/examples/tutorial/02-two-region-model/region_parameters.jl b/examples/tutorial/02-multi-region-model/region_parameters.jl similarity index 100% rename from examples/tutorial/02-two-region-model/region_parameters.jl rename to examples/tutorial/02-multi-region-model/region_parameters.jl diff --git a/test/mcs/test-model-2/main.jl b/test/mcs/test-model-2/main.jl index 2da8d679f..ff7de8f0b 100644 --- a/test/mcs/test-model-2/main.jl +++ b/test/mcs/test-model-2/main.jl @@ -1,6 +1,6 @@ using Mimi -include("two-region-model.jl") +include("multi-region-model.jl") using .MyModel model = construct_MyModel() diff --git a/test/mcs/test-model-2/two-region-model.jl b/test/mcs/test-model-2/multi-region-model.jl similarity index 100% rename from test/mcs/test-model-2/two-region-model.jl rename to test/mcs/test-model-2/multi-region-model.jl diff --git a/test/mcs/test-model/main.jl b/test/mcs/test-model/main.jl index 2da8d679f..ff7de8f0b 100644 --- a/test/mcs/test-model/main.jl +++ b/test/mcs/test-model/main.jl @@ -1,6 +1,6 @@ using Mimi -include("two-region-model.jl") +include("multi-region-model.jl") using .MyModel model = construct_MyModel() diff --git a/test/mcs/test_defmcs.jl b/test/mcs/test_defmcs.jl index fdfed77e2..1ae7cffd7 100644 --- a/test/mcs/test_defmcs.jl +++ b/test/mcs/test_defmcs.jl @@ -12,7 +12,7 @@ using Mimi: modelinstance, compinstance, get_var_value, OUTER, INNER, ReshapedDi using CSVFiles: load -include("test-model-2/two-region-model.jl") +include("test-model-2/multi-region-model.jl") using .MyModel m = construct_MyModel() diff --git a/test/mcs/test_defmcs_sobol.jl b/test/mcs/test_defmcs_sobol.jl index a76355caf..9e51ae124 100644 --- a/test/mcs/test_defmcs_sobol.jl +++ b/test/mcs/test_defmcs_sobol.jl @@ -40,7 +40,7 @@ sd = @defsim begin save(grosseconomy.K, grosseconomy.YGROSS, emissions.E, emissions.E_Global) end -include("../../examples/tutorial/02-two-region-model/main.jl") +include("../../examples/tutorial/02-multi-region-model/main.jl") m = model diff --git a/test/test_explorer_sim.jl b/test/test_explorer_sim.jl index d51b31a50..f72055fce 100644 --- a/test/test_explorer_sim.jl +++ b/test/test_explorer_sim.jl @@ -11,7 +11,7 @@ import Mimi: _spec_for_sim_item, menu_item_list, getdataframe, get_sim_results # Get the example -include("mcs/test-model-2/two-region-model.jl") +include("mcs/test-model-2/multi-region-model.jl") using .MyModel m = construct_MyModel() From 9be6f9b466a9ac1f47d0069ba076a637ac681619 Mon Sep 17 00:00:00 2001 From: Cora Kingdon Date: Tue, 8 Oct 2019 16:48:49 -0400 Subject: [PATCH 24/63] Start updating tutorial 4 --- docs/src/tutorials/tutorial_4.md | 394 ++++++++++++++++++---------- docs/src/tutorials/tutorial_main.md | 2 +- 2 files changed, 250 insertions(+), 146 deletions(-) diff --git a/docs/src/tutorials/tutorial_4.md b/docs/src/tutorials/tutorial_4.md index 49c1ee51b..92c4ddadc 100644 --- a/docs/src/tutorials/tutorial_4.md +++ b/docs/src/tutorials/tutorial_4.md @@ -1,6 +1,6 @@ # Tutorial 4: Sensitivity Analysis (SA) Support -This tutorial walks through the sensitivity analysis (SA) functionality of Mimi, including core routines and examples. We will start with looking at using the SA routines with the Mimi multi-region model provided in the Mimi repository at `examples/tutorial/02-multi-region-model`, and then build out to examine its use on [The Climate Framework for Uncertainty, Negotiation and Distribution (FUND)](http://www.fund-model.org), available on Github [here](https://github.com/fund-model/fund). +This tutorial walks through the sensitivity analysis (SA) functionality of Mimi, including core routines and examples. We will start with looking at using the SA routines with the multi-region Mimi model built in the second half of Tutorial 3, and also available in the Mimi repository at `examples/tutorial/02-multi-region-model`. Then we will show some more advanced features using a real Integrated Assessment model, [MimiDICE2010](https://github.com/anthofflab/MimiDICE2010.jl). Working through the following tutorial will require: @@ -9,7 +9,7 @@ Working through the following tutorial will require: If you have not yet prepared these, go back to the main tutorial page and follow the instructions for their download. -Futhermore, if you are not yet comfortable with downloading (only needs to be done once) and running FUND, refer to Tutorial 1 for instructions. Carry out **Steps 1 and 2** from Tutorial 1 and then return to continue with this tutorial. Note that FUND is only required for the second example in this tutorial. +Futhermore, if you are not yet comfortable with downloading (only needs to be done once) and running MimiDICE2010, refer to Tutorial 1 for instructions. Carry out **Steps 1 and 2** from Tutorial 1 for the MimiDICE2010 package and then return to continue with this tutorial. Note that MimiDICE2010 is only required for the second example in this tutorial. ## The API @@ -22,35 +22,176 @@ These are described further below. We will refer separately to two types, `Simul This section will walk through a simple example of how to define a simulation, run the simulation for a given model, and access the outputs. ### Step 1. Setup -First, set up for the tutorial as follows with the necessary packages and `main.jl` script for the multi-region example. You should have `Mimi` installed by now, and if you do not have `Distributions`, take a moment to add that package using by entering `]` to enter the [Pkg REPL](https://docs.julialang.org/en/v1/stdlib/Pkg/index.html) mode and then typing `add Distributions`. +You should have `Mimi` installed by now, and if you do not have the `Distributions` package, take a moment to add that package by entering `]` to enter the [Pkg REPL](https://docs.julialang.org/en/v1/stdlib/Pkg/index.html) mode and then typing `add Distributions`. + +As a reminder, the following code is the multi-region model that was constructed in the second half of tutorial 3. You can either load the `MyModel` module from tutorial 3, or run the following code which defines the same `construct_Mymodel` function that we will use. ```jldoctest tutorial4; output = false -using Mimi -using Distributions +using Mimi + +# Define the grosseconomy component +@defcomp grosseconomy begin + regions = Index() #Note that a regional index is defined here + + YGROSS = Variable(index=[time, regions]) #Gross output + K = Variable(index=[time, regions]) #Capital + l = Parameter(index=[time, regions]) #Labor + tfp = Parameter(index=[time, regions]) #Total factor productivity + s = Parameter(index=[time, regions]) #Savings rate + depk = Parameter(index=[regions]) #Depreciation rate on capital - Note that it only has a region index + k0 = Parameter(index=[regions]) #Initial level of capital + share = Parameter() #Capital share + + function run_timestep(p, v, d, t) + # Note that the regional dimension is defined in d and parameters and variables are indexed by 'r' + + # Define an equation for K + for r in d.regions + if is_first(t) + v.K[t,r] = p.k0[r] + else + v.K[t,r] = (1 - p.depk[r])^5 * v.K[t-1,r] + v.YGROSS[t-1,r] * p.s[t-1,r] * 5 + end + end + + # Define an equation for YGROSS + for r in d.regions + v.YGROSS[t,r] = p.tfp[t,r] * v.K[t,r]^p.share * p.l[t,r]^(1-p.share) + end + end +end + +# define the emissions component +@defcomp emissions begin + regions = Index() # The regions index must be specified for each component + + E = Variable(index=[time, regions]) # Total greenhouse gas emissions + E_Global = Variable(index=[time]) # Global emissions (sum of regional emissions) + sigma = Parameter(index=[time, regions]) # Emissions output ratio + YGROSS = Parameter(index=[time, regions]) # Gross output - Note that YGROSS is now a parameter + + # function init(p, v, d) + # end + + function run_timestep(p, v, d, t) + # Define an equation for E + for r in d.regions + v.E[t,r] = p.YGROSS[t,r] * p.sigma[t,r] + end + + # Define an equation for E_Global + for r in d.regions + v.E_Global[t] = sum(v.E[t,:]) + end + end + +end + +# Define values for input parameters to be used when constructing the model + +l = Array{Float64}(undef, 20, 3) +for t in 1:20 + l[t,1] = (1. + 0.015)^t *2000 + l[t,2] = (1. + 0.02)^t * 1250 + l[t,3] = (1. + 0.03)^t * 1700 +end + +tfp = Array{Float64}(undef, 20, 3) +for t in 1:20 + tfp[t,1] = (1 + 0.06)^t * 3.2 + tfp[t,2] = (1 + 0.03)^t * 1.8 + tfp[t,3] = (1 + 0.05)^t * 2.5 +end + +s = Array{Float64}(undef, 20, 3) +for t in 1:20 + s[t,1] = 0.21 + s[t,2] = 0.15 + s[t,3] = 0.28 +end + +depk = [0.11, 0.135 ,0.15] +k0 = [50.5, 22., 33.5] + +sigma = Array{Float64}(undef, 20, 3) +for t in 1:20 + sigma[t,1] = (1. - 0.05)^t * 0.58 + sigma[t,2] = (1. - 0.04)^t * 0.5 + sigma[t,3] = (1. - 0.045)^t * 0.6 +end + +# Define a function for building the model + +function construct_MyModel() + + m = Model() + + set_dimension!(m, :time, collect(2015:5:2110)) + set_dimension!(m, :regions, [:Region1, :Region2, :Region3]) # Note that the regions of your model must be specified here + + add_comp!(m, grosseconomy) + add_comp!(m, emissions) + + set_param!(m, :grosseconomy, :l, l) + set_param!(m, :grosseconomy, :tfp, tfp) + set_param!(m, :grosseconomy, :s, s) + set_param!(m, :grosseconomy, :depk,depk) + set_param!(m, :grosseconomy, :k0, k0) + set_param!(m, :grosseconomy, :share, 0.3) + + # set parameters for emissions component + set_param!(m, :emissions, :sigma, sigma) + connect_param!(m, :emissions, :YGROSS, :grosseconomy, :YGROSS) + + return m +end # output +construct_MyModel (generic function with 1 method) ``` -```julia -cd() # Mimi-directory-path is a placeholder for the string describing the path of the Mimi directory -include("examples/tutorial/02-multi-region-model/main.jl") -m = model # defined by 2-region model +Then, we obtain a copy of the model: + +```jldoctest tutorial4; output = false +m = construct_MyModel() + +# output + +Mimi.Model + Module: Mimi + Components: + ComponentId(grosseconomy) + ComponentId(emissions) + Built: false ``` ### Step 2. Define Random Variables -The `@defsim` macro is the first step in the process, and returns a SimulationDefinition. The following syntax allows users to define random variables (RVs) as distributions, +The `@defsim` macro is the first step in the process, and returns a `SimulationDef`. The following syntax allows users to define random variables (RVs) as distributions, and associate model parameters with the defined random variables. +There are two ways of assigning random variables to model parameters in the @defsim macro. Notice that both of the following syntaxes are used in the following example. + +The first is the following: +```julia +rv(rv1) = Normal(0, 0.8) # create a random variable called "rv1" with the specified distribution +param1 = rv1 # then assign this random variable "rv1" to the parameter "param1" in the model +``` + +The second is a shortcut, in which you can directly assign the distribution on the right-hand side to the name of the model parameter on the left hand side. With this syntax, a random variable is created under the hood and then assigned to `param1`. +```julia +param1 = Normal(0, 0.8) +``` + The `@defsim` macro also selects the sampling method. Simple random sampling (also called Monte Carlo sampling) is the default. Other options include Latin Hypercube sampling and Sobol sampling. ```jldoctest tutorial4; output = false +using Mimi +using Distributions + sd = @defsim begin - # Define random variables. The rv() is required to disambiguate an - # RV definition name = Dist(args...) from application of a distribution - # to an external parameter. This makes the (less common) naming of an - # RV slightly more burdensome, but it's only required when defining + # Define random variables. The rv() is only required when defining # correlations or sharing an RV across parameters. rv(name1) = Normal(1, 0.2) rv(name2) = Uniform(0.75, 1.25) @@ -63,24 +204,24 @@ sd = @defsim begin # sampling(MCSData) # For Sobol sampling, specify N, and calc_second_order, which defaults to false. - # sampling(SobolData, N=100000, calc_second_order=true) + # sampling(SobolData, N=10000, calc_second_order=true) # assign RVs to model Parameters share = Uniform(0.2, 0.8) sigma[:, Region1] *= name2 sigma[2020:5:2050, (Region2, Region3)] *= Uniform(0.8, 1.2) - # Assign an array of distributions, keyed by region, to parameter depk - depk = [Region1 => Uniform(0.7, 1.3), - Region2 => Uniform(0.8, 1.2), - Region3 => Normal()] + # For parameters that have a region dimension, you can assign an array of distributions, + # keyed by region label, which must match the region labels in the model + depk = [Region1 => Uniform(0.7, .9), + Region2 => Uniform(0.8, 1.), + Region3 => Truncated(Normal(), 0, 1)] - # indicate which parameters to save for each model run. Specify - # a parameter name or [later] some slice of its data, similar to the - # assignment of RVs, above. + # Indicate which variables to save for each model run. + # The syntax is: component_name.variable_name save(grosseconomy.K, grosseconomy.YGROSS, emissions.E, emissions.E_Global) -end; +end # output @@ -89,19 +230,27 @@ LHSData(Tuple{Symbol,Symbol,Float64}[(:name1, :name2, 0.7), (:name1, :name3, 0.5 ### Step 3. Run Simulation -Next, use the `run` function to run the simulation for the specified SimulationDefinition, model (or list of models), and number of trials. View the internals documentation [here](https://github.com/mimiframework/Mimi.jl/blob/master/docs/src/internals/montecarlo.md) for **critical and useful details on the full signature of the `run` function**. +Next, use the `run` function to run the simulation for the specified simulation definition, model (or list of models), and number of trials. View the internals documentation [here](https://github.com/mimiframework/Mimi.jl/blob/master/docs/src/internals/montecarlo.md) for **critical and useful details on the full signature of the `run` function**. -Here, we first employ `run` to obtain results: +In its simplest use, the `run` function generates and iterates over a sample of trial data from the distributions of the random variables defined in the `SimulationDef`, perturbing the subset of Mimi's "external parameters" that have been assigned random variables, and then runs the given Mimi model(s) for each set of trial data. The function returns a `SimulationInstance`, which holds a copy of the original `SimulationDef` in addition to trials information (`trials`, `current_trial`, and `current_data`), the model list `models`, and results information in `results`. Optionally, trial values and/or model results are saved to CSV files. Note that if there is concern about in-memory storage space for the results, use the `results_in_memory` flag set to `false` to incrementally clear the results from memory. ```jldoctest tutorial4; output = false - # Run 100 trials, and optionally save results to the indicated directories -si = run(sd, m, 100; trials_output_filename = "/tmp/trialdata.csv", results_output_dir="/tmp/Mimi") +si = run(sd, m, 100; trials_output_filename = "/tmp/trialdata.csv", results_output_dir="/tmp/tutorial4") + +# Explore the results saved in-memory by indexing into the returned SimulationInstance. +# Values are save from each trial for each variable or parameter specified by the call to "save()" at the end of the @defsim block. +K_results = si[:grosseconomy, :K] +E_results = si[:emissions, :E] + +size(E_results) == (6000, 4) # These results are DataFrames, with one value for each trial for each region and year + +# output -# Explore the results saved in-memory -results = si[:grosseconomy, :K] +true ``` + ### Step 4. Explore and Plot Results As described in the internals documentation [here](https://github.com/mimiframework/Mimi.jl/blob/master/docs/src/internals/montecarlo.md), Mimi provides both `explore` and `Mimi.plot` to explore the results of both a run `Model` and a run `SimulationInstance`. @@ -118,10 +267,9 @@ If desired, you may also include a `title` for your application window. If more explore(si; title = "MyWindow", model = 1) # we do not indicate scen_name here since we have no scenarios ``` -To view the results for one of the saved variables from the `save` command in `@defsim`, use the (unexported to avoid namespace collisions)`Mimi.plot` function. This function has the same keyword arguments and requirements as `explore`, save for `title`, and three required arguments: the `SimulationInstance`, the component name (as a `Symbol`), and the variable name (as a `Symbol`). +To view the results for one of the saved variables from the `save` command in `@defsim`, use the (unexported to avoid namespace collisions) `Mimi.plot` function. This function has the same keyword arguments and requirements as `explore` (except for `title`), and three required arguments: the `SimulationInstance`, the component name (as a `Symbol`), and the variable name (as a `Symbol`). ```julia -using VegaLite Mimi.plot(si, :grosseconomy, :K) ``` To save your figure, use the `save` function to save typical file formats such as [PNG](https://en.wikipedia.org/wiki/Portable_Network_Graphics), [SVG](https://en.wikipedia.org/wiki/Scalable_Vector_Graphics), [PDF](https://en.wikipedia.org/wiki/PDF) and [EPS](https://en.wikipedia.org/wiki/Encapsulated_PostScript) files. Note that while `explore(sim_inst)` returns interactive plots for several graphs, `Mimi.plot(si, :foo, :bar)` will return only static plots. @@ -131,137 +279,71 @@ p = Mimi.plot(si, :grosseconomy, :K) save("MyFigure.png", p) ``` -## Advanced Features - -While the model above employed a fairly simple `post_trial_func` that printed out results, the post-trial functions can be used for more complex calculations that need to be made for each simulation run. This can be especially useful, for example, for calculating net present value of damages or the social cost of carbon (SCC) for each run. - -In it's simplest use, the `run` function generates and iterates over generated trial data, perturbing a chosen subset of Mimi's "external parameters", based on the defined distributions, and then runs the given Mimi model(s). The function returns a `SimulationInstance`, holding a copy of the original `SimulationDef` in addition to trials information (`trials`, `current_trial`, and `current_data`), the model list`models`, and results information in `results`. Optionally, trial values and/or model results are saved to CSV files. Optionally, trial values and/or model results are saved to CSV files. Note that if there is concern about in-memory storage space for the results, use the `results_in_memory` flag set to `false` to incrementally clear the results from memory. View the internals documentation for **critical and useful details on the full signature of this function**: - -``` -function Base.run(sim_def::SimulationDef{T}, models::Union{Vector{Model}, Model}, samplesize::Int; - ntimesteps::Int=typemax(Int), - trials_output_filename::Union{Nothing, AbstractString}=nothing, - results_output_dir::Union{Nothing, AbstractString}=nothing, - pre_trial_func::Union{Nothing, Function}=nothing, - post_trial_func::Union{Nothing, Function}=nothing, - scenario_func::Union{Nothing, Function}=nothing, - scenario_placement::ScenarioLoopPlacement=OUTER, - scenario_args=nothing, - results_in_memory::Bool=true) where T <: AbstractSimulationData -``` - -### NPV of Damages - -Case: We want to run MimiDICE2010, varying the climate sensitivity `t2xco2` over a distribution `MyDistribution`, and for each run return the sum of discounted climate damages `DAMAGES` using three different discount rates. - -Without using the Mimi functionality, this may look something like: - -```julia -# N = number of trials -# m = DICE2010 model -# df = array of discount factors -# npv_damages= an empty array to store my results -# ECS_sample = a vector of climate sensitivity values drawn from the desired distribution - -for i = 1:N - update_param!(m, :t2xco2, ECS_sample[i]) - run(m) - npv_damages[i] = sum(df .* m[:neteconomy, :DAMAGES]) -end -``` +## Advanced Features - Social Cost of Carbon (SCC) Example -We encourage users to employ the Mimi framework for this type of analysis, in large part because the underlying functions have optimizations that will improve speed and memory use, especially as the number of runs climbs. +This example will discuss the more advanced SA capabilities of post-trial functions and payload objects. -Employing the sensitivity analysis functionality could look like the following template: +Case: We want to do an SCC calculation with `MimiDICE2010`, which consists of running both a `base` and `marginal` model (the latter being a model including an additional emissions pulse, see the [`create_marginal_model`](@ref) or create your own two models). We then take the difference between the consumption level in these two models and obtain the discounted net present value to get the SCC. -First, we define the typical variables for a simulation, including the number of trials `N` and the simulation definition `sim_def`. In this case we only define one random variable, `t2xco2`, but note there could be any number of random variables defined here. +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 `sim_def`. In this case we only define one random variable, `t2xco2`, but note there could be any number of random variables defined here. -```julia +```jldoctest tutorial4; output = false using Mimi using MimiDICE2010 +using Distributions -# define your trial number -N = 1000000 +# define the number of trials +N = 100 -# define your simulation(defaults to Monte Carlo sampling) +# define your simulation (defaults to Monte Carlo sampling) sd = @defsim begin - t2xco2 = MyDistribution() + t2xco2 = Truncated(Gamma(6.47815626,0.547629469), 1.0, Inf) # a dummy distribution end -``` - -Next, we consider the requirements for our post-trial function. We will need to define the array of discount rates `discount_rates`, and a function that converts `discount_rates` into the necessary array of discount factors `df`, as follows. -```julia -# define your desired discount rates and pre compute the discount factors -discount_rates = [0.025, 0.03, 0.05] -dfs = [calculate_df(rate) for rate in discount_rates] # need to define or replace calculate_df -``` +# output -Next, we must create an array to store the npv damages results to during the post-trial funciton -```julia -# make an array to store the npv damages results to during the post trial function -npv_results = zeros(N, length(discount_rates)) +MCSData() ``` -We are now ready to define a post-trial function, which has a required type signature `MyFunction(sim_inst::SimulationInstance, trialnum::Int, ntimesteps::Int, tup::Tuple)` although not all arguments have to be used within the function. Our function will access our model from the list of models in `mcs_inst.models` (length of one in this case) and then perform calculations on the `DAMAGES` variable from the `neteconomy` component in that model as follows. - -```julia -# define your post trial function; this is the required type signature, even though we won't use all of the arguments -function my_npv_calculation(sim_inst::SimulationInstance, trialnum::Int, ntimesteps::Int, tup::Tuple) - m = sim_inst.models[1] # access the model after it is run for this trial - damages = m[:neteconomy, :DAMAGES] # access the damage values for this run - for (i, df) in enumerate(dfs) # loop through our precomputed discount factors - npv_results[trialnum, i] = sum(df .* damages) # do the npv calculation and save it to our array of results - end - nothing # return nothing -end -``` -Now that we have defined our post-trial function, we can set our models and run the simulation! Afterwards, we can use the `npv_results` array as we need. +### Payload object +SimulationDefs 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 -si = run(sd, m, N; post_trial_func = my_npv_calculation, trials_output_filename = "ECS_sample.csv")# providing a file name is optional; only use if you want to see the climate sensitivity values later +```jldoctest tutorial4; output = false +# Choose what year to calculate the SCC for +scc_year = 2015 +year_idx = findfirst(isequal(scc_year), MimiDICE2010.model_years) -# do something with the npv_results array -println(mean(npv_results, dims=2)) # or write to a file -``` +# Pre-compute the discount factors for each discount rate +discount_rates = [0.03, 0.05, 0.07] +nyears = length(MimiDICE2010.model_years) +discount_factors = [[zeros(year_idx - 1)... [(1/(1 + r))^((t-year_idx)*10) for t in year_idx:nyears]...] for r in discount_rates] -### Social Cost of Carbon (SCC) +# Create an array to store the computed SCC in each trial for each discount rate +scc_results = zeros(N, length(discount_rates)) -Case: We want to do an SCC calculation across a base and marginal model of `MimiDICE2010`, which consists of running both a `base` and `marginal` model (the latter being a model including an emissions pulse, see the [`create_marginal_model`](@ref) or create your own two models). We then take the difference between the `DAMAGES` in these two models and obtain the NPV to get the SCC. +# Set the payload object in the simulation definition +Mimi.set_payload!(sd, (discount_factors, scc_results)) # In this case, the payload object is a tuple which holds both both arrays +nothing -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 `sim_def`. In this case we only define one random variable, `t2xco2`, but note there could be any number of random variables defined here. +# output -```jldoctest tutorial4; output = false -using Mimi -using MimiDICE2010 -using Distributions +``` -# define your number of trials and discount rates -N = 1000 -discount_rates = [0.3, 0.5, 0.7] +### Post-trial function -# define your simulation (defaults to Monte Carlo sampling) -sd = @defsim begin - t2xco2 = Truncated(Gamma(6.47815626,0.547629469), 1.0, Inf) # a dummy distribution -end +In the simple multi-region simulation example, the only values that were saved during each trial of the simulation were values of variables calculated internally by the model. Sometimes, a user may need to perform other calculations before or after each trial is run. For example, the SCC is calculated using two models, so this calculation needs to happen in a post-trial function, as shown below. -# output +Here we define a `post_trial_function` called `my_scc_calculation` which will calculate the SCC for each trial of the simulation. Notice that this function retrieves and uses the payload object that was previously stored in the Simulation definition. -MCSData() -``` +```jldoctest tutorial4; output = false -Next, we prepare our post-trial calculations by setting up a `scc_results` array to hold the results. We then define a `post_trial_function` called `my_scc_calculation` which will calculate the SCC for that run. +function my_scc_calculation(sim_inst::SimulationInstance, trialnum::Int, ntimesteps::Int, tup::Nothing) + mm = sim_inst.models[1] + discount_factors, scc_results = Mimi.payload(sim_inst) # Unpack the payload object -```jldoctest tutorial4; output = false -scc_results = zeros(N, length(discount_rates)) - -function my_scc_calculation(sim_inst::SimulationInstance, trialnum::Int, ntimesteps::Int, tup::Tuple) - base = sim_inst.models[1] - marginal = sim_inst.models[2] - base_damages = base[:neteconomy, :DAMAGES] - marg_damages = marginal[:neteconomy, :DAMAGES] - for (i, df) in enumerate(dfs) - scc_results[trialnum, i] = sum(df .* (marg_damages .- base_damages)) + marginal_damages = mm[:neteconomy, :C] * -1 * 10^12 * 12/44 # convert from trillion $/ton C to $/ton CO2; multiply by -1 to get positive value for damages + for (i, df) in enumerate(discount_factors) + scc_results[trialnum, i] = sum(df .* marginal_damages .* 10) end end @@ -270,23 +352,28 @@ end my_scc_calculation (generic function with 1 method) ``` -Now that we have our post-trial function, we can proceed to obtain our two models and run the simulation. +### Run the simulation -```julia -# Build the base model -base = MimiDICE2010.get_model() +Now that we have our post-trial function, we can proceed to obtain our two models and run the simulation. -#Build the marginal model -mm = MimiDICE2010.get_marginal_model(m, year = 2015) +```jldoctest tutorial4; output = false +# Build the marginal model +mm = MimiDICE2010.get_marginal_model(year = scc_year) # The additional emissions pulse will be added in the specified year # Run -si = run(sd, [mm.base, mm.marginal], N; trials_output_filename = "ecs_sample.csv", post_trial_func = my_scc_calculation) +si = run(sd, mm, N; trials_output_filename = "ecs_sample.csv", post_trial_func = my_scc_calculation) + +# View the scc_results by retrieving them from the payload object +scc_results = Mimi.payload(si)[2] # Recall that the SCC array was the second of two arrays we stored in the payload tuple +size(scc_results) == (N, 3) # output +true ``` -## Simulation Modification Functions -A small set of unexported functions are available to modify an existing `SimulationDefinition`. The functions include: + +### Simulation Modification Functions +A small set of unexported functions are available to modify an existing `SimulationDef`. The functions include: * `delete_RV!` * `add_RV!` * `replace_RV!` @@ -296,3 +383,20 @@ A small set of unexported functions are available to modify an existing `Simulat * `add_save!` * `set_payload!` * `payload` + +### Full list of keyword options for running a simulation + +View the internals documentation [here](https://github.com/anthofflab/Mimi.jl/blob/master/docs/src/internals/montecarlo.md) for **critical and useful details on the full signature of this function**: + +``` +function Base.run(sim_def::SimulationDef{T}, models::Union{Vector{Model}, Model}, samplesize::Int; + ntimesteps::Int=typemax(Int), + trials_output_filename::Union{Nothing, AbstractString}=nothing, + results_output_dir::Union{Nothing, AbstractString}=nothing, + pre_trial_func::Union{Nothing, Function}=nothing, + post_trial_func::Union{Nothing, Function}=nothing, + scenario_func::Union{Nothing, Function}=nothing, + scenario_placement::ScenarioLoopPlacement=OUTER, + scenario_args=nothing, + results_in_memory::Bool=true) where T <: AbstractSimulationData +``` diff --git a/docs/src/tutorials/tutorial_main.md b/docs/src/tutorials/tutorial_main.md index bad4983ef..350a26c2d 100644 --- a/docs/src/tutorials/tutorial_main.md +++ b/docs/src/tutorials/tutorial_main.md @@ -26,7 +26,7 @@ The following terminology is used throughout the documentation. 4. **Sensitivity Analysis** - [Tutorial 4: Sensitivity Analysis (SA) Support](@ref) explores Mimi's Sensitivity Analysis support, using both the simple 2-Region tutorial model and [FUND](http://www.fund-model.org) examples. + [Tutorial 4: Sensitivity Analysis (SA) Support](@ref) explores Mimi's Sensitivity Analysis support, using both the simple multi-Region tutorial model and MimiDICE2010 examples. _Additional AERE Workshop Tutorials: The Mimi developement team recently participated in the 2019 Association of Environmental and Resource Economists (AERE) summer conference during the pre-conference workshop on Advances in Integrated Assessment Models. This included both a presentation and a hands-on session demonstrating various use cases for Mimi. The Github repository [here](https://github.com/davidanthoff/teaching-2019-aere-workshop) contains a) all slides from the workshop and b) all the code from the hands on sessions, which may be of interest to Mimi users. Importantly note that the linked code represents as a snapshot of Mimi at the time of the workshop, and **will not** be updated to reflect new changes._ From a15233a87ada8aee1e43d4af1ff14ed363aeca55 Mon Sep 17 00:00:00 2001 From: Cora Kingdon Date: Tue, 8 Oct 2019 17:00:52 -0400 Subject: [PATCH 25/63] more edits to tutorial 4 --- docs/src/tutorials/tutorial_4.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/src/tutorials/tutorial_4.md b/docs/src/tutorials/tutorial_4.md index 92c4ddadc..dcc8063c8 100644 --- a/docs/src/tutorials/tutorial_4.md +++ b/docs/src/tutorials/tutorial_4.md @@ -1,6 +1,6 @@ # Tutorial 4: Sensitivity Analysis (SA) Support -This tutorial walks through the sensitivity analysis (SA) functionality of Mimi, including core routines and examples. We will start with looking at using the SA routines with the multi-region Mimi model built in the second half of Tutorial 3, and also available in the Mimi repository at `examples/tutorial/02-multi-region-model`. Then we will show some more advanced features using a real Integrated Assessment model, [MimiDICE2010](https://github.com/anthofflab/MimiDICE2010.jl). +This tutorial walks through the sensitivity analysis (SA) functionality of Mimi, including core routines and examples. We will start with looking at using the SA routines with the multi-region Mimi model built in the second half of Tutorial 3, which is also available in the Mimi repository at `examples/tutorial/02-multi-region-model`. Then we will show some more advanced features using a real Integrated Assessment model, [MimiDICE2010](https://github.com/anthofflab/MimiDICE2010.jl). Working through the following tutorial will require: @@ -15,7 +15,7 @@ Futhermore, if you are not yet comfortable with downloading (only needs to be do The best current documentation on the SA API is the internals documentation [here](https://github.com/anthofflab/Mimi.jl/blob/master/docs/src/internals/montecarlo.md), which provides a working and informal description of the Sensitivity Analysis support of Mimi. This file should be used in conjunction with the examples below for details, since the documentation covers more advanced options such as non-stochastic scenarios and running multiple models, which are not yet included in this tutorial. -These are described further below. We will refer separately to two types, `SimulationDef` and `SimulationInstance`. They are referred to as `sim_def` and `sim_inst` respectively as function arguments, and `sd` and `si` respectively as local variables. +We will refer separately to two types, `SimulationDef` and `SimulationInstance`. They are referred to as `sim_def` and `sim_inst` respectively as function arguments, and `sd` and `si` respectively as local variables. ## Multi-Region Model Example @@ -170,7 +170,7 @@ Mimi.Model The `@defsim` macro is the first step in the process, and returns a `SimulationDef`. The following syntax allows users to define random variables (RVs) as distributions, and associate model parameters with the defined random variables. -There are two ways of assigning random variables to model parameters in the @defsim macro. Notice that both of the following syntaxes are used in the following example. +There are two ways of assigning random variables to model parameters in the `@defsim` macro. Notice that both of the following syntaxes are used in the following example. The first is the following: ```julia @@ -191,8 +191,9 @@ using Mimi using Distributions sd = @defsim begin - # Define random variables. The rv() is only required when defining - # correlations or sharing an RV across parameters. + # Define random variables. The rv() is only required when defining correlations + # or sharing an RV across parameters. Otherwise, you can use the shortcut syntax + # to assign a distribution to a parameter name. rv(name1) = Normal(1, 0.2) rv(name2) = Uniform(0.75, 1.25) rv(name3) = LogNormal(20, 4) @@ -283,9 +284,9 @@ save("MyFigure.png", p) This example will discuss the more advanced SA capabilities of post-trial functions and payload objects. -Case: We want to do an SCC calculation with `MimiDICE2010`, which consists of running both a `base` and `marginal` model (the latter being a model including an additional emissions pulse, see the [`create_marginal_model`](@ref) or create your own two models). We then take the difference between the consumption level in these two models and obtain the discounted net present value to get the SCC. +Case: We want to do an SCC calculation with `MimiDICE2010`, which consists of running both a `base` and `marginal` model (the latter being a model including an additional emissions pulse, see the [`create_marginal_model`](@ref) function or create your own two models). We then take the difference between the consumption level in these two models and obtain the discounted net present value to get the SCC. -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 `sim_def`. In this case we only define one random variable, `t2xco2`, but note there could be any number of random variables defined here. +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 tutorial4; output = false using Mimi @@ -306,7 +307,7 @@ MCSData() ``` ### Payload object -SimulationDefs 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. +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 tutorial4; output = false # Choose what year to calculate the SCC for @@ -322,7 +323,8 @@ discount_factors = [[zeros(year_idx - 1)... [(1/(1 + r))^((t-year_idx)*10) for t scc_results = zeros(N, length(discount_rates)) # Set the payload object in the simulation definition -Mimi.set_payload!(sd, (discount_factors, scc_results)) # In this case, the payload object is a tuple which holds both both arrays +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) nothing # output @@ -333,10 +335,9 @@ nothing In the simple multi-region simulation example, the only values that were saved during each trial of the simulation were values of variables calculated internally by the model. Sometimes, a user may need to perform other calculations before or after each trial is run. For example, the SCC is calculated using two models, so this calculation needs to happen in a post-trial function, as shown below. -Here we define a `post_trial_function` called `my_scc_calculation` which will calculate the SCC for each trial of the simulation. Notice that this function retrieves and uses the payload object that was previously stored in the Simulation definition. +Here we define a `post_trial_function` called `my_scc_calculation` which will calculate the SCC for each trial of the simulation. Notice that this function retrieves and uses the payload object that was previously stored in the `SimulationDef`. ```jldoctest tutorial4; output = false - function my_scc_calculation(sim_inst::SimulationInstance, trialnum::Int, ntimesteps::Int, tup::Nothing) mm = sim_inst.models[1] discount_factors, scc_results = Mimi.payload(sim_inst) # Unpack the payload object @@ -354,7 +355,7 @@ my_scc_calculation (generic function with 1 method) ### Run the simulation -Now that we have our post-trial function, we can proceed to obtain our two models and run the simulation. +Now that we have our post-trial function, we can proceed to obtain our two models and run the simulation. Note that we are using a Mimi MarginalModel `mm` from MimiDICE2010, which is a Mimi object that holds both the base model and the model with the additional pulse of emissions. ```jldoctest tutorial4; output = false # Build the marginal model From f7f7f00b577cc1bbf963fec58f15521d296a0685 Mon Sep 17 00:00:00 2001 From: lrennels Date: Tue, 8 Oct 2019 18:17:34 -0700 Subject: [PATCH 26/63] Various updates to doctests --- docs/Project.toml | 2 ++ docs/src/tutorials/tutorial_1.md | 33 +++++++++++++++++++-------- docs/src/tutorials/tutorial_3.md | 11 +++++++-- docs/src/tutorials/tutorial_4.md | 39 ++++++++++++++++++++++---------- 4 files changed, 61 insertions(+), 24 deletions(-) diff --git a/docs/Project.toml b/docs/Project.toml index 6bc748bc0..2032b6522 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -5,6 +5,7 @@ Mimi = "e4e893b0-ee5e-52ea-8111-44b3bdec128c" MimiDICE2010 = "4f2c5d70-42a7-11e9-1de8-c370bd984083" MimiFUND = "b3ba11de-429f-11e9-29f7-cb478ab96e7c" StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" +VegaLite = "112f6efa-9a02-5b7d-90c0-432ed331239a" [compat] Distributions = "0.21" @@ -13,3 +14,4 @@ Mimi = "0.9.3" MimiDICE2010 = "0.1" MimiFUND = "3.11" StatsBase = "0.32" +VegaLite = "0.7" diff --git a/docs/src/tutorials/tutorial_1.md b/docs/src/tutorials/tutorial_1.md index ee79afb2d..60311d3f5 100644 --- a/docs/src/tutorials/tutorial_1.md +++ b/docs/src/tutorials/tutorial_1.md @@ -36,7 +36,7 @@ using MimiFUND # output ``` -to access the public API to FUND, which currently includes the function `MimiFUND.get_model` (which can also be called with the exported and identical function `getfund`). This function returns a version of fund allowing for different user specifications. +to access the public API to FUND, which currently includes the function `MimiFUND.get_model` (which can also be called with the exported and identical function `getfund`). This function returns a version of fund allowing for different user specifications. Here we will first get the model, and then use the `run` function to run it. ```jldoctest tutorial1; output = false m = MimiFUND.get_model() @@ -92,17 +92,16 @@ You may also get data in the form of a dataframe, which will display the corresp getdataframe(m, :ComponentName=>:Variable) # request one variable from one component getdataframe(m, :ComponentName=>(:Variable1, :Variable2)) # request multiple variables from the same component getdataframe(m, :Component1=>:Var1, :Component2=>:Var2) # request variables from different components - ``` Try doing this for the `income` variable of the `socioeconomic` component using: ```jldoctest tutorial1; output = false getdataframe(m, :socioeconomic=>:income) # request one variable from one component -getdataframe(m, :socioeconomic=>:income)[1:5,:] # first five rows +getdataframe(m, :socioeconomic=>:income)[1:16,:] # results for all regions in first year (1950) # output -5×3 DataFrames.DataFrame +16×3 DataFrames.DataFrame │ Row │ time │ regions │ income │ │ │ Int64 │ String │ Float64⍰ │ ├─────┼───────┼─────────┼──────────┤ @@ -111,6 +110,17 @@ getdataframe(m, :socioeconomic=>:income)[1:5,:] # first five rows │ 3 │ 1950 │ WEU │ 1913.32 │ │ 4 │ 1950 │ JPK │ 616.022 │ │ 5 │ 1950 │ ANZ │ 119.058 │ +│ 6 │ 1950 │ EEU │ 87.9192 │ +│ 7 │ 1950 │ FSU │ 167.309 │ +│ 8 │ 1950 │ MDE │ 76.065 │ +│ 9 │ 1950 │ CAM │ 40.5139 │ +│ 10 │ 1950 │ LAM │ 193.139 │ +│ 11 │ 1950 │ SAS │ 57.9714 │ +│ 12 │ 1950 │ SEA │ 25.6943 │ +│ 13 │ 1950 │ CHI │ 18.8014 │ +│ 14 │ 1950 │ MAF │ 13.4482 │ +│ 15 │ 1950 │ SSA │ 94.686 │ +│ 16 │ 1950 │ SIS │ 6.82114 │ ``` ### Step 4. Access Results: Plots and Graphs @@ -124,23 +134,26 @@ Mimi provides support for plotting using [VegaLite](https://github.com/vega/vega If you wish to explore the results graphically, use the explorer UI, described [here](https://www.mimiframework.org/Mimi.jl/stable/userguide/#Plotting-and-the-Explorer-UI-1) in Section 5 of the Mimi User Guide. To explore all variables and parameters of FUND in a dynamic UI app window, use the [`explore`](@ref) function called with the model as the required first argument, and the optional argument of the `title` The menu on the left hand side will list each element in a label formatted as `component: variable/parameter`. -```julia +```jldoctest tutorial1; output = false, filter = r".*" explore(m, title = "My Window") + +# output + ``` Alternatively, in order to view just one parameter or variable, call the function [`explore`](@ref) as below to return a plot object and automatically display the plot in a viewer, assuming [`explore`](@ref) is the last command executed. This call will return the type `VegaLite.VLSpec`, which you may interact with using the API described in the [VegaLite.jl](https://github.com/fredo-dedup/VegaLite.jl) documentation. For example, [VegaLite.jl](https://github.com/fredo-dedup/VegaLite.jl) plots can be saved as [PNG](https://en.wikipedia.org/wiki/Portable_Network_Graphics), [SVG](https://en.wikipedia.org/wiki/Scalable_Vector_Graphics), [PDF](https://en.wikipedia.org/wiki/PDF) and [EPS](https://en.wikipedia.org/wiki/Encapsulated_PostScript) files. You may save a plot using the `save` function. Note that saving an interactive plot in a non-interactive file format, such as .pdf or .svg will result in a warning `WARN Can not resolve event source: window`, but the plot will be saved as a static image. If you wish to preserve interactive capabilities, you may save it using the .vegalite file extension. If you then open this file in Jupyter lab, the interactive aspects will be preserved. ```julia -using VegaLite -run(m) -p = Mimi.plot(m, component1, parameter1) +p = Mimi.plot(m, :mycomponent, :myvariable) save("MyFilePath.svg", p) ``` More specifically for our tutorial use of FUND, try: -```julia -using VegaLite +```jldoctest tutorial1; output = false, filter = r".*" p = Mimi.plot(m, :socioeconomic, :income) save("MyFilePath.svg", p) + +# output + ``` #### Component Graph diff --git a/docs/src/tutorials/tutorial_3.md b/docs/src/tutorials/tutorial_3.md index a9a01f391..98404acf0 100644 --- a/docs/src/tutorials/tutorial_3.md +++ b/docs/src/tutorials/tutorial_3.md @@ -159,12 +159,17 @@ m[:emissions, :E] 92022.29655492865 ``` Finally we can visualize the results: -```julia +```jldoctest tutorial3; output = false, filter = r".*" +using VegaLite + # Plot model results Mimi.plot(m, :emissions, :E); # Observe all model result graphs in UI explore(m) + +# output + ``` ## Constructing A Multi-Region Model @@ -381,8 +386,10 @@ m[:emissions, :E_Global] 36444.054899836294 38226.21934898662 ``` -```julia +```jldoctest tutorial3; output = false, filter = r".*" # Observe model result graphs explore(m) +# output + ``` diff --git a/docs/src/tutorials/tutorial_4.md b/docs/src/tutorials/tutorial_4.md index dcc8063c8..0e8ba7d49 100644 --- a/docs/src/tutorials/tutorial_4.md +++ b/docs/src/tutorials/tutorial_4.md @@ -235,10 +235,14 @@ Next, use the `run` function to run the simulation for the specified simulation In its simplest use, the `run` function generates and iterates over a sample of trial data from the distributions of the random variables defined in the `SimulationDef`, perturbing the subset of Mimi's "external parameters" that have been assigned random variables, and then runs the given Mimi model(s) for each set of trial data. The function returns a `SimulationInstance`, which holds a copy of the original `SimulationDef` in addition to trials information (`trials`, `current_trial`, and `current_data`), the model list `models`, and results information in `results`. Optionally, trial values and/or model results are saved to CSV files. Note that if there is concern about in-memory storage space for the results, use the `results_in_memory` flag set to `false` to incrementally clear the results from memory. -```jldoctest tutorial4; output = false +```julia # Run 100 trials, and optionally save results to the indicated directories si = run(sd, m, 100; trials_output_filename = "/tmp/trialdata.csv", results_output_dir="/tmp/tutorial4") +``` + +We can then take a look at the results saved in memory +```jldoctest tutorial4; output = false, setup = :(si = run(sd, m, 100; trials_output_filename = "/tmp/trialdata.csv", results_output_dir="/tmp/tutorial4")) # Explore the results saved in-memory by indexing into the returned SimulationInstance. # Values are save from each trial for each variable or parameter specified by the call to "save()" at the end of the @defsim block. K_results = si[:grosseconomy, :K] @@ -250,34 +254,46 @@ size(E_results) == (6000, 4) # These results are DataFrames, with one value fo true ``` - - ### Step 4. Explore and Plot Results As described in the internals documentation [here](https://github.com/mimiframework/Mimi.jl/blob/master/docs/src/internals/montecarlo.md), Mimi provides both `explore` and `Mimi.plot` to explore the results of both a run `Model` and a run `SimulationInstance`. To view your results in an interactive application viewer, simply call: -```julia +```jldoctest tutorial4; output = false, filter = r".*" explore(si) + +# output + ``` If desired, you may also include a `title` for your application window. If more than one model was run in your Simulation, indicate which model you would like to explore with the `model` keyword argument, which defaults to 1. Finally, if your model leverages different scenarios, you **must** indicate the `scenario_name`. -```julia -explore(si; title = "MyWindow", model = 1) # we do not indicate scen_name here since we have no scenarios +```jldoctest tutorial4; output = false, filter = r".*" +explore(si; title = "MyWindow", model_index = 1) # we do not indicate scen_name here since we have no scenarios + +# output + ``` To view the results for one of the saved variables from the `save` command in `@defsim`, use the (unexported to avoid namespace collisions) `Mimi.plot` function. This function has the same keyword arguments and requirements as `explore` (except for `title`), and three required arguments: the `SimulationInstance`, the component name (as a `Symbol`), and the variable name (as a `Symbol`). -```julia +```jldoctest tutorial4; output = false, filter = r".*" Mimi.plot(si, :grosseconomy, :K) + +# output + ``` To save your figure, use the `save` function to save typical file formats such as [PNG](https://en.wikipedia.org/wiki/Portable_Network_Graphics), [SVG](https://en.wikipedia.org/wiki/Scalable_Vector_Graphics), [PDF](https://en.wikipedia.org/wiki/PDF) and [EPS](https://en.wikipedia.org/wiki/Encapsulated_PostScript) files. Note that while `explore(sim_inst)` returns interactive plots for several graphs, `Mimi.plot(si, :foo, :bar)` will return only static plots. -```julia +```jldoctest tutorial4; output = false, filter = r".*" p = Mimi.plot(si, :grosseconomy, :K) save("MyFigure.png", p) + +# output + +WARN Layer's shared color channel is overriden +WARN Layer's shared color channel is overriden ``` ## Advanced Features - Social Cost of Carbon (SCC) Example @@ -309,7 +325,7 @@ MCSData() ### 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 tutorial4; output = false +```jldoctest tutorial4; output = false, filter = r".*" # Choose what year to calculate the SCC for scc_year = 2015 year_idx = findfirst(isequal(scc_year), MimiDICE2010.model_years) @@ -325,7 +341,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) -nothing # output @@ -357,7 +372,7 @@ my_scc_calculation (generic function with 1 method) Now that we have our post-trial function, we can proceed to obtain our two models and run the simulation. Note that we are using a Mimi MarginalModel `mm` from MimiDICE2010, which is a Mimi object that holds both the base model and the model with the additional pulse of emissions. -```jldoctest tutorial4; output = false +```jldoctest tutorial4; output = false, # Build the marginal model mm = MimiDICE2010.get_marginal_model(year = scc_year) # The additional emissions pulse will be added in the specified year @@ -389,7 +404,7 @@ A small set of unexported functions are available to modify an existing `Simulat View the internals documentation [here](https://github.com/anthofflab/Mimi.jl/blob/master/docs/src/internals/montecarlo.md) for **critical and useful details on the full signature of this function**: -``` +```julia function Base.run(sim_def::SimulationDef{T}, models::Union{Vector{Model}, Model}, samplesize::Int; ntimesteps::Int=typemax(Int), trials_output_filename::Union{Nothing, AbstractString}=nothing, From 47a411f7453562be74a6f8799cdabca84b2f3bd8 Mon Sep 17 00:00:00 2001 From: David Anthoff Date: Tue, 8 Oct 2019 20:33:31 -0700 Subject: [PATCH 27/63] Use Julia 1.2 for doc build --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fe7bd27f9..aba9d1c57 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,7 +31,7 @@ after_success: jobs: include: - stage: "Documentation" - julia: 1.1 + julia: 1.2 os: linux script: - julia --project=docs/ -e 'using Pkg; Pkg.Registry.add(RegistrySpec(url = "https://github.com/mimiframework/MimiRegistry.git"))' From e07ee03f0f02dc0983ad047d674efb9c515c252f Mon Sep 17 00:00:00 2001 From: David Anthoff Date: Tue, 8 Oct 2019 22:14:58 -0700 Subject: [PATCH 28/63] Tweak travis script --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index aba9d1c57..f2ee7dc8e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,7 +34,7 @@ jobs: julia: 1.2 os: linux script: - - julia --project=docs/ -e 'using Pkg; Pkg.Registry.add(RegistrySpec(url = "https://github.com/mimiframework/MimiRegistry.git"))' + - julia --project=docs/ -e 'using Pkg; Pkg.update(); Pkg.Registry.add(RegistrySpec(url = "https://github.com/mimiframework/MimiRegistry.git"))' - julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()' - julia --project=docs/ --color=yes docs/make.jl after_success: skip From 57b679dfb87fea03bee66a05c3a355882378d978 Mon Sep 17 00:00:00 2001 From: David Anthoff Date: Wed, 9 Oct 2019 08:57:05 -0700 Subject: [PATCH 29/63] Fix travis --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f2ee7dc8e..8b5a3880c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,7 +34,8 @@ jobs: julia: 1.2 os: linux script: - - julia --project=docs/ -e 'using Pkg; Pkg.update(); Pkg.Registry.add(RegistrySpec(url = "https://github.com/mimiframework/MimiRegistry.git"))' + - julia -e 'using Pkg; Pkg.update()' + - julia --project=docs/ -e 'using Pkg; Pkg.Registry.add(RegistrySpec(url = "https://github.com/mimiframework/MimiRegistry.git"))' - julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()' - julia --project=docs/ --color=yes docs/make.jl after_success: skip From 165b937ec27e8e6f798ff27ee502de48aff28aa7 Mon Sep 17 00:00:00 2001 From: lrennels Date: Wed, 9 Oct 2019 11:03:34 -0700 Subject: [PATCH 30/63] Include newlines in filters; fix bug --- docs/src/tutorials/tutorial_1.md | 4 ++-- docs/src/tutorials/tutorial_2.md | 6 +++--- docs/src/tutorials/tutorial_3.md | 7 ++++--- docs/src/tutorials/tutorial_4.md | 23 +++++++---------------- 4 files changed, 16 insertions(+), 24 deletions(-) diff --git a/docs/src/tutorials/tutorial_1.md b/docs/src/tutorials/tutorial_1.md index 60311d3f5..826b6ef01 100644 --- a/docs/src/tutorials/tutorial_1.md +++ b/docs/src/tutorials/tutorial_1.md @@ -134,7 +134,7 @@ Mimi provides support for plotting using [VegaLite](https://github.com/vega/vega If you wish to explore the results graphically, use the explorer UI, described [here](https://www.mimiframework.org/Mimi.jl/stable/userguide/#Plotting-and-the-Explorer-UI-1) in Section 5 of the Mimi User Guide. To explore all variables and parameters of FUND in a dynamic UI app window, use the [`explore`](@ref) function called with the model as the required first argument, and the optional argument of the `title` The menu on the left hand side will list each element in a label formatted as `component: variable/parameter`. -```jldoctest tutorial1; output = false, filter = r".*" +```jldoctest tutorial1; output = false, filter = r".*"s explore(m, title = "My Window") # output @@ -148,7 +148,7 @@ save("MyFilePath.svg", p) ``` More specifically for our tutorial use of FUND, try: -```jldoctest tutorial1; output = false, filter = r".*" +```jldoctest tutorial1; output = false, filter = r".*"s p = Mimi.plot(m, :socioeconomic, :income) save("MyFilePath.svg", p) diff --git a/docs/src/tutorials/tutorial_2.md b/docs/src/tutorials/tutorial_2.md index 6317183d5..539c44c54 100644 --- a/docs/src/tutorials/tutorial_2.md +++ b/docs/src/tutorials/tutorial_2.md @@ -44,7 +44,7 @@ pkg> registry add https://github.com/mimiframework/MimiRegistry.git ``` You simply need to add the DICE2010 model with -``` +```julia add MimiDICE2010 ``` You have now successfully downloaded DICE to your local machine. @@ -53,7 +53,7 @@ You have now successfully downloaded DICE to your local machine. The next step is to run DICE. If you wish to first get more aquainted with the model itself, take a look at the provided online documentation. Now run DICE using the provided API for the package: -```jldoctest tutorial2; output = false +```jldoctest tutorial2; output = false, filter = r".*"s using MimiDICE2010 m = MimiDICE2010.get_model() run(m) @@ -65,7 +65,7 @@ run(m) Note that 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. In this case, the function `MimiDICE2010.get_model()` has the signature -``` +```julia get_model(params=nothing) ``` Thus there are no required arguments, although the user can input `params`, a dictionary definining the parameters of the model. diff --git a/docs/src/tutorials/tutorial_3.md b/docs/src/tutorials/tutorial_3.md index 98404acf0..c6ea8d4c4 100644 --- a/docs/src/tutorials/tutorial_3.md +++ b/docs/src/tutorials/tutorial_3.md @@ -159,7 +159,7 @@ m[:emissions, :E] 92022.29655492865 ``` Finally we can visualize the results: -```jldoctest tutorial3; output = false, filter = r".*" +```jldoctest tutorial3; output = false, filter = r".*"s using VegaLite # Plot model results @@ -188,6 +188,7 @@ As this model is also more complex and spread across several files, we will also ```jldoctest tutorial3; output = false using Mimi + @defcomp grosseconomy begin regions = Index() #Note that a regional index is defined here @@ -225,7 +226,7 @@ end Save this component as **`gross_economy.jl`** -```jldoctest tutorial3; output = false +```jldoctest tutorial3; output = false, filter = r".*"s using Mimi #Make sure to call Mimi again @defcomp emissions begin @@ -386,7 +387,7 @@ m[:emissions, :E_Global] 36444.054899836294 38226.21934898662 ``` -```jldoctest tutorial3; output = false, filter = r".*" +```jldoctest tutorial3; output = false, filter = r".*"s # Observe model result graphs explore(m) diff --git a/docs/src/tutorials/tutorial_4.md b/docs/src/tutorials/tutorial_4.md index 0e8ba7d49..6d85b88fb 100644 --- a/docs/src/tutorials/tutorial_4.md +++ b/docs/src/tutorials/tutorial_4.md @@ -235,24 +235,17 @@ Next, use the `run` function to run the simulation for the specified simulation In its simplest use, the `run` function generates and iterates over a sample of trial data from the distributions of the random variables defined in the `SimulationDef`, perturbing the subset of Mimi's "external parameters" that have been assigned random variables, and then runs the given Mimi model(s) for each set of trial data. The function returns a `SimulationInstance`, which holds a copy of the original `SimulationDef` in addition to trials information (`trials`, `current_trial`, and `current_data`), the model list `models`, and results information in `results`. Optionally, trial values and/or model results are saved to CSV files. Note that if there is concern about in-memory storage space for the results, use the `results_in_memory` flag set to `false` to incrementally clear the results from memory. -```julia +``````jldoctest tutorial4; output = false, filter = r".*"s # Run 100 trials, and optionally save results to the indicated directories si = run(sd, m, 100; trials_output_filename = "/tmp/trialdata.csv", results_output_dir="/tmp/tutorial4") -``` -We can then take a look at the results saved in memory - -```jldoctest tutorial4; output = false, setup = :(si = run(sd, m, 100; trials_output_filename = "/tmp/trialdata.csv", results_output_dir="/tmp/tutorial4")) # Explore the results saved in-memory by indexing into the returned SimulationInstance. # Values are save from each trial for each variable or parameter specified by the call to "save()" at the end of the @defsim block. K_results = si[:grosseconomy, :K] E_results = si[:emissions, :E] -size(E_results) == (6000, 4) # These results are DataFrames, with one value for each trial for each region and year - # output -true ``` ### Step 4. Explore and Plot Results @@ -260,7 +253,7 @@ As described in the internals documentation [here](https://github.com/mimiframew To view your results in an interactive application viewer, simply call: -```jldoctest tutorial4; output = false, filter = r".*" +```jldoctest tutorial4; output = false, filter = r".*"s explore(si) # output @@ -269,7 +262,7 @@ explore(si) If desired, you may also include a `title` for your application window. If more than one model was run in your Simulation, indicate which model you would like to explore with the `model` keyword argument, which defaults to 1. Finally, if your model leverages different scenarios, you **must** indicate the `scenario_name`. -```jldoctest tutorial4; output = false, filter = r".*" +```jldoctest tutorial4; output = false, filter = r".*"s explore(si; title = "MyWindow", model_index = 1) # we do not indicate scen_name here since we have no scenarios # output @@ -278,7 +271,7 @@ explore(si; title = "MyWindow", model_index = 1) # we do not indicate scen_name To view the results for one of the saved variables from the `save` command in `@defsim`, use the (unexported to avoid namespace collisions) `Mimi.plot` function. This function has the same keyword arguments and requirements as `explore` (except for `title`), and three required arguments: the `SimulationInstance`, the component name (as a `Symbol`), and the variable name (as a `Symbol`). -```jldoctest tutorial4; output = false, filter = r".*" +```jldoctest tutorial4; output = false, filter = r".*"s Mimi.plot(si, :grosseconomy, :K) # output @@ -286,7 +279,7 @@ Mimi.plot(si, :grosseconomy, :K) ``` To save your figure, use the `save` function to save typical file formats such as [PNG](https://en.wikipedia.org/wiki/Portable_Network_Graphics), [SVG](https://en.wikipedia.org/wiki/Scalable_Vector_Graphics), [PDF](https://en.wikipedia.org/wiki/PDF) and [EPS](https://en.wikipedia.org/wiki/Encapsulated_PostScript) files. Note that while `explore(sim_inst)` returns interactive plots for several graphs, `Mimi.plot(si, :foo, :bar)` will return only static plots. -```jldoctest tutorial4; output = false, filter = r".*" +```jldoctest tutorial4; output = false, filter = r".*"s p = Mimi.plot(si, :grosseconomy, :K) save("MyFigure.png", p) @@ -325,7 +318,7 @@ MCSData() ### 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 tutorial4; output = false, filter = r".*" +```jldoctest tutorial4; 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) @@ -372,7 +365,7 @@ my_scc_calculation (generic function with 1 method) Now that we have our post-trial function, we can proceed to obtain our two models and run the simulation. Note that we are using a Mimi MarginalModel `mm` from MimiDICE2010, which is a Mimi object that holds both the base model and the model with the additional pulse of emissions. -```jldoctest tutorial4; output = false, +```jldoctest tutorial4; output = false, filter = r".*"s # Build the marginal model mm = MimiDICE2010.get_marginal_model(year = scc_year) # The additional emissions pulse will be added in the specified year @@ -381,11 +374,9 @@ si = run(sd, mm, N; trials_output_filename = "ecs_sample.csv", post_trial_func = # View the scc_results by retrieving them from the payload object scc_results = Mimi.payload(si)[2] # Recall that the SCC array was the second of two arrays we stored in the payload tuple -size(scc_results) == (N, 3) # output -true ``` ### Simulation Modification Functions From ee3823136adc6fd6471bfc60614fc486325b7200 Mon Sep 17 00:00:00 2001 From: Cora Kingdon Date: Thu, 10 Oct 2019 14:39:59 -0400 Subject: [PATCH 31/63] small edits to tutorials 1 and 2 --- docs/src/tutorials/tutorial_1.md | 27 +++++++++++++-------------- docs/src/tutorials/tutorial_2.md | 30 ++++++++++++++---------------- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/docs/src/tutorials/tutorial_1.md b/docs/src/tutorials/tutorial_1.md index 826b6ef01..081a9959b 100644 --- a/docs/src/tutorials/tutorial_1.md +++ b/docs/src/tutorials/tutorial_1.md @@ -11,24 +11,22 @@ If you have not yet prepared these, go back to the main tutorial page and follow ### Step 1. Download FUND -The first step in this process is downloading the FUND model, which is now made easy with the Mimi registry. Assuming you have already done the one-time run of the following to connect your julia installation with the central Mimi registry of Mimi models +The first step in this process is downloading the FUND model, which is now made easy with the Mimi registry. Assuming you have already done the one-time run of the following command to connect your julia installation with the central Mimi registry of Mimi models: ```julia pkg> registry add https://github.com/mimiframework/MimiRegistry.git ``` -You simply need to add the FUND model with -``` -add MimiFUND +You simply need to add the FUND model in the Pkg REPL with: +```julia +pkg> add MimiFUND ``` ### Step 2. Run FUND -The next step is to run FUND. If you wish to first get more aquainted with the model itself, take a look at the provided online documentation. - -In order to run FUND, you will need to have the packages `Distributions` and `StatsBase` installed, and if not do so by entering [Pkg mode](https://docs.julialang.org/en/v1/stdlib/Pkg/index.html) by typing `]`, and then `add StatsBase` and `add Distributions`. +The next step is to run FUND. If you wish to first get more acquainted with the model itself, take a look at the provided online [documentation](http://www.fund-model.org). -Now open a julia REPL and type +Now open a julia REPL and type the following command to load the MimiFUND package into the current environment: ```jldoctest tutorial1; output = false using MimiFUND @@ -36,7 +34,7 @@ using MimiFUND # output ``` -to access the public API to FUND, which currently includes the function `MimiFUND.get_model` (which can also be called with the exported and identical function `getfund`). This function returns a version of fund allowing for different user specifications. Here we will first get the model, and then use the `run` function to run it. +Now we can access the public API of FUND, including the function `MimiFUND.get_model`. This function returns a copy of the default FUND model. Here we will first get the model, and then use the `run` function to run it. ```jldoctest tutorial1; output = false m = MimiFUND.get_model() @@ -48,16 +46,17 @@ run(m) Note that 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. -In this case, the function `get_model` has the signature +In the MimiFUND package, the function `get_model` has the signature ```julia get_model(; nsteps = default_nsteps, datadir = default_datadir, params = default_params) ``` -Thus there are no required arguments, although the user can input `nsteps` to define the number of timesteps (years in this case) the model runs for, `datadir` to define the location of the input data, and `params`, a dictionary definining the parameters of the model. For example, if you wish to see only the first 100 timesteps,you may use: -```julia +Thus there are no required arguments, although the user can input `nsteps` to define the number of timesteps (years in this case) the model runs for, `datadir` to define the location of the input data, and `params`, a dictionary definining the parameters of the model. For example, if you wish to run only the first 200 timesteps, you may use: +```jldoctest tutorial1; output = false using MimiFUND -m = MimiFUND.get_model(nsteps = 100) +m = MimiFUND.get_model(nsteps = 200) run(m) ``` + ### Step 3. Access Results: Values After the model has been run, you may access the results (the calculated variable values in each component) in a few different ways. @@ -76,7 +75,7 @@ m[:ComponentName, :VariableName] # returns the whole array of values m[:ComponentName, :VariableName][100] # returns just the 100th value ``` -Indexing into a model with the name of the component and variable will return an array with values from each timestep. You may index into this array to get one value (as in the second line, which returns just the 100th value). Note that if the requested variable is two-dimensional, then a 2-D array will be returned. For example, try taking a look at the `income` variable of the `socioeconomic` component using the code below: +Indexing into a model with the name of the component and variable will return an array with values from each timestep. You may index into this array to get one value (as in the second line, which returns just the 100th value). Note that if the requested variable is two-dimensional, then a 2-D array will be returned. For example, try taking a look at the `income` variable of the `socioeconomic` component of FUND using the code below: ```jldoctest tutorial1; output = false m[:socioeconomic, :income] m[:socioeconomic, :income][100] diff --git a/docs/src/tutorials/tutorial_2.md b/docs/src/tutorials/tutorial_2.md index 539c44c54..1667d054f 100644 --- a/docs/src/tutorials/tutorial_2.md +++ b/docs/src/tutorials/tutorial_2.md @@ -1,6 +1,6 @@ # Tutorial 2: Modify an Existing Model -This tutorial walks through the steps to modify an existing model. There are several existing models publically available on Github, and for the purposes of this tutorial we will use MimiDICE2010, available on Github [here](https://github.com/anthofflab/MimiDICE2010.jl). +This tutorial walks through the steps to modify an existing model. There are several existing models publically available on the [MimiRegistry](https://github.com/mimiframework/MimiRegistry), and for the purposes of this tutorial we will use the `MimiDICE2010` model. Working through the following tutorial will require: @@ -9,11 +9,9 @@ Working through the following tutorial will require: If you have not yet prepared these, go back to the main tutorial page and follow the instructions for their download. -Futhermore, this tutorial uses the [DICE](https://github.com/anthofflab/MimiDICE2010.jl) model as an example. Downloading `DICE` uses similar steps to those described for `FUND` in Tutorial 1 Steps 1 and 2. - ## Introduction -There are various ways to modify an existing model, and this tutorial aims to introduce the Mimi API relevant to this broad category of tasks. It is important to note that regardless of the goals and complexities of your modifications, the API aims to allow for modification **without alteration of the original code for the model being modified**. Instead, you will download and run the new model, and then use API calls to modify it. This means that in practice, you should not need to alter the source code of the model they are modifying. Thus, it is easy to keep up with any external updates or improvements made to that model. +There are various ways to modify an existing model, and this tutorial aims to introduce the Mimi API relevant to this broad category of tasks. It is important to note that regardless of the goals and complexities of your modifications, the API aims to allow for modification **without alteration of the original code for the model being modified**. Instead, you will download and run the existing model, and then use API calls to modify it. This means that in practice, you should not need to alter the source code of the model you are modifying. Thus, it is easy to keep up with any external updates or improvements made to that model. Possible modifications range in complexity, from simply altering parameter values, to adjusting an existing component, to adding a brand new component. These take advantage of the public API listed [here](https://www.mimiframework.org/Mimi.jl/dev/reference/), as well as other functions listed in the Mimi Documentation. @@ -26,32 +24,32 @@ When the original model calls [`set_param!`](@ref), Mimi creates an external par ```julia update_param!(mymodel, :parametername, newvalues) # update values only -update_param!(mymodel, :parametername, newvalues, update_timesteps=true) # also update time keys +update_param!(mymodel, :parametername, newvalues, update_timesteps=true) # also update time keys. Only necessary if the time dimension of the model has been changed. ``` -Also note that in the code above,`newvalues` must be the same size and type (or be able to convert to the type) of the old values stored in that parameter. +Also note that in the code above, `newvalues` must be the same size and type (or be able to convert to the type) of the old values stored in that parameter. If you wish to alter connections within an existing model, [`disconnect_param!`](@ref) and [`connect_param!`](@ref) can be used in conjunction with each other to update the connections within the model, although this is more likely to be done as part of larger changes involving components themslves, as discussed in the next subsection. ## Parametric Modifications: DICE Example -### Step 1. Download DICE +### Step 1. Download MimiDICE2010 -The first step in this process is downloading the FUND model, which is now made easy with the Mimi registry. Assuming you have already done the one-time run of the following to connect your julia installation with the central Mimi registry of Mimi models +The first step in this process is downloading the DICE2010 model, which is now made easy with the Mimi registry. Assuming you have already done the one-time run of the following to connect your julia installation with the central Mimi registry of Mimi models: ```julia pkg> registry add https://github.com/mimiframework/MimiRegistry.git ``` -You simply need to add the DICE2010 model with +You simply need to add the MimiDICE2010 model in the Pkg REPL with: ```julia -add MimiDICE2010 +pkg> add MimiDICE2010 ``` -You have now successfully downloaded DICE to your local machine. +You have now successfully downloaded MimiDICE2010 to your local machine. ### Step 2. Run DICE -The next step is to run DICE. If you wish to first get more aquainted with the model itself, take a look at the provided online documentation. Now run DICE using the provided API for the package: +The next step is to run DICE using the provided API for the package: ```jldoctest tutorial2; output = false, filter = r".*"s using MimiDICE2010 @@ -68,7 +66,7 @@ In this case, the function `MimiDICE2010.get_model()` has the signature ```julia get_model(params=nothing) ``` -Thus there are no required arguments, although the user can input `params`, a dictionary definining the parameters of the model. +Thus there are no required arguments, although the user can input `params`, a dictionary definining the parameters of the model. If nothing is provided, the model will be built with the default parameters for DICE2010. ### Step 3. Altering Parameters @@ -91,7 +89,7 @@ run(m) ``` -A more complex example may 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: +A more complex example may 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 @@ -105,7 +103,7 @@ set_dimension!(m, :time, years) [2000, 2010, 2020, 2030, 2040, 2050, 2060, 2070, 2080, 2090 … 2400, 2410, 2420, 2430, 2440, 2450, 2460, 2470, 2480, 2490, 2500] ``` -Next, create a dictionary `params` with one entry (k, v) per external parameter by name k to value v. Each key k must be a symbol or convert to a symbol matching the name of an external parameter that already exists in the model definition. Part of this dictionary may look like: +Next, create a dictionary `params` with one entry `(k, v)` per external parameter by name `k` to value `v`. Each key `k` must be a symbol or convert to a symbol matching the name of an external parameter that already exists in the model definition. Part of this dictionary may look like: ```julia params = Dict{Any, Any}() @@ -137,4 +135,4 @@ If you wish to modify the component structure we recommend you also look into th ## Component and Structural Modifications: DICE Example - This example is in progress and will be built out soon. +This example is in progress and will be built out soon. From 643adb5cbe465cff68f98a19b2a5271ee836a477 Mon Sep 17 00:00:00 2001 From: lrennels Date: Thu, 10 Oct 2019 18:04:44 -0700 Subject: [PATCH 32/63] Fix doctest; udpate reference.md --- docs/src/reference.md | 2 -- docs/src/tutorials/tutorial_1.md | 5 ++++- src/core/defs.jl | 11 +++++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/docs/src/reference.md b/docs/src/reference.md index 01d357ca8..1b7834b5e 100644 --- a/docs/src/reference.md +++ b/docs/src/reference.md @@ -22,9 +22,7 @@ is_first is_last is_time is_timestep -load_comps modeldef -name parameters parameter_names parameter_dimensions diff --git a/docs/src/tutorials/tutorial_1.md b/docs/src/tutorials/tutorial_1.md index 081a9959b..5f9879826 100644 --- a/docs/src/tutorials/tutorial_1.md +++ b/docs/src/tutorials/tutorial_1.md @@ -51,10 +51,13 @@ In the MimiFUND package, the function `get_model` has the signature get_model(; nsteps = default_nsteps, datadir = default_datadir, params = default_params) ``` Thus there are no required arguments, although the user can input `nsteps` to define the number of timesteps (years in this case) the model runs for, `datadir` to define the location of the input data, and `params`, a dictionary definining the parameters of the model. For example, if you wish to run only the first 200 timesteps, you may use: -```jldoctest tutorial1; output = false +```jldoctest tutorial1; output = false, filter = r".*"s using MimiFUND m = MimiFUND.get_model(nsteps = 200) run(m) + +# output + ``` ### Step 3. Access Results: Values diff --git a/src/core/defs.jl b/src/core/defs.jl index d90319d67..9249f9c3c 100644 --- a/src/core/defs.jl +++ b/src/core/defs.jl @@ -350,6 +350,12 @@ function parameter_unit(obj::AbstractComponentDef, param_name::Symbol) return unit(param) end +""" + parameter_dimensions(obj::AbstractComponentDef, param_name::Symbol) + +Returns the names of the dimensions of parameter `param_name`. +""" + function parameter_dimensions(obj::AbstractComponentDef, param_name::Symbol) param = parameter(obj, param_name) return dim_names(param) @@ -567,6 +573,11 @@ function variable_dimensions(obj::AbstractCompositeComponentDef, comp_path::Comp return dim_names(var) end +""" + function variable_dimensions(obj::AbstractComponentDef, name::Symbol) + +Returns the names of the dimensions of variable `name`. +""" function variable_dimensions(obj::AbstractComponentDef, name::Symbol) var = variable(obj, name) return dim_names(var) From 94bc5c3cda5a57df9a8ada26135c0ea5fa4f9e3d Mon Sep 17 00:00:00 2001 From: Cora Kingdon Date: Fri, 11 Oct 2019 12:22:25 -0400 Subject: [PATCH 33/63] remove doctest filter on one block --- docs/src/tutorials/tutorial_1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/tutorials/tutorial_1.md b/docs/src/tutorials/tutorial_1.md index 5f9879826..d6b4703bb 100644 --- a/docs/src/tutorials/tutorial_1.md +++ b/docs/src/tutorials/tutorial_1.md @@ -51,7 +51,7 @@ In the MimiFUND package, the function `get_model` has the signature get_model(; nsteps = default_nsteps, datadir = default_datadir, params = default_params) ``` Thus there are no required arguments, although the user can input `nsteps` to define the number of timesteps (years in this case) the model runs for, `datadir` to define the location of the input data, and `params`, a dictionary definining the parameters of the model. For example, if you wish to run only the first 200 timesteps, you may use: -```jldoctest tutorial1; output = false, filter = r".*"s +```jldoctest tutorial1; output = false using MimiFUND m = MimiFUND.get_model(nsteps = 200) run(m) From 685378651b5ba3fb4597a5698f72b506cb368708 Mon Sep 17 00:00:00 2001 From: lrennels Date: Fri, 11 Oct 2019 12:52:29 -0700 Subject: [PATCH 34/63] Try running doctests from make.jl --- docs/make.jl | 2 ++ docs/src/tutorials/tutorial_1.md | 2 +- src/core/defs.jl | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index 4d58fe423..52dbbb623 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -2,6 +2,8 @@ using Documenter, Mimi DocMeta.setdocmeta!(Mimi, :DocTestSetup, :(using Mimi; using Distributions; using MimiDICE2010; using MimiFUND); recursive=true) +doctest(Mimi) + makedocs( modules = [Mimi], sitename = "Mimi.jl", diff --git a/docs/src/tutorials/tutorial_1.md b/docs/src/tutorials/tutorial_1.md index d6b4703bb..5f9879826 100644 --- a/docs/src/tutorials/tutorial_1.md +++ b/docs/src/tutorials/tutorial_1.md @@ -51,7 +51,7 @@ In the MimiFUND package, the function `get_model` has the signature get_model(; nsteps = default_nsteps, datadir = default_datadir, params = default_params) ``` Thus there are no required arguments, although the user can input `nsteps` to define the number of timesteps (years in this case) the model runs for, `datadir` to define the location of the input data, and `params`, a dictionary definining the parameters of the model. For example, if you wish to run only the first 200 timesteps, you may use: -```jldoctest tutorial1; output = false +```jldoctest tutorial1; output = false, filter = r".*"s using MimiFUND m = MimiFUND.get_model(nsteps = 200) run(m) diff --git a/src/core/defs.jl b/src/core/defs.jl index 9249f9c3c..207ff0f93 100644 --- a/src/core/defs.jl +++ b/src/core/defs.jl @@ -355,7 +355,6 @@ end Returns the names of the dimensions of parameter `param_name`. """ - function parameter_dimensions(obj::AbstractComponentDef, param_name::Symbol) param = parameter(obj, param_name) return dim_names(param) From 8570ae8bcd72640af057447ebaec1f45e5a7c8c5 Mon Sep 17 00:00:00 2001 From: lrennels Date: Fri, 8 Nov 2019 20:23:23 -0800 Subject: [PATCH 35/63] Update FUND version --- test/dependencies/run_dependency_tests.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/dependencies/run_dependency_tests.jl b/test/dependencies/run_dependency_tests.jl index dd7bb8a66..c959201de 100644 --- a/test/dependencies/run_dependency_tests.jl +++ b/test/dependencies/run_dependency_tests.jl @@ -2,7 +2,7 @@ using Pkg packages_to_test = [ ("https://github.com/anthofflab/MimiRICE2010.jl.git", "v2.0.3", "MimiRICE2010"), - ("https://github.com/fund-model/MimiFUND.jl.git", "v3.11.8", "MimiFUND") + ("https://github.com/fund-model/MimiFUND.jl.git", "v3.11.9", "MimiFUND") ] for (pkg_url, pkg_rev, pkg_name) in packages_to_test From 95371d02ec4617099075e63e730081149a83a702 Mon Sep 17 00:00:00 2001 From: lrennels Date: Fri, 8 Nov 2019 20:46:24 -0800 Subject: [PATCH 36/63] Fix typo; Add filter to supress deprecation warnings --- docs/src/tutorials/tutorial_1.md | 4 ++-- docs/src/tutorials/tutorial_2.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/tutorials/tutorial_1.md b/docs/src/tutorials/tutorial_1.md index 5f9879826..0c9a95873 100644 --- a/docs/src/tutorials/tutorial_1.md +++ b/docs/src/tutorials/tutorial_1.md @@ -36,7 +36,7 @@ using MimiFUND ``` Now we can access the public API of FUND, including the function `MimiFUND.get_model`. This function returns a copy of the default FUND model. Here we will first get the model, and then use the `run` function to run it. -```jldoctest tutorial1; output = false +```jldoctest tutorial1; output = false, filter = r".*"s m = MimiFUND.get_model() run(m) @@ -103,7 +103,7 @@ getdataframe(m, :socioeconomic=>:income)[1:16,:] # results for all regions in fi # output -16×3 DataFrames.DataFrame +16×3 DataFrame │ Row │ time │ regions │ income │ │ │ Int64 │ String │ Float64⍰ │ ├─────┼───────┼─────────┼──────────┤ diff --git a/docs/src/tutorials/tutorial_2.md b/docs/src/tutorials/tutorial_2.md index 1667d054f..1fe43a4c9 100644 --- a/docs/src/tutorials/tutorial_2.md +++ b/docs/src/tutorials/tutorial_2.md @@ -81,7 +81,7 @@ using Mimi For example, 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`. If you wanted to change this value from its default value of `3.200` to `3.000` in both components,you would use the following code: -```jldoctest tutorial2; output = false +```jldoctest tutorial2; output = false, filter = r".*"s update_param!(m, :fco22x, 3.000) run(m) From 75e0c07ead45ef8d64ec4f7ddeacf4b30fb57350 Mon Sep 17 00:00:00 2001 From: lrennels Date: Fri, 8 Nov 2019 22:33:20 -0800 Subject: [PATCH 37/63] Fix typo --- docs/src/tutorials/tutorial_1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/tutorials/tutorial_1.md b/docs/src/tutorials/tutorial_1.md index 0c9a95873..57202a681 100644 --- a/docs/src/tutorials/tutorial_1.md +++ b/docs/src/tutorials/tutorial_1.md @@ -103,7 +103,7 @@ getdataframe(m, :socioeconomic=>:income)[1:16,:] # results for all regions in fi # output -16×3 DataFrame +16×3 DataFrames.DataFrame │ Row │ time │ regions │ income │ │ │ Int64 │ String │ Float64⍰ │ ├─────┼───────┼─────────┼──────────┤ From 808df07a3197822938b778e4b3e5e49d2aac1acf Mon Sep 17 00:00:00 2001 From: lrennels Date: Sat, 9 Nov 2019 19:41:18 -0800 Subject: [PATCH 38/63] Add missing docstrings for reference.md --- src/core/types/time.jl | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/core/types/time.jl b/src/core/types/time.jl index b03378bf4..e47be60ae 100644 --- a/src/core/types/time.jl +++ b/src/core/types/time.jl @@ -22,6 +22,14 @@ struct VariableTimestep{TIMES} <: AbstractTimestep end end +""" + TimestepValue + +A user-facing API used to index into a `TimestepArray` in `run_timestep` functions +and containing a `value` of the same Type as the times in the `TimstepArray` it + is used to index into, and an optional `offset` in terms of +timesteps. +""" struct TimestepValue{T} value::T offset::Int @@ -31,6 +39,12 @@ struct TimestepValue{T} end end +""" + TimestepValue + +A user-facing API used to index into a `TimestepArray` in `run_timestep` functions +and containing an `index` in terms of timesteps. +""" struct TimestepIndex index::Int end From a890f7c8ad2b2894c4d27378ccab04d667eb516a Mon Sep 17 00:00:00 2001 From: lrennels Date: Sat, 9 Nov 2019 19:45:10 -0800 Subject: [PATCH 39/63] Fix typo --- docs/src/tutorials/tutorial_4.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/tutorials/tutorial_4.md b/docs/src/tutorials/tutorial_4.md index 6d85b88fb..72c7fc9ee 100644 --- a/docs/src/tutorials/tutorial_4.md +++ b/docs/src/tutorials/tutorial_4.md @@ -235,7 +235,7 @@ Next, use the `run` function to run the simulation for the specified simulation In its simplest use, the `run` function generates and iterates over a sample of trial data from the distributions of the random variables defined in the `SimulationDef`, perturbing the subset of Mimi's "external parameters" that have been assigned random variables, and then runs the given Mimi model(s) for each set of trial data. The function returns a `SimulationInstance`, which holds a copy of the original `SimulationDef` in addition to trials information (`trials`, `current_trial`, and `current_data`), the model list `models`, and results information in `results`. Optionally, trial values and/or model results are saved to CSV files. Note that if there is concern about in-memory storage space for the results, use the `results_in_memory` flag set to `false` to incrementally clear the results from memory. -``````jldoctest tutorial4; output = false, filter = r".*"s +```jldoctest tutorial4; output = false, filter = r".*"s # Run 100 trials, and optionally save results to the indicated directories si = run(sd, m, 100; trials_output_filename = "/tmp/trialdata.csv", results_output_dir="/tmp/tutorial4") From b4f7039c3b33e69ee356c81e46bf66c5ed11c507 Mon Sep 17 00:00:00 2001 From: lrennels Date: Sat, 9 Nov 2019 21:17:44 -0800 Subject: [PATCH 40/63] Use getdataframe for simulation instance --- docs/src/tutorials/tutorial_4.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/tutorials/tutorial_4.md b/docs/src/tutorials/tutorial_4.md index 72c7fc9ee..0af404a88 100644 --- a/docs/src/tutorials/tutorial_4.md +++ b/docs/src/tutorials/tutorial_4.md @@ -239,10 +239,10 @@ In its simplest use, the `run` function generates and iterates over a sample of # Run 100 trials, and optionally save results to the indicated directories si = run(sd, m, 100; trials_output_filename = "/tmp/trialdata.csv", results_output_dir="/tmp/tutorial4") -# Explore the results saved in-memory by indexing into the returned SimulationInstance. +# Explore the results saved in-memory by usign getdataframe into the returned SimulationInstance. # Values are save from each trial for each variable or parameter specified by the call to "save()" at the end of the @defsim block. -K_results = si[:grosseconomy, :K] -E_results = si[:emissions, :E] +K_results = getdataframe(si, :grosseconomy, :K) +E_results = getdataframe(si, :emissions, :E) # output From 0f3e34015747b695a180c0dc29ff13ea50f80640 Mon Sep 17 00:00:00 2001 From: Lisa Rennels <31779240+lrennels@users.noreply.github.com> Date: Sat, 9 Nov 2019 22:04:55 -0800 Subject: [PATCH 41/63] Remove explicit doctest call from make.jl Documenter should automatically run dockets without explicitly calling doctest(Mimi) --- docs/make.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/make.jl b/docs/make.jl index 52dbbb623..5f9028680 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -2,7 +2,7 @@ using Documenter, Mimi DocMeta.setdocmeta!(Mimi, :DocTestSetup, :(using Mimi; using Distributions; using MimiDICE2010; using MimiFUND); recursive=true) -doctest(Mimi) +# doctest(Mimi) makedocs( modules = [Mimi], From da02eec3aba758a35e87bb0ad428a129fcd695e6 Mon Sep 17 00:00:00 2001 From: lrennels Date: Sat, 9 Nov 2019 23:13:58 -0800 Subject: [PATCH 42/63] Test that Travis doctests fail --- docs/src/tutorials/tutorial_1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/tutorials/tutorial_1.md b/docs/src/tutorials/tutorial_1.md index 57202a681..f4051ed4e 100644 --- a/docs/src/tutorials/tutorial_1.md +++ b/docs/src/tutorials/tutorial_1.md @@ -32,7 +32,7 @@ Now open a julia REPL and type the following command to load the MimiFUND packag using MimiFUND # output - +THIS SHOULD CAUSE AN ERROR ``` Now we can access the public API of FUND, including the function `MimiFUND.get_model`. This function returns a copy of the default FUND model. Here we will first get the model, and then use the `run` function to run it. From 47d55e949a5c803e90707805188d1ad2697d0050 Mon Sep 17 00:00:00 2001 From: lrennels Date: Sat, 9 Nov 2019 23:16:08 -0800 Subject: [PATCH 43/63] Add test to see if Travis will fail doctestS --- docs/src/tutorials/tutorial_1.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/src/tutorials/tutorial_1.md b/docs/src/tutorials/tutorial_1.md index f4051ed4e..444120cc5 100644 --- a/docs/src/tutorials/tutorial_1.md +++ b/docs/src/tutorials/tutorial_1.md @@ -32,6 +32,7 @@ Now open a julia REPL and type the following command to load the MimiFUND packag using MimiFUND # output + THIS SHOULD CAUSE AN ERROR ``` Now we can access the public API of FUND, including the function `MimiFUND.get_model`. This function returns a copy of the default FUND model. Here we will first get the model, and then use the `run` function to run it. From bc7e8d60b71fb7727c36eea5b9e10bb9a4a8ca02 Mon Sep 17 00:00:00 2001 From: Lisa Rennels <31779240+lrennels@users.noreply.github.com> Date: Sun, 10 Nov 2019 01:38:21 -0800 Subject: [PATCH 44/63] Remove bug tests. --- docs/src/tutorials/tutorial_1.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/src/tutorials/tutorial_1.md b/docs/src/tutorials/tutorial_1.md index 444120cc5..57202a681 100644 --- a/docs/src/tutorials/tutorial_1.md +++ b/docs/src/tutorials/tutorial_1.md @@ -33,7 +33,6 @@ using MimiFUND # output -THIS SHOULD CAUSE AN ERROR ``` Now we can access the public API of FUND, including the function `MimiFUND.get_model`. This function returns a copy of the default FUND model. Here we will first get the model, and then use the `run` function to run it. From 0a137d1adde09da4e82b758bc27a61b0e64e6eb2 Mon Sep 17 00:00:00 2001 From: lrennels Date: Sun, 10 Nov 2019 02:05:38 -0800 Subject: [PATCH 45/63] Change makedocs strict setting to true --- docs/make.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/make.jl b/docs/make.jl index 5f9028680..c1aaa5ab3 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -5,6 +5,7 @@ DocMeta.setdocmeta!(Mimi, :DocTestSetup, :(using Mimi; using Distributions; usin # doctest(Mimi) makedocs( + strict = true, modules = [Mimi], sitename = "Mimi.jl", pages = [ From a3771be86272ce97c58793137da3730d22878f67 Mon Sep 17 00:00:00 2001 From: lrennels Date: Sun, 10 Nov 2019 10:32:10 -0800 Subject: [PATCH 46/63] Move doctesting to outside of makedocs --- docs/make.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index c1aaa5ab3..12daa49df 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -2,10 +2,10 @@ using Documenter, Mimi DocMeta.setdocmeta!(Mimi, :DocTestSetup, :(using Mimi; using Distributions; using MimiDICE2010; using MimiFUND); recursive=true) -# doctest(Mimi) +doctest(Mimi) makedocs( - strict = true, + doctest = false, modules = [Mimi], sitename = "Mimi.jl", pages = [ From b72afbddb93dcefda87f6eced21d733b29f33e57 Mon Sep 17 00:00:00 2001 From: Cora Kingdon Date: Mon, 11 Nov 2019 15:54:36 -0500 Subject: [PATCH 47/63] Fix minor typos --- docs/src/tutorials/tutorial_4.md | 4 ++-- src/core/defs.jl | 8 ++++---- src/core/types/time.jl | 11 +++++------ 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/docs/src/tutorials/tutorial_4.md b/docs/src/tutorials/tutorial_4.md index 0af404a88..b8da561e8 100644 --- a/docs/src/tutorials/tutorial_4.md +++ b/docs/src/tutorials/tutorial_4.md @@ -239,8 +239,8 @@ In its simplest use, the `run` function generates and iterates over a sample of # Run 100 trials, and optionally save results to the indicated directories si = run(sd, m, 100; trials_output_filename = "/tmp/trialdata.csv", results_output_dir="/tmp/tutorial4") -# Explore the results saved in-memory by usign getdataframe into the returned SimulationInstance. -# Values are save from each trial for each variable or parameter specified by the call to "save()" at the end of the @defsim block. +# Explore the results saved in-memory by using getdataframe with the returned SimulationInstance. +# Values are saved from each trial for each variable or parameter specified by the call to "save()" at the end of the @defsim block. K_results = getdataframe(si, :grosseconomy, :K) E_results = getdataframe(si, :emissions, :E) diff --git a/src/core/defs.jl b/src/core/defs.jl index e1f7b8b93..0476d483b 100644 --- a/src/core/defs.jl +++ b/src/core/defs.jl @@ -353,8 +353,8 @@ end """ parameter_dimensions(obj::AbstractComponentDef, param_name::Symbol) -Return the names of the dimensions of parameter `param_name` exposed in the composite -component definition indicated by`obj`. +Return the names of the dimensions of parameter `param_name` exposed in the component +definition indicated by `obj`. """ function parameter_dimensions(obj::AbstractComponentDef, param_name::Symbol) param = parameter(obj, param_name) @@ -588,8 +588,8 @@ end """ variable_dimensions(obj::AbstractComponentDef, name::Symbol) -Return the names of the dimensions of variable `name` exposed in the composite -component definition indicated by`obj`. +Return the names of the dimensions of variable `name` exposed in the component definition +indicated by `obj`. """ function variable_dimensions(obj::AbstractComponentDef, name::Symbol) var = variable(obj, name) diff --git a/src/core/types/time.jl b/src/core/types/time.jl index e47be60ae..f999ad389 100644 --- a/src/core/types/time.jl +++ b/src/core/types/time.jl @@ -25,10 +25,9 @@ end """ TimestepValue -A user-facing API used to index into a `TimestepArray` in `run_timestep` functions -and containing a `value` of the same Type as the times in the `TimstepArray` it - is used to index into, and an optional `offset` in terms of -timesteps. +A user-facing type used to index into a `TimestepArray` in `run_timestep` functions, +containing a `value` of the same Type as the times in the `TimstepArray` which is used to +index into the array at that position, with an optional Int `offset` in terms of timesteps. """ struct TimestepValue{T} value::T @@ -42,8 +41,8 @@ end """ TimestepValue -A user-facing API used to index into a `TimestepArray` in `run_timestep` functions -and containing an `index` in terms of timesteps. +A user-facing type used to index into a `TimestepArray` in `run_timestep` functions, +containing an Int `index` that indicates the position in the array in terms of timesteps. """ struct TimestepIndex index::Int From 7bcb1a7b1c63ff6aaaa8ea78902971166bda1afe Mon Sep 17 00:00:00 2001 From: Cora Kingdon Date: Mon, 11 Nov 2019 15:55:01 -0500 Subject: [PATCH 48/63] Remove uncessary compats from docs Project.toml --- docs/Project.toml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/docs/Project.toml b/docs/Project.toml index 2032b6522..3bd09cfa7 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -8,10 +8,5 @@ StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" VegaLite = "112f6efa-9a02-5b7d-90c0-432ed331239a" [compat] -Distributions = "0.21" -Documenter = "0.23" -Mimi = "0.9.3" -MimiDICE2010 = "0.1" -MimiFUND = "3.11" -StatsBase = "0.32" -VegaLite = "0.7" +Documenter = "~0.23" +MimiFUND = "~3.11.9" From 0d784be4b92eafbd56b93c9c37fba92f41a649b8 Mon Sep 17 00:00:00 2001 From: Cora Kingdon Date: Tue, 12 Nov 2019 09:06:35 -0500 Subject: [PATCH 49/63] Remove MimiFUND compat in docs --- docs/Project.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/Project.toml b/docs/Project.toml index 3bd09cfa7..7d322f7c0 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -9,4 +9,3 @@ VegaLite = "112f6efa-9a02-5b7d-90c0-432ed331239a" [compat] Documenter = "~0.23" -MimiFUND = "~3.11.9" From 9331ef48582375563875ad78f3422cfde3986e5f Mon Sep 17 00:00:00 2001 From: Cora Kingdon Date: Tue, 12 Nov 2019 13:28:36 -0500 Subject: [PATCH 50/63] Move `doctest(Mimi)` into test suite --- Project.toml | 5 ++++- docs/Project.toml | 11 ----------- docs/make.jl | 4 ---- test/runtests.jl | 2 ++ 4 files changed, 6 insertions(+), 16 deletions(-) delete mode 100644 docs/Project.toml diff --git a/Project.toml b/Project.toml index 3f50622bc..dd6e69c35 100644 --- a/Project.toml +++ b/Project.toml @@ -43,6 +43,7 @@ GraphPlot = "0.3, 0.4" IteratorInterfaceExtensions = "^0.1.1, ^1" TableTraits = "^0.4.1, ^1" julia = "1" +Documenter = "~0.23" [extras] DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" @@ -57,6 +58,8 @@ Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" ZipFile = "a5390f91-8eb1-5f08-bee0-b1d1ffed6cea" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +MimiDICE2010 = "4f2c5d70-42a7-11e9-1de8-c370bd984083" +MimiFUND = "b3ba11de-429f-11e9-29f7-cb478ab96e7c" [targets] -test = ["Pkg", "Statistics", "NamedArrays", "ExcelFiles", "ExcelReaders", "DelimitedFiles", "Documenter", "Random", "Test", "ZipFile", "MacroTools", "Query"] +test = ["Pkg", "Statistics", "NamedArrays", "ExcelFiles", "ExcelReaders", "DelimitedFiles", "Documenter", "Random", "Test", "ZipFile", "MacroTools", "Query", "MimiFUND", "MimiDICE2010"] diff --git a/docs/Project.toml b/docs/Project.toml deleted file mode 100644 index 7d322f7c0..000000000 --- a/docs/Project.toml +++ /dev/null @@ -1,11 +0,0 @@ -[deps] -Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" -Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" -Mimi = "e4e893b0-ee5e-52ea-8111-44b3bdec128c" -MimiDICE2010 = "4f2c5d70-42a7-11e9-1de8-c370bd984083" -MimiFUND = "b3ba11de-429f-11e9-29f7-cb478ab96e7c" -StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" -VegaLite = "112f6efa-9a02-5b7d-90c0-432ed331239a" - -[compat] -Documenter = "~0.23" diff --git a/docs/make.jl b/docs/make.jl index 12daa49df..7e04c491b 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,9 +1,5 @@ using Documenter, Mimi -DocMeta.setdocmeta!(Mimi, :DocTestSetup, :(using Mimi; using Distributions; using MimiDICE2010; using MimiFUND); recursive=true) - -doctest(Mimi) - makedocs( doctest = false, modules = [Mimi], diff --git a/test/runtests.jl b/test/runtests.jl index 36988f539..fd13671ae 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,6 +2,8 @@ using Mimi using Test using Documenter +doctest(Mimi) + @testset "Mimi" begin @info("test_main.jl") From 77f03302a4c639e9196da2b743e885668df75f48 Mon Sep 17 00:00:00 2001 From: Cora Kingdon Date: Wed, 13 Nov 2019 13:18:03 -0500 Subject: [PATCH 51/63] Fix doctest setup --- .travis.yml | 2 ++ docs/Project.toml | 5 +++++ 2 files changed, 7 insertions(+) create mode 100644 docs/Project.toml diff --git a/.travis.yml b/.travis.yml index 8c3fe5e3b..3fb255044 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,6 +25,8 @@ branches: - /v(\d+)\.(\d+)\.(\d+)/ env: - PYTHON="" MIMI_RUN_DEPENDENCY_TESTS="TRUE" +before_script: + - julia -e 'using Pkg; Pkg.Registry.add(RegistrySpec(url ="https://github.com/mimiframework/MimiRegistry.git"))' after_success: - julia -e 'using Pkg; cd(Pkg.dir("Mimi")); Pkg.add("Coverage"); using Coverage; Codecov.submit(process_folder())' diff --git a/docs/Project.toml b/docs/Project.toml new file mode 100644 index 000000000..2ccde0209 --- /dev/null +++ b/docs/Project.toml @@ -0,0 +1,5 @@ +[deps] +Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" + +[compat] +Documenter = "~0.23" \ No newline at end of file From 9ad35477ea4f005e7b37e8fabf14e44a910eda1a Mon Sep 17 00:00:00 2001 From: lrennels Date: Fri, 15 Nov 2019 15:44:48 -0800 Subject: [PATCH 52/63] Update travis.yml file --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3fb255044..a7f014d9f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,7 +26,7 @@ branches: env: - PYTHON="" MIMI_RUN_DEPENDENCY_TESTS="TRUE" before_script: - - julia -e 'using Pkg; Pkg.Registry.add(RegistrySpec(url ="https://github.com/mimiframework/MimiRegistry.git"))' + - julia -e 'using Pkg; Pkg.update(); Pkg.Registry.add(RegistrySpec(url ="https://github.com/mimiframework/MimiRegistry.git")) after_success: - julia -e 'using Pkg; cd(Pkg.dir("Mimi")); Pkg.add("Coverage"); using Coverage; Codecov.submit(process_folder())' From 01ef1fa9bee47ebbb68762c10817930df9a67981 Mon Sep 17 00:00:00 2001 From: Cora Kingdon Date: Mon, 18 Nov 2019 10:26:41 -0500 Subject: [PATCH 53/63] missing quote --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a7f014d9f..9ae197f97 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,7 +26,7 @@ branches: env: - PYTHON="" MIMI_RUN_DEPENDENCY_TESTS="TRUE" before_script: - - julia -e 'using Pkg; Pkg.update(); Pkg.Registry.add(RegistrySpec(url ="https://github.com/mimiframework/MimiRegistry.git")) + - julia -e 'using Pkg; Pkg.update(); Pkg.Registry.add(RegistrySpec(url ="https://github.com/mimiframework/MimiRegistry.git"))' after_success: - julia -e 'using Pkg; cd(Pkg.dir("Mimi")); Pkg.add("Coverage"); using Coverage; Codecov.submit(process_folder())' From e4b0b96720c82ece2186b684ddd12e66507d44bd Mon Sep 17 00:00:00 2001 From: lrennels Date: Mon, 18 Nov 2019 14:07:37 -0800 Subject: [PATCH 54/63] Move doctest to botto of testing suite file --- test/runtests.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index fd13671ae..e9b76b106 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,8 +2,6 @@ using Mimi using Test using Documenter -doctest(Mimi) - @testset "Mimi" begin @info("test_main.jl") @@ -105,3 +103,5 @@ doctest(Mimi) run(`$(Base.julia_cmd()) --startup-file=no --project=$(joinpath(@__DIR__, "dependencies", ".")) $(joinpath(@__DIR__, "dependencies", "run_dependency_tests.jl"))`) end end + +doctest(Mimi) From 2902d7df9d6bc7f5f628042bc81ad8b8e2271c78 Mon Sep 17 00:00:00 2001 From: lrennels Date: Mon, 18 Nov 2019 22:30:42 -0800 Subject: [PATCH 55/63] Remove doctesting of explore function --- docs/src/tutorials/tutorial_1.md | 5 +--- docs/src/tutorials/tutorial_3.md | 14 ++++------ docs/src/tutorials/tutorial_4.md | 10 ++------ test/runtests.jl | 4 +-- test/test_explorer_model.jl | 44 ++++++++++++++++++++++++++++++++ test/test_timesteparrays.jl | 2 -- 6 files changed, 54 insertions(+), 25 deletions(-) diff --git a/docs/src/tutorials/tutorial_1.md b/docs/src/tutorials/tutorial_1.md index 57202a681..5a3deabef 100644 --- a/docs/src/tutorials/tutorial_1.md +++ b/docs/src/tutorials/tutorial_1.md @@ -136,11 +136,8 @@ Mimi provides support for plotting using [VegaLite](https://github.com/vega/vega If you wish to explore the results graphically, use the explorer UI, described [here](https://www.mimiframework.org/Mimi.jl/stable/userguide/#Plotting-and-the-Explorer-UI-1) in Section 5 of the Mimi User Guide. To explore all variables and parameters of FUND in a dynamic UI app window, use the [`explore`](@ref) function called with the model as the required first argument, and the optional argument of the `title` The menu on the left hand side will list each element in a label formatted as `component: variable/parameter`. -```jldoctest tutorial1; output = false, filter = r".*"s +```julia explore(m, title = "My Window") - -# output - ``` Alternatively, in order to view just one parameter or variable, call the function [`explore`](@ref) as below to return a plot object and automatically display the plot in a viewer, assuming [`explore`](@ref) is the last command executed. This call will return the type `VegaLite.VLSpec`, which you may interact with using the API described in the [VegaLite.jl](https://github.com/fredo-dedup/VegaLite.jl) documentation. For example, [VegaLite.jl](https://github.com/fredo-dedup/VegaLite.jl) plots can be saved as [PNG](https://en.wikipedia.org/wiki/Portable_Network_Graphics), [SVG](https://en.wikipedia.org/wiki/Scalable_Vector_Graphics), [PDF](https://en.wikipedia.org/wiki/PDF) and [EPS](https://en.wikipedia.org/wiki/Encapsulated_PostScript) files. You may save a plot using the `save` function. Note that saving an interactive plot in a non-interactive file format, such as .pdf or .svg will result in a warning `WARN Can not resolve event source: window`, but the plot will be saved as a static image. If you wish to preserve interactive capabilities, you may save it using the .vegalite file extension. If you then open this file in Jupyter lab, the interactive aspects will be preserved. diff --git a/docs/src/tutorials/tutorial_3.md b/docs/src/tutorials/tutorial_3.md index c6ea8d4c4..2e8e518fe 100644 --- a/docs/src/tutorials/tutorial_3.md +++ b/docs/src/tutorials/tutorial_3.md @@ -158,18 +158,17 @@ m[:emissions, :E] 87208.1411195294 92022.29655492865 ``` -Finally we can visualize the results: +Finally we can visualize the results via plotting: ```jldoctest tutorial3; output = false, filter = r".*"s using VegaLite # Plot model results Mimi.plot(m, :emissions, :E); - +``` +and via explorer: +```julia # Observe all model result graphs in UI explore(m) - -# output - ``` ## Constructing A Multi-Region Model @@ -387,10 +386,7 @@ m[:emissions, :E_Global] 36444.054899836294 38226.21934898662 ``` -```jldoctest tutorial3; output = false, filter = r".*"s +```julia # Observe model result graphs explore(m) - -# output - ``` diff --git a/docs/src/tutorials/tutorial_4.md b/docs/src/tutorials/tutorial_4.md index b8da561e8..5e6eda4c4 100644 --- a/docs/src/tutorials/tutorial_4.md +++ b/docs/src/tutorials/tutorial_4.md @@ -253,20 +253,14 @@ As described in the internals documentation [here](https://github.com/mimiframew To view your results in an interactive application viewer, simply call: -```jldoctest tutorial4; output = false, filter = r".*"s +```julia explore(si) - -# output - ``` If desired, you may also include a `title` for your application window. If more than one model was run in your Simulation, indicate which model you would like to explore with the `model` keyword argument, which defaults to 1. Finally, if your model leverages different scenarios, you **must** indicate the `scenario_name`. -```jldoctest tutorial4; output = false, filter = r".*"s +```julia explore(si; title = "MyWindow", model_index = 1) # we do not indicate scen_name here since we have no scenarios - -# output - ``` To view the results for one of the saved variables from the `save` command in `@defsim`, use the (unexported to avoid namespace collisions) `Mimi.plot` function. This function has the same keyword arguments and requirements as `explore` (except for `title`), and three required arguments: the `SimulationInstance`, the component name (as a `Symbol`), and the variable name (as a `Symbol`). diff --git a/test/runtests.jl b/test/runtests.jl index e9b76b106..fd13671ae 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,6 +2,8 @@ using Mimi using Test using Documenter +doctest(Mimi) + @testset "Mimi" begin @info("test_main.jl") @@ -103,5 +105,3 @@ using Documenter run(`$(Base.julia_cmd()) --startup-file=no --project=$(joinpath(@__DIR__, "dependencies", ".")) $(joinpath(@__DIR__, "dependencies", "run_dependency_tests.jl"))`) end end - -doctest(Mimi) diff --git a/test/test_explorer_model.jl b/test/test_explorer_model.jl index f2032d978..16f209879 100644 --- a/test/test_explorer_model.jl +++ b/test/test_explorer_model.jl @@ -99,3 +99,47 @@ run(m2) #spec creation for MyComp.a should warn because over 2 indexed dimensions @test_logs (:warn, "MyComp2.a has > 2 indexed dimensions, not yet implemented in explorer") explore(m2) @test_logs (:warn, "MyComp2.a has > 2 indexed dimensions, not yet implemented in explorer") _spec_for_item(m2, :MyComp2, :a) + +#7. Test TimestepArrays with time not as the first dimension + +@defcomp gdp begin + growth = Parameter(index=[regions, foo, time, 2]) # test that time is not first but not last + gdp = Variable(index=[regions, foo, time, 2]) + gdp0 = Parameter(index=[regions, foo, 2]) + + pgrowth = Parameter(index=[regions, 3, time]) # test time as last + pop = Variable(index=[regions, 3, time]) + + mat = Parameter(index=[regions, time]) # test time as last for a matrix + mat2 = Variable(index=[regions, time]) + + function run_timestep(p, v, d, ts) + if is_first(ts) + v.gdp[:, :, ts, :] = (1 .+ p.growth[:, :, ts, :]) .* p.gdp0 + v.pop[:, :, ts] = zeros(2, 3) + else + v.gdp[:, :, ts, :] = (1 .+ p.growth[:, :, ts, :]) .* v.gdp[:, :, ts-1, :] + v.pop[:, :, ts] = v.pop[:, :, ts-1] .+ p.pgrowth[:, :, ts] + end + v.mat2[:, ts] = p.mat[:, ts] + end +end + +time_index = 2000:2100 +regions = ["OECD","non-OECD"] +nsteps=length(time_index) + +m = Model() +set_dimension!(m, :time, time_index) +set_dimension!(m, :regions, regions) +set_dimension!(m, :foo, 3) +add_comp!(m, gdp) +set_param!(m, :gdp, :gdp0, [3; 7] .* ones(length(regions), 3, 2)) +set_param!(m, :gdp, :growth, [0.02; 0.03] .* ones(length(regions), 3, nsteps, 2)) +set_leftover_params!(m, Dict{String, Any}([ + "pgrowth" => ones(length(regions), 3, nsteps), + "mat" => rand(length(regions), nsteps) +])) +run(m) +w = explore(m) +close(w) diff --git a/test/test_timesteparrays.jl b/test/test_timesteparrays.jl index 2f3f437f2..86b39e8a4 100644 --- a/test/test_timesteparrays.jl +++ b/test/test_timesteparrays.jl @@ -667,8 +667,6 @@ set_leftover_params!(m, Dict{String, Any}([ "mat" => rand(length(regions), nsteps) ])) run(m) -w = explore(m) -close(w) @test size(m[:gdp, :gdp]) == (length(regions), 3, length(time_index), 2) From 04d54ab661b36ed2bbf2686cf99115ff7239b6a8 Mon Sep 17 00:00:00 2001 From: lrennels Date: Mon, 18 Nov 2019 23:42:17 -0800 Subject: [PATCH 56/63] Add # output line to fix bug --- docs/src/tutorials/tutorial_3.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/src/tutorials/tutorial_3.md b/docs/src/tutorials/tutorial_3.md index 2e8e518fe..f64355c93 100644 --- a/docs/src/tutorials/tutorial_3.md +++ b/docs/src/tutorials/tutorial_3.md @@ -164,6 +164,9 @@ using VegaLite # Plot model results Mimi.plot(m, :emissions, :E); + +# output + ``` and via explorer: ```julia From 723a3aaffec2a70539126eca9f569c6619295b3d Mon Sep 17 00:00:00 2001 From: David Anthoff Date: Sat, 23 Nov 2019 08:46:05 -0800 Subject: [PATCH 57/63] Move doctest call --- test/runtests.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index eeabd29fb..aed04bba4 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -3,8 +3,6 @@ import Electron using Test using Documenter -doctest(Mimi) - Electron.prep_test_env() @testset "Mimi" begin @@ -104,6 +102,8 @@ Electron.prep_test_env() include("mcs/runtests.jl") + doctest(Mimi) + if get(ENV, "MIMI_RUN_DEPENDENCY_TESTS", "")=="TRUE" run(`$(Base.julia_cmd()) --startup-file=no --project=$(joinpath(@__DIR__, "dependencies", ".")) $(joinpath(@__DIR__, "dependencies", "run_dependency_tests.jl"))`) end From 7198310831f0b95f1a5a8916010e508cd554abdb Mon Sep 17 00:00:00 2001 From: David Anthoff Date: Sat, 23 Nov 2019 08:54:06 -0800 Subject: [PATCH 58/63] Add MimiRegistry in build on gh --- deps/build.jl | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 deps/build.jl diff --git a/deps/build.jl b/deps/build.jl new file mode 100644 index 000000000..5fdaabf99 --- /dev/null +++ b/deps/build.jl @@ -0,0 +1,5 @@ +using Pkg + +if haskey(ENV, "GITHUB_ACTIONS") && ENV["GITHUB_ACTIONS"] == "true" + Pkg.Registry.add("https://github.com/mimiframework/MimiRegistry") +end From cc8e704f696c5d7986886c7bc8406f15c7c935cc Mon Sep 17 00:00:00 2001 From: David Anthoff Date: Sat, 23 Nov 2019 09:24:05 -0800 Subject: [PATCH 59/63] Try new strategy for package install --- Project.toml | 2 -- deps/build.jl | 5 ----- test/runtests.jl | 5 +++++ 3 files changed, 5 insertions(+), 7 deletions(-) delete mode 100644 deps/build.jl diff --git a/Project.toml b/Project.toml index a018fcf78..c9ae53f19 100644 --- a/Project.toml +++ b/Project.toml @@ -74,8 +74,6 @@ Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" ZipFile = "a5390f91-8eb1-5f08-bee0-b1d1ffed6cea" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" -MimiDICE2010 = "4f2c5d70-42a7-11e9-1de8-c370bd984083" -MimiFUND = "b3ba11de-429f-11e9-29f7-cb478ab96e7c" [targets] test = ["Pkg", "Statistics", "NamedArrays", "ExcelFiles", "ExcelReaders", "DelimitedFiles", "Documenter", "Random", "Test", "ZipFile", "MacroTools", "Query", "MimiFUND", "MimiDICE2010"] diff --git a/deps/build.jl b/deps/build.jl deleted file mode 100644 index 5fdaabf99..000000000 --- a/deps/build.jl +++ /dev/null @@ -1,5 +0,0 @@ -using Pkg - -if haskey(ENV, "GITHUB_ACTIONS") && ENV["GITHUB_ACTIONS"] == "true" - Pkg.Registry.add("https://github.com/mimiframework/MimiRegistry") -end diff --git a/test/runtests.jl b/test/runtests.jl index aed04bba4..edf7138dc 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,8 +1,13 @@ using Mimi import Electron using Test +using Pkg using Documenter +# We need these for the doctests +Pkg.add(PackageSpec(url="https://github.com/fund-model/MimiFUND.jl", rev="master")) +Pkg.add(PackageSpec(url="https://github.com/anthofflab/MimiDICE2010.jl", rev="master")) + Electron.prep_test_env() @testset "Mimi" begin From f793174463efad4729a5a61b6d042cb590ae833d Mon Sep 17 00:00:00 2001 From: David Anthoff Date: Sat, 23 Nov 2019 09:26:10 -0800 Subject: [PATCH 60/63] Fix bug in Project.toml --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index c9ae53f19..114887236 100644 --- a/Project.toml +++ b/Project.toml @@ -76,4 +76,4 @@ ZipFile = "a5390f91-8eb1-5f08-bee0-b1d1ffed6cea" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" [targets] -test = ["Pkg", "Statistics", "NamedArrays", "ExcelFiles", "ExcelReaders", "DelimitedFiles", "Documenter", "Random", "Test", "ZipFile", "MacroTools", "Query", "MimiFUND", "MimiDICE2010"] +test = ["Pkg", "Statistics", "NamedArrays", "ExcelFiles", "ExcelReaders", "DelimitedFiles", "Documenter", "Random", "Test", "ZipFile", "MacroTools", "Query"] From 6fb320af5a5af4fd1629abf2b2c3628e6cdac4e3 Mon Sep 17 00:00:00 2001 From: David Anthoff Date: Sat, 23 Nov 2019 09:52:02 -0800 Subject: [PATCH 61/63] Fix a doctest bug --- docs/src/tutorials/tutorial_1.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/src/tutorials/tutorial_1.md b/docs/src/tutorials/tutorial_1.md index 5a3deabef..1cfc24bd7 100644 --- a/docs/src/tutorials/tutorial_1.md +++ b/docs/src/tutorials/tutorial_1.md @@ -5,9 +5,9 @@ This tutorial walks through the steps to download, run, and view the output of a Working through the following tutorial will require: - [Julia v1.1.0](https://julialang.org/downloads/) or higher -- [Mimi v0.9.4](https://github.com/mimiframework/Mimi.jl) +- [Mimi v0.9.4](https://github.com/mimiframework/Mimi.jl) -If you have not yet prepared these, go back to the main tutorial page and follow the instructions for their download. +If you have not yet prepared these, go back to the main tutorial page and follow the instructions for their download. ### Step 1. Download FUND @@ -24,9 +24,9 @@ pkg> add MimiFUND ### Step 2. Run FUND -The next step is to run FUND. If you wish to first get more acquainted with the model itself, take a look at the provided online [documentation](http://www.fund-model.org). +The next step is to run FUND. If you wish to first get more acquainted with the model itself, take a look at the provided online [documentation](http://www.fund-model.org). -Now open a julia REPL and type the following command to load the MimiFUND package into the current environment: +Now open a julia REPL and type the following command to load the MimiFUND package into the current environment: ```jldoctest tutorial1; output = false using MimiFUND @@ -63,7 +63,7 @@ run(m) ### Step 3. Access Results: Values After the model has been run, you may access the results (the calculated variable values in each component) in a few different ways. -Start off by importing the Mimi package to your space with +Start off by importing the Mimi package to your space with ```jldoctest tutorial1; output = false using Mimi @@ -80,8 +80,8 @@ m[:ComponentName, :VariableName][100] # returns just the 100th value ``` Indexing into a model with the name of the component and variable will return an array with values from each timestep. You may index into this array to get one value (as in the second line, which returns just the 100th value). Note that if the requested variable is two-dimensional, then a 2-D array will be returned. For example, try taking a look at the `income` variable of the `socioeconomic` component of FUND using the code below: ```jldoctest tutorial1; output = false -m[:socioeconomic, :income] -m[:socioeconomic, :income][100] +m[:socioeconomic, :income] +m[:socioeconomic, :income][100] # output @@ -103,7 +103,7 @@ getdataframe(m, :socioeconomic=>:income)[1:16,:] # results for all regions in fi # output -16×3 DataFrames.DataFrame +16×3 DataFrame │ Row │ time │ regions │ income │ │ │ Int64 │ String │ Float64⍰ │ ├─────┼───────┼─────────┼──────────┤ @@ -127,7 +127,7 @@ getdataframe(m, :socioeconomic=>:income)[1:16,:] # results for all regions in fi ### Step 4. Access Results: Plots and Graphs -After running the FUND model, you may also explore the results using plots and graphs. +After running the FUND model, you may also explore the results using plots and graphs. Mimi provides support for plotting using [VegaLite](https://github.com/vega/vega-lite) and [VegaLite.jl](https://github.com/fredo-dedup/VegaLite.jl) within the Mimi Explorer UI, and the [LightGraphs](https://github.com/JuliaGraphs/LightGraphs.jl) and [MetaGraphs](https://github.com/JuliaGraphs/MetaGraphs.jl) for the [`plot_comp_graph`](@ref) function. From 473ff22055a6387da23f1b06795d6976d99cbce1 Mon Sep 17 00:00:00 2001 From: David Anthoff Date: Sat, 23 Nov 2019 11:51:45 -0800 Subject: [PATCH 62/63] Rearrange some code --- test/runtests.jl | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index edf7138dc..d0e2b4d83 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,13 +1,15 @@ -using Mimi -import Electron -using Test using Pkg -using Documenter -# We need these for the doctests +# We need these for the doctests. We install them before we load any +# package so that we don't run into precompile problems Pkg.add(PackageSpec(url="https://github.com/fund-model/MimiFUND.jl", rev="master")) Pkg.add(PackageSpec(url="https://github.com/anthofflab/MimiDICE2010.jl", rev="master")) +using Mimi +import Electron +using Test +using Documenter + Electron.prep_test_env() @testset "Mimi" begin From a570d75c530b0a78de0174482c7c1a83ae5746f2 Mon Sep 17 00:00:00 2001 From: lrennels Date: Tue, 26 Nov 2019 13:20:03 -0800 Subject: [PATCH 63/63] Doctest dataframes instead of arrays --- docs/src/tutorials/tutorial_3.md | 86 ++++++++++++++++---------------- 1 file changed, 42 insertions(+), 44 deletions(-) diff --git a/docs/src/tutorials/tutorial_3.md b/docs/src/tutorials/tutorial_3.md index f64355c93..d32bb26ba 100644 --- a/docs/src/tutorials/tutorial_3.md +++ b/docs/src/tutorials/tutorial_3.md @@ -132,31 +132,30 @@ m = construct_model() run(m) # Check model results -m[:emissions, :E] +getdataframe(m, :emissions, :E) # or m[:emissions, :E_Global] to return just the Array # output -20-element Array{Union{Missing, Float64},1}: - 4211.090591062387 - 15079.467021779814 - 23922.34250656177 - 30255.835991903466 - 35175.69763623216 - 39293.007327689294 - 42947.659714791596 - 46344.92375399115 - 49617.22023134532 - 52854.33568269569 - 56119.657629233516 - 59459.60027273144 - 62909.41007665139 - 66496.902005524 - 70244.9426237597 - 74173.13994450058 - 78299.0143500136 - 82638.82192356508 - 87208.1411195294 - 92022.29655492865 +20×2 DataFrame +│ Row │ time │ E │ +│ │ Int64 │ Float64⍰ │ +├─────┼───────┼──────────┤ +│ 1 │ 2015 │ 4211.09 │ +│ 2 │ 2020 │ 15079.5 │ +│ 3 │ 2025 │ 23922.3 │ +│ 4 │ 2030 │ 30255.8 │ +│ 5 │ 2035 │ 35175.7 │ +│ 6 │ 2040 │ 39293.0 │ +│ 7 │ 2045 │ 42947.7 │ +⋮ +│ 13 │ 2075 │ 62909.4 │ +│ 14 │ 2080 │ 66496.9 │ +│ 15 │ 2085 │ 70244.9 │ +│ 16 │ 2090 │ 74173.1 │ +│ 17 │ 2095 │ 78299.0 │ +│ 18 │ 2100 │ 82638.8 │ +│ 19 │ 2105 │ 87208.1 │ +│ 20 │ 2110 │ 92022.3 │ ``` Finally we can visualize the results via plotting: ```jldoctest tutorial3; output = false, filter = r".*"s @@ -363,31 +362,30 @@ m = construct_MyModel() run(m) # Check results -m[:emissions, :E_Global] +getdataframe(m, :emissions, :E_Global) # or m[:emissions, :E_Global] to return just the Array # output -20-element Array{Union{Missing, Float64},1}: - 2392.079742190377 - 7740.882236708259 - 11842.440651248193 - 14629.668992409268 - 16686.547618646313 - 18338.39368484932 - 19763.668705801665 - 21066.519405994735 - 22310.85541553882 - 23537.444423151617 - 24773.181203244094 - 26036.421133213866 - 27340.180766955593 - 28694.115410299266 - 30105.7665949292 - 31581.36120424167 - 33126.32978664035 - 34745.64653516074 - 36444.054899836294 - 38226.21934898662 +20×2 DataFrame +│ Row │ time │ E_Global │ +│ │ Int64 │ Float64⍰ │ +├─────┼───────┼──────────┤ +│ 1 │ 2015 │ 2392.08 │ +│ 2 │ 2020 │ 7740.88 │ +│ 3 │ 2025 │ 11842.4 │ +│ 4 │ 2030 │ 14629.7 │ +│ 5 │ 2035 │ 16686.5 │ +│ 6 │ 2040 │ 18338.4 │ +│ 7 │ 2045 │ 19763.7 │ +⋮ +│ 13 │ 2075 │ 27340.2 │ +│ 14 │ 2080 │ 28694.1 │ +│ 15 │ 2085 │ 30105.8 │ +│ 16 │ 2090 │ 31581.4 │ +│ 17 │ 2095 │ 33126.3 │ +│ 18 │ 2100 │ 34745.6 │ +│ 19 │ 2105 │ 36444.1 │ +│ 20 │ 2110 │ 38226.2 │ ``` ```julia # Observe model result graphs