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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 1 addition & 48 deletions docs/src/internals/structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,53 +78,6 @@ In the new version, all component definitions are represented by one type, `Comp

![Object structure](figs/MimiModelArchitecture-v1.png)

## 3. New macro `@defmodel`

The `@defmodel` macro provides simplified syntax for model creation, eliminating many redundant parameters. For example, you can write:

```
@defmodel mymodel begin

index[time] = 2015:5:2110

component(grosseconomy)
component(emissions)

# Set parameters for the grosseconomy component
grosseconomy.l = [(1. + 0.015)^t *6404 for t in 1:20]
grosseconomy.tfp = [(1 + 0.065)^t * 3.57 for t in 1:20]
grosseconomy.s = ones(20).* 0.22
grosseconomy.depk = 0.1
grosseconomy.k0 = 130.0
grosseconomy.share = 0.3

# Set parameters for the emissions component
emissions.sigma = [(1. - 0.05)^t *0.58 for t in 1:20]

# Connect pararameters (source_variable => destination_parameter)
grosseconomy.YGROSS => emissions.YGROSS
end
```

which produces these function calls:

```
quote
mymodel = Model()
set_dimension!(mymodel, :time, 2015:5:2110)
add_comp!(mymodel, Main.grosseconomy, :grosseconomy)
add_comp!(mymodel, Main.emissions, :emissions)
set_param!(mymodel, :grosseconomy, :l, [(1.0 + 0.015) ^ t * 6404 for t = 1:20])
set_param!(mymodel, :grosseconomy, :tfp, [(1 + 0.065) ^ t * 3.57 for t = 1:20])
set_param!(mymodel, :grosseconomy, :s, ones(20) * 0.22)
set_param!(mymodel, :grosseconomy, :depk, 0.1)
set_param!(mymodel, :grosseconomy, :k0, 130.0)
set_param!(mymodel, :grosseconomy, :share, 0.3)
set_param!(mymodel, :emissions, :sigma, [(1.0 - 0.05) ^ t * 0.58 for t = 1:20])
connect_param!(mymodel, :emissions, :YGROSS, :grosseconomy, :YGROSS)
end
```

## 4. Pre-compilation and built-in components
## 3. Pre-compilation and built-in components

To get `__precompile__()` to work required moving the creation of "helper" components to an `__init__()` method in Mimi.jl, which is run automatically after Mimi loads. It defines the two "built-in" components, from `adder.jl` and `connector.jl` in the `components` subdirectory.
4 changes: 1 addition & 3 deletions docs/src/ref/ref_API.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,11 @@ get_var_value
hasvalue
is_first
is_last
is_time
is_timestep
modeldef
parameter_names
parameter_dimensions
plot_comp_graph
replace_comp!
replace!
set_dimension!
set_leftover_params!
set_param!
Expand Down
12 changes: 6 additions & 6 deletions docs/src/tutorials/tutorial_2.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ The next step is to run FUND. If you wish to first get more acquainted with the

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

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

# output

```
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, filter = r".*"s
```jldoctest tutorial2; output = false, filter = r".*"s
m = MimiFUND.get_model()
run(m)

Expand All @@ -58,7 +58,7 @@ get_model(; nsteps = default_nsteps, datadir = default_datadir, params = default

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 tutorial2; output = false, filter = r".*"s
using MimiFUND
m = MimiFUND.get_model(nsteps = 200)
run(m)
Expand All @@ -72,7 +72,7 @@ After the model has been run, you may access the results (the calculated variabl

Start off by importing the Mimi package to your space with

```jldoctest tutorial1; output = false
```jldoctest tutorial2; output = false
using Mimi

# output
Expand All @@ -89,7 +89,7 @@ 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
```jldoctest tutorial2; output = false
m[:socioeconomic, :income]
m[:socioeconomic, :income][100]

Expand All @@ -108,7 +108,7 @@ 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, filter = r".*"s
```jldoctest tutorial2; output = false, filter = r".*"s
getdataframe(m, :socioeconomic=>:income) # request one variable from one component
getdataframe(m, :socioeconomic=>:income)[1:16,:] # results for all regions in first year (1950)

Expand Down
2 changes: 1 addition & 1 deletion docs/src/tutorials/tutorial_3.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ Note that here we use the `update_timesteps` flag and set it to `true`, because

## Component and Structural Modifications: The API

Most model modifications will include not only parametric updates, but also strutural changes and component modification, addition, replacement, and deletion along with the required re-wiring of parameters etc. The most useful functions of the common API, in these cases are likely **[`replace_comp!`](@ref), [`add_comp!`](@ref)** along with **`Mimi.delete!`** and the requisite functions for parameter setting and connecting. For detail on the public API functions look at the API reference.
Most model modifications will include not only parametric updates, but also structural changes and component modification, addition, replacement, and deletion along with the required re-wiring of parameters etc. The most useful functions of the common API, in these cases are likely **[`replace!`](@ref), [`add_comp!`](@ref)** along with **`delete!`** and the requisite functions for parameter setting and connecting. For detail on the public API functions look at the API reference.

If you wish to modify the component structure we recommend you also look into the **built-in helper components `adder`, `ConnectorCompVector`, and `ConnectorCompMatrix`** in the `src/components` folder, as these can prove quite useful.

Expand Down
18 changes: 9 additions & 9 deletions docs/src/tutorials/tutorial_4.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,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 how to guide How-to Guide 4: Work with Timesteps, Parameters, and Variables

```jldoctest tutorial3; output = false
```jldoctest tutorial4; output = false
using Mimi # start by importing the Mimi package to your space

@defcomp grosseconomy begin
Expand Down Expand Up @@ -61,7 +61,7 @@ end

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.

```jldoctest tutorial3; output = false
```jldoctest tutorial4; output = false
@defcomp emissions begin
E = Variable(index=[time]) # Total greenhouse gas emissions
sigma = Parameter(index=[time]) # Emissions output ratio
Expand All @@ -88,7 +88,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.

```jldoctest tutorial3; output = false
```jldoctest tutorial4; output = false

using Mimi

Expand Down Expand Up @@ -128,7 +128,7 @@ Note that as an alternative to using many of the `set_param!` calls above, one m

Now we can run the model and examine the results:

```jldoctest tutorial3; output = false, filter = r".*"s
```jldoctest tutorial4; output = false, filter = r".*"s
# Run model
m = construct_model()
run(m)
Expand Down Expand Up @@ -162,7 +162,7 @@ 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.

```jldoctest tutorial3; output = false
```jldoctest tutorial4; output = false
using Mimi

@defcomp grosseconomy begin
Expand Down Expand Up @@ -202,7 +202,7 @@ end

Save this component as **`gross_economy.jl`**

```jldoctest tutorial3; output = false, filter = r".*"s
```jldoctest tutorial4; output = false, filter = r".*"s
using Mimi #Make sure to call Mimi again

@defcomp emissions begin
Expand Down Expand Up @@ -238,7 +238,7 @@ 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.

```jldoctest tutorial3; output = false
```jldoctest tutorial4; output = false
l = Array{Float64}(undef, 20, 3)
for t in 1:20
l[t,1] = (1. + 0.015)^t *2000
Expand Down Expand Up @@ -288,7 +288,7 @@ include("emissions.jl")

export construct_MyModel
```
```jldoctest tutorial3; output = false
```jldoctest tutorial4; output = false
function construct_MyModel()

m = Model()
Expand Down Expand Up @@ -332,7 +332,7 @@ using Mimi
include("MyModel.jl")
using .MyModel
```
```jldoctest tutorial3; output = false, filter = r".*"s
```jldoctest tutorial4; output = false, filter = r".*"s
m = construct_MyModel()
run(m)

Expand Down
22 changes: 10 additions & 12 deletions docs/src/tutorials/tutorial_5.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ You should have `Mimi` installed by now, and if you do not have the `Distributio

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
```jldoctest tutorial5; output = false
using Mimi

# Define the grosseconomy component
Expand Down Expand Up @@ -155,7 +155,7 @@ construct_MyModel (generic function with 1 method)

Then, we obtain a copy of the model:

```jldoctest tutorial4; output = false
```jldoctest tutorial5; output = false
m = construct_MyModel()

# output
Expand All @@ -172,7 +172,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.

The first is the following:
```julia
rv(rv1) = Normal(0, 0.8) # create a random variable called "rv1" with the specified distribution
Expand All @@ -187,7 +187,7 @@ 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, filter = r".*"s
```jldoctest tutorial5; output = false, filter = r".*"s
using Mimi
using Distributions

Expand Down Expand Up @@ -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 tutorial5; 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")

Expand Down Expand Up @@ -279,11 +279,11 @@ 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) 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.
Case: We want to do an SCC calculation with `MimiDICE2010`, which consists of running both a `base` and `modified` 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 `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
```jldoctest tutorial5; output = false
using Mimi
using MimiDICE2010
using Distributions
Expand All @@ -304,7 +304,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".*"s
```jldoctest tutorial5; output = false, filter = r".*"s
# Choose what year to calculate the SCC for
scc_year = 2015
year_idx = findfirst(isequal(scc_year), MimiDICE2010.model_years)
Expand All @@ -331,7 +331,7 @@ In the simple multi-region simulation example, the only values that were saved d

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
```jldoctest tutorial5; 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
Expand All @@ -351,7 +351,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, filter = r".*"s
```julia
Copy link
Collaborator Author

@lrennels lrennels Jun 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed the doctest for now because MimiDICE2010 uses .marginal instead of .modified, can re-add it once the correct version of that model is used

# Build the marginal model
mm = MimiDICE2010.get_marginal_model(year = scc_year) # The additional emissions pulse will be added in the specified year

Expand All @@ -361,8 +361,6 @@ 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

# output

```

#### Simulation Modification Functions
Expand Down
3 changes: 1 addition & 2 deletions src/Mimi.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export
hasvalue,
is_first,
is_last,
is_time,
is_time,
is_timestep,
modeldef,
name,
Expand Down Expand Up @@ -60,7 +60,6 @@ include("core/build.jl")
include("core/connections.jl")
include("core/defs.jl")
include("core/defcomp.jl")
include("core/defmodel.jl")
include("core/defcomposite.jl")
include("core/dimensions.jl")
include("core/instances.jl")
Expand Down
6 changes: 3 additions & 3 deletions src/core/defcomp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -195,13 +195,13 @@ macro defcomp(comp_name, ex)
continue
end

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

# elt_type is one of {:Variable, :Parameter, :Index}
if elt_type == :Index
expr = _generate_dims_expr(name, args, datum_type)
Expand Down
Loading