diff --git a/contrib/test_all_models.jl b/contrib/test_all_models.jl index 224e64186..96b10d2a5 100644 --- a/contrib/test_all_models.jl +++ b/contrib/test_all_models.jl @@ -21,7 +21,7 @@ packages_to_test = [ "MimiSNEASY" => ("https://github.com/anthofflab/MimiSNEASY.jl", "master"), "MimiFAIR" => ("https://github.com/anthofflab/MimiFAIR.jl", "master"), "MimiMAGICC" => ("https://github.com/anthofflab/MimiMAGICC.jl", "master"), - "MimiHECTOR" => ("https://github.com/anthofflab/MimiHector.jl", "master") + "MimiHector" => ("https://github.com/anthofflab/MimiHector.jl", "master") ] using Pkg diff --git a/docs/make.jl b/docs/make.jl index 0ab42ca7a..00c252651 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -12,7 +12,8 @@ makedocs( "2 Run an Existing Model" => "tutorials/tutorial_2.md", "3 Modify an Existing Model" => "tutorials/tutorial_3.md", "4 Create a Model" => "tutorials/tutorial_4.md", - "5 Monte Carlo + Sensitivity Analysis" => "tutorials/tutorial_5.md" + "5 Monte Carlo + Sensitivity Analysis" => "tutorials/tutorial_5.md", + "6 Create a Model with Composite Components" => "tutorials/tutorial_6.md" ], "How-to Guides" => Any[ "How-to Guides Intro" => "howto/howto_main.md", @@ -31,10 +32,14 @@ makedocs( "Reference Guides" => Any[ "Reference Guides Intro" => "ref/ref_main.md", "Mimi API" => "ref/ref_API.md", - "Structures" => "ref/ref_structures.md", + "Structures: Classes.jl and Types" => "ref/ref_structures_classes_types.md", "Structures: Definitions" => "ref/ref_structures_definitions.md", "Structures: Instances" => "ref/ref_structures_instances.md" ], + "Explanations" => Any[ + "Explanations Intro" => "explanations/exp_main.md", + "Models as Packages" => "explanations/exp_pkgs.md" + ], "FAQ" => "faq.md", ], format = Documenter.HTML(prettyurls = get(ENV, "JULIA_NO_LOCAL_PRETTY_URLS", nothing) === nothing) diff --git a/docs/src/explanations/exp_main.md b/docs/src/explanations/exp_main.md new file mode 100644 index 000000000..8281fa2ab --- /dev/null +++ b/docs/src/explanations/exp_main.md @@ -0,0 +1,9 @@ +# Explanations Introduction + +The following reference guides are technical descriptions of the Mimi machinery, organized around the actual code behind Mimi and intended to be information-oriented for those interested in the internals or needing to more deeply understand those aspects in order to carry out their projects. Given the complexity of this code base, these references are not comprehensive, but intended to target some important and relevant aspects of Mimi. + +If you find a bug in these reference guides, or have a clarifying question or suggestion, please reach out via Github Issues or our [Mimi Framework forum](https://forum.mimiframework.org). We welcome your feedback. + +## Available Reference Guides + +- [Explanations: Models as Packages](@ref) provides a high-level explanation of the practice of organizing models as packages. diff --git a/docs/src/explanations/exp_pkgs.md b/docs/src/explanations/exp_pkgs.md new file mode 100644 index 000000000..fbec848b6 --- /dev/null +++ b/docs/src/explanations/exp_pkgs.md @@ -0,0 +1,49 @@ +## Explanations: Models as Packages + +## Models as Packages + +[Pkg](https://docs.julialang.org/en/v1/stdlib/Pkg/index.html) (more detail [here](https://julialang.github.io/Pkg.jl/v1/))is Julia's builtin package manager, and handles operations such as installing, updating and removing packages. It is often convenient to set Mimi models up as julia packages using the steps described [here](https://julialang.github.io/Pkg.jl/v1/creating-packages/). "A package is a project with a `name`, `uuid` and version entry in the `Project.toml` file, and a `src/PackageName.jl` file that defines the module `PackageName`. This file is executed when the package is loaded." + +Models can be registered or unregistered, as described in the next section, but it is **not necessary** to register a package in order to use the `Pkg` interface. + +### Example + +The [MimiDICE2016](https://github.com/AlexandrePavlov/MimiDICE2016.jl) model is an unregistered package. As its README instructs, it can be accessed by: + +Running the following command at the julia package REPL: +```julia +pkg> add https://github.com/AlexandrePavlov/MimiDICE2016.jl +``` +Now you can use `MimiDICE2016` and its exported API: +```julia +using MimiDICE2016 +m = MimiDICE2016.get_model() +run(m) +``` + +## Registries and The Mimi Registry + +Packages can be registered in a [Registry](https://julialang.github.io/Pkg.jl/v1/registries/), and "registries contain information about packages, such as available releases and dependencies, and where they can be downloaded. The [General registry](https://github.com/JuliaRegistries/General) is the default one, and is installed automatically". + +The Mimi registry is a custom registry maintained by the Mimi development team that colocates several Mimi models in one central registry in the same way julia colates packages in the General registry, where `Mimi` and other packages you commonly may use are located. While the development team maintains this registry and has some basic requirements such as continuous integration tesing (CI) and proper package structure as dictated by julia, they do not claim responsibility or knowledge of the content or quality of the models themselves. + +If you are interested in adding a model to the Mimi Registry, please be in touch with the Mimi development team by opening an [Issue on the Registry](https://github.com/mimiframework/MimiRegistry/issues) and/or a question on the [Mimi forum](https://forum.mimiframework.org) if you do not receive a timely response. We will aim to create a standard guide for this process soon. + +### Example + +The [MimiDICE2010] model is a registered package in the Mimi Registry, and can be accessed by: + +Running the following command at the julia package REPL (only required once): +```julia +pkg> registry add https://github.com/mimiframework/MimiRegistry.git +``` +Followed by adding the package: +```julia +pkg> add MimiDICE2010 +``` +Now you can use `MimiDICE2010` and its exported API: +```julia +using MimiDICE2010 +m = MimiDICE2010.get_model() +run(m) +``` diff --git a/docs/src/howto/howto_1.md b/docs/src/howto/howto_1.md index 50e1cc1af..90e352069 100644 --- a/docs/src/howto/howto_1.md +++ b/docs/src/howto/howto_1.md @@ -1,16 +1,20 @@ # How-to Guide 1: Construct and Run a Model -This how-to guide pairs nicely with Tutorial 4: Create a Model, serving as an abbreviated, less-detailed version and refresher for those with some experience with Mimi. If this is your first time constructing and running a Mimi model, we recommend you start with Tutorial 4, which will give you more detailed step-by step instructions. +This how-to guide pairs nicely with Tutorial 4: Create a Model and Tutorial 6: Create a Model with Composite Components, and serves as a higher-level version and refresher for those with some experience with Mimi. If this is your first time constructing and running a Mimi model, we recommend you start with Tutorial 4 (and Tutorial 6 if you are interested in composite components), which will give you more detailed step-by step instructions. ## Defining Components -Any Mimi model is made up of at least one component, so before you construct a model, you need to create your components. +Any Mimi model is made up of at least one component, so before you construct a model, you need to create your components. -A component can have any number of parameters and variables. Parameters are data values that will be provided to the component as input, and variables are values that the component will calculate in the `run_timestep` function when the model is run. The index of a parameter or variable determines the number of dimensions that parameter or variable has. They can be scalar values and have no index, such as parameter 'c' in the example below. They can be one-dimensional, such as the variable 'A' and the parameters 'd' and 'f' below. They can be two dimensional such as variable 'B' and parameter 'e' below. Note that any index other than 'time' must be declared at the top of the component, as shown by `regions = Index()` below. +Mimi provides two types of components, leaf components and composite components, which generally match intuitively with the classic computer science tree data structure. Note that many existing models are "flat models" with one layer of components, and thus only contain leaf components. + +### Leaf Components + +A leaf component can have any number of parameters and variables. Parameters are data values that will be provided to the component as input, and variables are values that the component will calculate in the `run_timestep` function when the model is run. The index of a parameter or variable determines the number of dimensions that parameter or variable has. They can be scalar values and have no index, such as parameter 'c' in the example below. They can be one-dimensional, such as the variable 'A' and the parameters 'd' and 'f' below. They can be two dimensional such as variable 'B' and parameter 'e' below. Note that any index other than 'time' must be declared at the top of the component, as shown by `regions = Index()` below. The user must define a `run_timestep` function for each component. -We define a component in the following way: +We define a leaf component in the following way: ```jldoctest; output = false using Mimi @@ -46,8 +50,94 @@ To access the data in a parameter or to assign a value to a variable, you must u By default, all parameters and variables defined in the `@defcomp` will be allocated storage as scalars or Arrays of type `Float64.` For a description of other data type options, see How-to Guide 4: Work with Timesteps, Parameters, and Variables +### Composite Components + +Composite components can contain any number of subcomponents, **which can be either leaf components or more composite components**. To the degree possible, composite components are designed to operate in the same way as leaf components, although there are a few necessary differences: + +- Leaf components are defined using the macro `@defcomp`, while Composite components are defined using `@defcomposite`. Each macro supports syntax and semantics specific to the type of component. + +- Leaf components support user-defined `run_timestep()` functions, whereas composites have a built-in `run_timestep()` function that iterates over its subcomponents and calls their `run_timestep()` function. + +A composite component can have any number of parameters and variables, which point to one or more parameters or variables in the composite's subcomponents. Data all eventually flows through to the leaf components, where calculations are made at runtime and then data is bubbled up into composite components as necessary. + +Note that it is not imperative that you explicitly define parameters or variables in a composite component. It may be desireable for specific use cases, such as ease of access for future connections, future model modification, connecting multiple subcomponent parameters or variables to one higher level component parameter or variable, or parameter conflict resolution (explained below). + +We define a composite component in the following way: + +First we will need to have defined some leaf components: +```julia +@defcomp Leaf1 begin + par_1_1 = Parameter(index=[time]) + var_1_1 = Variable(index=[time]) + foo = Parameter() + + function run_timestep(p, v, d, t) + v.var_1_1[t] = p.par_1_1[t] + end +end + +@defcomp Leaf2 begin + par_2_1 = Parameter(index=[time]) + par_2_2 = Parameter(index=[time]) + var_2_1 = Variable(index=[time]) + foo = Parameter() + + function run_timestep(p, v, d, t) + v.var_2_1[t] = p.par_2_1[t] + p.foo * p.par_2_2[t] + end +end +``` +Now we construct a composite component `MyCompositeComponent` which holds the two subcomponents, `Leaf1` and `Leaf2`: +```julia +@defcomposite MyCompositeComponent begin + Component(Leaf1) + Component(Leaf2) + + foo1 = Parameter(Leaf1.foo) + foo2 = Parameter(Leaf2.foo) + + var_2_1 = Variable(Leaf2.var_2_1) + + connect(Leaf2.par_2_1, Leaf1.var_1_1) + connect(Leaf2.par_2_2, Leaf1.var_1_1) +end +``` + +The `connect` calls are responsible for making internal connections between any two components held by a composite component, similar to `connect_param!` described in the Model section below. + +As mentioned above, conflict resolution refers to cases where two subcomponents have identically named parameters, and thus the user needs to explicitly demonstrate that they are aware of this and create a new external parameter that will point to all subcomponent parameters with that name. For example, given leaf components `A` and `B`: + +```julia +@defcomp Leaf1 begin + p1 = Parameter() + v1 = Variable(index=[time]) +end + +@defcomp Leaf2 begin + p1 = Parameter() +end +``` +The following will fail because you need to resolve the namespace collision of the `p1`'s: +```julia +@defcomposite MyCompositeComponent begin + Component(Leaf1) + Component(Leaf2) +end +``` +Fix it with a call to `Parameter` as follows: +```julia +@defcomposite MyCompositeComponent begin + Component(Leaf1) + Component(Leaf2) + + p1 = Parameter(Leaf1.p1, Leaf2.p1) +end +``` + ## Constructing a Model +Continuing the analogy of a tree data structure, one may consider the Model to be the root, orchestrating the running of all components it contains. + 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 @@ -84,6 +174,11 @@ set_param!(m, :ComponentName, :ParameterName2, rand(351, 3)) # a two-dimensional To make an internal connection, the syntax is as follows. +```julia +connect_param!(m, :TargetComponent, :ParameterName, :SourceComponent, :VariableName) +connect_param!(m, :TargetComponent, :ParameterName, :SourceComponent, :VariableName) +``` +or ```julia connect_param!(m, :TargetComponent=>:ParameterName, :SourceComponent=>:VariableName) connect_param!(m, :TargetComponent=>:ParameterName, :SourceComponent=>:VariableName) @@ -104,3 +199,107 @@ After all components have been added to your model and all parameters have been ```julia run(m) ``` + +## Long Example + +As a final, lengthier example, below we use the syntax in this tutorial to create and run a toy model with the following structure: + + top + / \ + A B + / \ / \ + 1 2 3 4 + +```julia +@defcomp Comp1 begin + par_1_1 = Parameter(index=[time]) # external input + var_1_1 = Variable(index=[time]) # computed + foo = Parameter() + function run_timestep(p, v, d, t) + v.var_1_1[t] = p.par_1_1[t] + end +end + +@defcomp Comp2 begin + par_2_1 = Parameter(index=[time]) # connected to Comp1.var_1_1 + par_2_2 = Parameter(index=[time]) # external input + var_2_1 = Variable(index=[time]) # computed + foo = Parameter() + function run_timestep(p, v, d, t) + v.var_2_1[t] = p.par_2_1[t] + p.foo * p.par_2_2[t] + end +end + +@defcomp Comp3 begin + par_3_1 = Parameter(index=[time]) # connected to Comp2.var_2_1 + var_3_1 = Variable(index=[time]) # external output + foo = Parameter(default=30) + + function run_timestep(p, v, d, t) + # @info "Comp3 run_timestep" + v.var_3_1[t] = p.par_3_1[t] * 2 + end +end + +@defcomp Comp4 begin + par_4_1 = Parameter(index=[time]) # connected to Comp2.var_2_1 + var_4_1 = Variable(index=[time]) # external output + foo = Parameter(default=300) + + function run_timestep(p, v, d, t) + # @info "Comp4 run_timestep" + v.var_4_1[t] = p.par_4_1[t] * 2 + end +end + +@defcomposite A begin + Component(Comp1) + Component(Comp2) + + foo1 = Parameter(Comp1.foo) + foo2 = Parameter(Comp2.foo) + + var_2_1 = Variable(Comp2.var_2_1) + + connect(Comp2.par_2_1, Comp1.var_1_1) + connect(Comp2.par_2_2, Comp1.var_1_1) +end + +@defcomposite B begin + Component(Comp3) + Component(Comp4) + + foo3 = Parameter(Comp3.foo) + foo4 = Parameter(Comp4.foo) + + var_3_1 = Variable(Comp3.var_3_1) +end + +@defcomposite top begin + Component(A) + + fooA1 = Parameter(A.foo1) + fooA2 = Parameter(A.foo2) + + # TBD: component B isn't getting added to mi + Component(B) + foo3 = Parameter(B.foo3) + foo4 = Parameter(B.foo4) + + var_3_1 = Variable(B.var_3_1) + + connect(B.par_3_1, A.var_2_1) + connect(B.par_4_1, B.var_3_1) +end + +m = Model() +set_dimension!(m, :time, 2005:2020) +add_comp!(m, top, nameof(top)) +set_param!(m, :fooA1, 1) +set_param!(m, :fooA2, 2) +set_param!(m, :foo3, 10) +set_param!(m, :foo4, 20) +set_param!(m, :par_1_1, collect(1:length(2005:2020))) +run(m) +``` +Take a look at what you've created now using `explore(m)`, a peek into what you can learn in How To Guide 2! diff --git a/docs/src/howto/howto_2.md b/docs/src/howto/howto_2.md index 1f2738be8..2174b42e4 100644 --- a/docs/src/howto/howto_2.md +++ b/docs/src/howto/howto_2.md @@ -4,7 +4,7 @@ This guide show show to access the numerical values of your results in a usable ## Accessing Results -After a model has been run, you can access the results (the calculated variable values in each component) in a few different ways. +After a model has been run, you can access the results (the calculated variable values in each component) in a few different ways. Note that if you have used composite components and wish to access results deeper than the the parameters and variables available in your top-level components you may need the special syntax in the Composite Component Details subsection below. You can use the `getindex` syntax as follows: @@ -24,6 +24,10 @@ getdataframe(m, :ComponentName=>(:Variable1, :Variable2)) # request multiple var getdataframe(m, :Component1=>:Var1, :Component2=>:Var2) # request variables from different components ``` +### Composite Component Details + +[TODO] + ## Plotting and the Explorer UI Mimi provides support for plotting using [VegaLite](https://github.com/vega/vega-lite) and [VegaLite.jl](https://github.com/fredo-dedup/VegaLite.jl). diff --git a/docs/src/howto/howto_3.md b/docs/src/howto/howto_3.md index 3a7daa7fe..52bf3b4c9 100644 --- a/docs/src/howto/howto_3.md +++ b/docs/src/howto/howto_3.md @@ -10,7 +10,7 @@ Running Monte Carlo simulations, and proximal sensitivity analysis, in Mimi can 2. The `run` function, which runs a simulation instance, setting the model(s) on which a simulation definition can be run with `set_models!`, generates all trial data with `generate_trials!`, and has several with optional parameters and optional callback functions to customize simulation behavior. -3. The `analyze` function, which takes a simulation instance, analyzes the results and returns results specific to the type of simulation passed in. Currently this function is only defined for the `SobolSimulationInstance` subtype of `SimulationInstance` +3. The `analyze` function, which takes a simulation instance, analyzes the results and returns results specific to the type of simulation passed in. The rest of this document will be organized as follows: @@ -27,11 +27,12 @@ The rest of this document will be organized as follows: The first step in a Mimi sensitivity analysis is using the `@defsim` macro to define and return a `SimulationDef{T}`. This simulation definition contains all the definition information in a form that can be applied at run-time. The `T` in `SimulationDef{T}` is any type that your application would like to live inside the `SimulationDef` struct, and most importantly specifies the sampling strategy to be used in your sensitivity analysis. -We have implemented three types for `T <: AbstractSimulationData`: +We have implemented four types for `T <: AbstractSimulationData`: 1. Simple random-sampling Monte Carlo Simulation (`MCSData`), 2. Latin Hypercube Sampling (`LHSData`) 3. Sobol sampling and analysis (`SobolData`) +4. Delta sampling and analysis (`DeltaData`) - **Beta**, we don't recommend use yet We also define type constants with friendlier names for these parameterized types: @@ -44,6 +45,9 @@ const LatinHypercubeSimulationInstance = SimulationInstance{LHSData} const SobolSimulationDef = SimulationDef{SobolData} const SobolSimulationInstance = SimulationInstance{SobolData} + +const DeltaSimulationDef = SimulationDef{DeltaData} +const DeltaSimulationInstance = SimulationInstance{DeltaData} ``` In order to build the information required at run-time, the `@defsim` macro carries out several tasks including the following. @@ -153,6 +157,7 @@ As previously mentioned and included in the tutorial, the `@defsim` macro uses t *Latin Hypercube sampling divides the distribution into equally-spaced quantiles, obtains values at those quantiles, and then shuffles the values. The result is better representation of the tails of the distribution with fewer samples than would be required for purely random sampling.* 3. Sobol sampling and analysis (`SobolData`) +4. Delta samping and analysis (`DeltaData`) - **Beta**, we don't recommend use yet ### Include Sampling Strategy-specifc Parameters @@ -294,7 +299,9 @@ By default, all defined models are run. In some cases, you may want to run some ## 3. The `analyze` function -[TODO] +The `analyze` function takes a simulation instance, runs a sensitivity analysis method as determined by the type of simulation instance, and returns the results. It is currenlty defined for a `SobolSimulationInstance` and the `DeltaSimulationInstance` (**Beta**) subtypes of `SimulationInstance`. + +This function wraps the `analyze` function in the [GlobalSensitivityAnalysis.jl](https://github.com/lrennels/GlobalSensitivityAnalysis.jl) package, so please view the README of this package for the most up to date information. ## 4. Plotting and the Explorer UI diff --git a/docs/src/index.md b/docs/src/index.md index a889d4655..5f322c6e5 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -21,16 +21,23 @@ Finally, when in doubt, ask your question on the [Mimi Framework forum](https:// ## Models using Mimi -* [MimiFUND.jl](https://github.com/fund-model/MimiFUND.jl) (currently in beta) -* [MimiDICE2010.jl](https://github.com/anthofflab/MimiDICE2010.jl) -* [MimiDICE2013.jl](https://github.com/anthofflab/MimiDICE2013.jl) -* [MimiRICE2010.jl](https://github.com/anthofflab/MimiRICE2010.jl) -* [Mimi-SNEASY.jl](https://github.com/anthofflab/mimi-sneasy.jl) (currently in closed beta) -* [Mimi-FAIR.jl](https://github.com/anthofflab/mimi-fair.jl) (currently in closed beta) -* [MimiPAGE2009.jl](https://github.com/anthofflab/MimiPAGE2009.jl) (currently in closed beta) -* [Mimi-MAGICC.jl](https://github.com/anthofflab/mimi-magicc.jl) (CH4 parts currently in closed beta) -* [Mimi-HECTOR.jl](https://github.com/anthofflab/mimi-hector.jl) (CH4 parts currently in closed beta) -* [Mimi-CIAM.jl](https://github.com/anthofflab/mimi-ciam.jl) (currently in closed beta) -* [Mimi-BRICK.jl](https://github.com/anthofflab/mimi-brick.jl) (currently in closed beta) +*an asterisk after a model name indicates that this model is registered in the [MimiRegistry](https://github.com/mimiframework/Mimi.jl) as described in Tutorial 1* + +* [MimiFUND.jl](https://github.com/fund-model/MimiFUND.jl)* +* [MimiDICE2010.jl](https://github.com/anthofflab/MimiDICE2010.jl)* +* [MimiDICE2013.jl](https://github.com/anthofflab/MimiDICE2013.jl)* +* [MimiDICE2016.jl](https://github.com/AlexandrePavlov/MimiDICE2016.jl)* +* [MimiRICE2010.jl](https://github.com/anthofflab/MimiRICE2010.jl)* +* [Mimi-SNEASY.jl](https://github.com/anthofflab/mimi-sneasy.jl)* +* [Mimi-FAIR.jl](https://github.com/anthofflab/mimi-fair.jl/)* +* [MimiPAGE2009.jl](https://github.com/anthofflab/MimiPAGE2009.jl/)* +* [Mimi-MAGICC.jl](https://github.com/anthofflab/mimi-magicc.jl)* +* [Mimi-HECTOR.jl](https://github.com/anthofflab/mimi-hector.jl)* +* [Mimi-CIAM.jl](https://github.com/anthofflab/mimi-ciam.jl) (currently in closed BETA) +* [Mimi-BRICK.jl](https://github.com/anthofflab/mimi-brick.jl) (currently in closed BETA) +* [mimi_NICE](https://github.com/fdennig/mimi_NICE) * [AWASH](http://awashmodel.org/) * [PAGE-ICE](https://github.com/openmodels/PAGE-ICE) +* [RICE+AIR](https://github.com/Environment-Research/AIR) +* [Moore-Ag.jl](https://github.com/ckingdon95/MooreAg.jl)* +* [MimiIWG.jl](https://github.com/rffscghg/MimiIWG.jl)* diff --git a/docs/src/ref/ref_composites.md b/docs/src/ref/ref_composites.md new file mode 100644 index 000000000..5da2bbf14 --- /dev/null +++ b/docs/src/ref/ref_composites.md @@ -0,0 +1,9 @@ +# Reference Guide: Composite Components + +Prior versions of Mimi supported only "flat" models, i.e., with one level of components. The current version supports mulitple layers of components, with some components being "final" or leaf components, and others being "composite" components which themselves contain other leaf or composite components. This approach allows for a cleaner organization of complex models, and allows the construction of building blocks that can be re-used in multiple models. + +To the degree possible, composite components are designed to operate the same as leaf components, though there are necessarily differences: + +1. Leaf components are defined using the macro `@defcomp`, while composites are defined using `@defcomposite`. Each macro supports syntax and semantics specific to the type of component. + +2. Leaf components support user-defined `run_timestep()` functions, whereas composites have a built-in `run_timestep()` function that iterates over its subcomponents and calls their `run_timestep()` function. The `init()` function is handled analogously. diff --git a/docs/src/ref/ref_main.md b/docs/src/ref/ref_main.md index 9ea91852c..3f010c1bc 100644 --- a/docs/src/ref/ref_main.md +++ b/docs/src/ref/ref_main.md @@ -9,11 +9,12 @@ If you find a bug in these reference guides, or have a clarifying question or su - [Reference Guide: The Mimi API](@ref) provides a guide to the public API for Mimi, including macros, types, and functions along with their signatures and descriptions. -- [Reference Guide: Structures](@ref) describes the core data structures used to implement in Mimi 1.0. +- [Reference Guide: Structures - Classes.jl and Core Types](@ref) describes the use of Classes.jl in Mimi as well as some of the core Types used to implement Mimi 1.0. -- [Reference Guide: Structures - Definitions](@ref) describes the core _definition_ data structures used to implement in Mimi 1.0. +- [Reference Guide: Structures - Definitions](@ref) describes the core _definition_ data structures used to implement Mimi 1.0. -- [Reference Guide: Structures - Instances](@ref) describes the core _instance_ data structures used to implement in Mimi 1.0. - +- [Reference Guide: Structures - Instances](@ref) describes the core _instance_ data structures used to implement Mimi 1.0. + +- [Reference Guide: Composite Components](@ref) describes the introduction of composite components in Mimi 1.0. diff --git a/docs/src/ref/ref_structures.md b/docs/src/ref/ref_structures_classes_types.md similarity index 62% rename from docs/src/ref/ref_structures.md rename to docs/src/ref/ref_structures_classes_types.md index 1fb7eac04..323e0587f 100644 --- a/docs/src/ref/ref_structures.md +++ b/docs/src/ref/ref_structures_classes_types.md @@ -1,15 +1,4 @@ - -# Reference Guide: Structures - -This document (along with "structures_2_definitions" and "structures_3_instances") describes the core data structures used to implement in Mimi 1.0. - -Prior versions of Mimi supported only "flat" models, i.e., with one level of components. The current version supports mulitple layers of components, with some components being "final" or leaf components, and others being "composite" components which themselves contain other leaf or composite components. This approach allows for a cleaner organization of complex models, and allows the construction of building blocks that can be re-used in multiple models. - -To the degree possible, composite components are designed to operate the same as leaf components, though there are necessarily differences: - -1. Leaf components are defined using the macro `@defcomp`, while composites are defined using `@defcomposite`. Each macro supports syntax and semantics specific to the type of component. See below for more details on these macros. - -1. Leaf composites support user-defined `run_timestep()` functions, whereas composites have a built-in `run_timestep()` function that iterates over its subcomponents and calls their `run_timestep()` function. The `init()` function is handled analogously. +# Reference Guide: Structures - Classes.jl and Core Types ## Classes.jl @@ -21,11 +10,23 @@ Most of the core data structures are defined using the `Classes.jl` package, whi For example, in Mimi, `ModelDef` is a subclass of `CompositeComponentDef`, which in turn is a subclass of `ComponentDef`. Thus, methods can be written with arguments typed `x::ComponentDef` to operate on leaf components only, or `x::AbstractCompositeComponentDef` to operate on composites and `ModelDef`, or as `x::AbstractComponentDef` to operate on all three concrete types. -## Core types +## User-facing Classes + +1. `Model`: The `Model` class contains the `ModelDef`, and after the `build()` function is called, a `ModelInstance` that can be run. The API for `Model` delegates many calls to either its top-level `ModeDef` or `ModelInstance`, while providing additional functionality including running a Monte Carlo simulation. + +2. `ComponentReference` + +[TODO] + +3. `VariableReference` + +[TODO] + +## Core Types Several core types are defined in `types/core.jl`, including the two primary abstract types, `MimiStruct` and `MimiClass`. -All structs and classes in Mimi are derived from these abstract types, which allows us to identify Mimi-defined items when writing `show()` methods. Important structs and classes include: +All structs and classes in Mimi are derived from these abstract types, which allows us to identify Mimi-defined items when writing `show()` methods. Some of the important structs and classes include: 1. `ComponentId` diff --git a/docs/src/ref/ref_structures_instances.md b/docs/src/ref/ref_structures_instances.md index b02833e44..32cc5e64b 100644 --- a/docs/src/ref/ref_structures_instances.md +++ b/docs/src/ref/ref_structures_instances.md @@ -9,18 +9,21 @@ comp_id::ComponentID comp_path::ComponentPath (from top (model) down) first::Int last::Int - +``` +``` # LeafComponentInstance <: ComponentInstance variables::ComponentInstanceVariables parameters::ComponentInstanceParameters init::Union{Nothing, Function} run_timestep::Union{Nothing, Function} - +``` +``` # CompositeComponentInstance <: ComponentInstance comps_dict::OrderedDict{Symbol, ComponentInstance} parameters::NamedTuple variables::NamedTuple - +``` +``` # ModelInstance <: CompositeComponentInstance md::ModelDef ``` @@ -31,17 +34,10 @@ md::ModelDef # ComponentInstanceParameters (only exist in leaf component instances) nt::NamedTuple{Tuple{Symbol}, Tuple{Type}} # Type is either ScalarModelParameter (for scalar parameters) or TimestepArray (for array parameters) comp_paths::Vector{ComponentPath} - +``` +Note: In the `ComponentInstanceParameters`, the values stored in the named tuple point to the actual variable arrays in the other components for things that are internally connected, or to the actual value stored in the mi.md.external_params dictionary if it's an external parameter. +``` # ComponentInstanceVariables (only exist in leaf component instances) nt::NamedTuple{Tuple{Symbol}, Tuple{Type}} # Type is either ScalarModelParameter (for scalar variables) or TimestepArray (for array variables) comp_paths::Vector{ComponentPath} -``` -Note: in the `ComponentInstanceParameters`, the values stored in the named tuple point to the actual variable arrays in the other components for things that are internally connected, or to the actual value stored in the mi.md.external_params dictionary if it's an external parameter. (So I'm not sure what the component paths are there for, because the component path seems to always reference the current component, even if the parameter data tehcnically originates from a different component.) - -## User-facing Classes - -1. `Model`: The `Model` class contains the `ModelDef`, and after the `build()` function is called, a `ModelInstance` that can be run. The API for `Model` delegates many calls to either its top-level `ModeDef` or `ModelInstance`, while providing additional functionality including running a Monte Carlo simulation. - -2. `ComponentReference` - -3. `VariableReference` +``` \ No newline at end of file diff --git a/docs/src/tutorials/tutorial_6.md b/docs/src/tutorials/tutorial_6.md new file mode 100644 index 000000000..04a68a002 --- /dev/null +++ b/docs/src/tutorials/tutorial_6.md @@ -0,0 +1,10 @@ +# Tutorial 6: Create a Model Including Composite Components + +This tutorial walks through the steps to create a new model that uses composite components, a new feature of Mimi v1.0.0. + +Working through the following tutorial will require: + +- [Julia v1.4.0](https://julialang.org/downloads/) or higher +- [Mimi v0.10.0](https://github.com/mimiframework/Mimi.jl) or higher + +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_main.md b/docs/src/tutorials/tutorial_main.md index 346da36db..7c523df77 100644 --- a/docs/src/tutorials/tutorial_main.md +++ b/docs/src/tutorials/tutorial_main.md @@ -21,4 +21,24 @@ If you find a bug in these tutorials, or have a clarifying question or suggestio [Tutorial 5: Monte Carlo Simulations and Sensitivity Analysis Support](@ref) explores Mimi's Monte Carlo simulation and 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._ +[Tutorial 6: Create a Model Including Composite Components](@ref) expands on Tutorial 4 and explains how to create a model from scratch including the use of composite components. + +## Additional Tutorals + +#### 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. + +#### Resources for the Future (RFF) Webinar + +On February 10, 2021, Resources for the Future (RFF) held a [live webinar](https://www.rff.org/events/rff-live/the-social-cost-of-carbon-key-scientific-and-policy-considerations-for-the-biden-administration/) for over 1,000 participants described on rff.org as follows: + +"Over the past four years, the [Social Cost of Carbon Initiative](https://www.rff.org/topics/scc/) at Resources for the Future (RFF) has been a key hub for SCC scholarship to implement the NAS recommendations. On February 10, 2021, RFF held a live webinar that highlighted the latest SCC-related research from RFF scholars and the [Climate Impact Lab](http://www.impactlab.org). The conversation also featured perspectives from decisionmakers using the SCC to inform policy and highlighted key considerations for the Biden administration’s near-term and final updates of the estimates." + +This webinar highlighted Mimi as a "free, open-source computing platform allows users to access, run, and modify the social cost of carbon (SCC) models used by the federal Interagency Working Group to estimate the SCC", **and was paired with the [Social Cost of Carbon Computing Platform: Models from the Interagency Working Group](https://www.rff.org/publications/data-tools/social-cost-of-carbon-computing-platform-models-from-the-iwg/) post including an [embedded video](https://www.youtube.com/watch?v=C2rqpHk3Rek&feature=emb_logo) by Professor Anthoff.** + +Links: + +[RFF Mimi Post (with link to Mimi Demo )](https://www.rff.org/publications/data-tools/social-cost-of-carbon-computing-platform-models-from-the-iwg/) + +[Direct YouTube Link to Mimi Demo](https://www.youtube.com/watch?v=C2rqpHk3Rek&feature=emb_logo) \ No newline at end of file