Skip to content

Running MIMOSA

Base run

A basic run of MIMOSA requires 4 steps: loading the parameters, building the model instance, solving the model and finally saving the output. With this code, the default parameter values are used (see Parameter reference).

from mimosa import MIMOSA, load_params

params = load_params()  # (1)!

model1 = MIMOSA(params)  # (2)!
model1.solve()  # (3)!

model1.save("run1")  # (4)!
  1. Read the default parameters
  2. Build the model using the parameters
  3. Once the model is built, send the model to the solver.
    Note that if you use the NEOS solver, use the syntax model1.solve(use_neos=True, neos_email="your.email@email.com")
  4. Export the output to the file output/run1.csv

ACCREU cost-benefit analysis

Doing an ACCREU run.

ACCREU adaptation expenditure is a solver control by default, and solve() therefore optimises mitigation and adaptation jointly. To use the ordered cost-benefit workflow, select analytical adaptation and the sequential strategy. One call to solve() then first optimises mitigation without adaptation and evaluates analytical optimal adaptation along the resulting pathway. The final values are loaded into the public model, so they can be saved normally:

from mimosa import MIMOSA, load_params

params = load_params()
params["model structure"]["damage module"] = "ACCREU"
options = params["economics"]["damages"]["accreu"]
options["adaptation"] = "sectoral"
options["adaptation_determination"] = "analytical_optimum"
options["cba_strategy"] = "mitigation_then_adaptation"

model = MIMOSA(params)
model.solve()
model.save("run_accreu_cba")

For an adaptation-only scenario, select analytical_optimum and call run_simulation() without controls. run_nopolicy_baseline() always disables both mitigation and adaptation so avoided damages have a consistent reference. The sequential strategy rejects a fixed carbon budget. Transferred pathways remain available as model.workflow_control_values for diagnostics.

The joint strategy also supports analytical_optimum. In that combination, MIMOSA performs one ordinary optimisation: the solver chooses mitigation while adaptation responds through its analytical optimum equations. This differs from mitigation_then_adaptation, which first chooses mitigation in a model without adaptation.

Configuring the time grid

The time.dt parameter sets the initial timestep length, while time.periods optionally maps change years to the new timestep length used after that year. The default grid uses five-year timesteps through 2050 and ten-year timesteps thereafter:

params = load_params()
params["time"]["start"] = 2025
params["time"]["end"] = 2150
params["time"]["dt"] = 5
params["time"]["periods"] = {2050: 10}

Additional changes can be added to the mapping. For example, with end = 2290, {2050: 10, 2150: 20} uses five-year timesteps through 2050, ten-year timesteps through 2150, and twenty-year timesteps thereafter. Every change year and the final year must lie on the resulting grid. Within model equations, m.period_length[t] gives the number of years between timestep t - 1 and t; it is zero for the initial timestep.

Reading the output

Once the script above has finished running, it has produced two output files in the folder output: run1.csv and run1.csv.params.json. The latter is a JSON file with all the input parameters used for this particular run (for reproducibility), together with the MIMOSA version, scenario type and runtime in seconds. For optimisation output, the runtime measures the complete model.solve() call and excludes model creation and prerunning. For simulation output, it measures the model.run_simulation() call that produced the saved result. The CSV file contains all the output data. Every variable in MIMOSA is saved in this file in a format similar to IAMC data format:

output/run1.csv

Variable Region Unit 2020 2025 2030 2035 2040 2045 2050 2055 2060 2065 2070 2075 2080 2085 2090 2095 2100 2105 2110 2115 2120 2125 2130 2135 2140 2145 2150
regional_emissions CAN GtCO2/yr 0.511577 0.383683 0.255789 0.155544 0.136527 0.113384 0.0944834 0.0845257 0.077836 0.0694752 0.0588413 0.0469933 0.0359533 0.0269266 0.0199594 0.014565 0.0104499 0.0517489 0.0517486 0.0517485 0.0517484 0.0517483 0.0517482 0.0517481 0.051748 0.0517478 0.0517476
regional_emissions USA GtCO2/yr 5.39382 4.04537 2.69691 1.34846 0.789513 0.649695 0.531854 0.430432 0.341586 0.262853 0.195861 0.142273 0.101621 0.072636 0.0549502 0.0495887 0.0582421 0.534749 0.534749 0.534749 0.534749 0.534749 0.534749 0.534749 0.534749 0.534748 0.534748
regional_emissions MEX GtCO2/yr 0.572878 0.429658 0.286439 0.250682 0.235195 0.210891 0.184067 0.159748 0.137097 0.114491 0.0904155 0.0650686 0.0402638 0.0171455 -0.00403092 -0.0236268 -0.0413935 6.53385e-05 6.49712e-05 6.47857e-05 6.46547e-05 6.45457e-05 6.4444e-05 6.4339e-05 6.42181e-05 6.40555e-05 6.37559e-05
... ...

These output files can be easily imported for plotting software (like using Plotly in Python). An easier way, however, to quickly visualise and compare MIMOSA outputs, is by using the MIMOSA Dashboard. After opening the online Dashboard, simply drag and drop all output files to the drag-and-drop input to visualise one or multiple MIMOSA output files. Also include the parameter files to directly see the difference in input parameters.

Open the MIMOSA Dashboard

Derived global variables

Add derived regional and missing global series to the exported results.

Indirect costs are attributed to damage, mitigation, and adaptation using their shares of cumulative direct costs. Only costs before the current time step are included, and annual cost flows are weighted by the length of the interval over which they affect capital accumulation. Global series are the baseline-GDP-weighted aggregations of the regional attributed costs. All attributed series are zero in the initial period or when cumulative direct costs are zero. Damage and adaptation shares are zero when damages are ignored; a missing adaptation-cost series is also treated as zero.

Some variables are defined only by time and region because their global counterparts are not needed while solving the model. To keep selected variables available at the global level without adding equations to the optimisation problem, MIMOSA derives the corresponding series while exporting the results.

A variable can be aggregated when it:

  • is a Pyomo variable indexed by time and region;
  • does not already have a global_<variable name> counterpart.

Regional population quantities, such as variables measured in billion people, are summed directly:

\[ \text{global population quantity}_t = \sum_r \text{population quantity}_{t,r}. \]

Regional cost variables are aggregated when they have fraction_of_GDP as their unit and contain costs in their name.

If an exported <variable name>_abs quantity exists, its regional values are used as the numerator:

\[ \text{global costs}_t = \frac{\sum_r \text{absolute costs}_{t,r}} {\href{./#var__global_GDP_gross}{\text{global GDP gross}_t}}. \]

Otherwise, absolute regional costs are reconstructed from the GDP-relative values:

\[ \text{global costs}_t = \frac{\sum_r \left(\text{costs}_{t,r} \cdot \href{./#var__GDP_gross}{\text{GDP gross}_{t,r}}\right)} {\href{./#var__global_GDP_gross}{\text{global GDP gross}_t}}. \]

Regional adaptation effectiveness variables measured as fraction_of_gross_damages are weighted by the corresponding sector's absolute gross damages. The corresponding gross-damage variable is inferred from the name: <sector>_adaptation_level uses <sector>_damage_costs_gross. If global gross damages are zero, the exported avoided fraction is NaN.

The resulting global_* rows are added only to the exported CSV file. They are not added as Pyomo components and therefore cannot be accessed as attributes of the model. Global variables that already exist in the model are exported normally and are not replaced by this calculation.

Source code in mimosa/export/save.py
def add_derived_global_rows(rows, m, all_variables):
    r"""
    Add derived regional and missing global series to the exported results.

    Indirect costs are attributed to damage, mitigation, and adaptation using
    their shares of cumulative direct costs. Only costs before the current time
    step are included, and annual cost flows are weighted by the length of the
    interval over which they affect capital accumulation. Global series are the
    baseline-GDP-weighted aggregations of the regional attributed costs. All
    attributed series are zero in the initial period or when cumulative direct
    costs are zero. Damage and adaptation shares are zero when damages are
    ignored; a missing adaptation-cost series is also treated as zero.

    Some variables are defined only by time and region because their global
    counterparts are not needed while solving the model. To keep selected
    variables available at the global level without adding equations to the
    optimisation problem, MIMOSA derives the corresponding series while exporting
    the results.

    A variable can be aggregated when it:

    - is a Pyomo variable indexed by time and region;
    - does not already have a `global_<variable name>` counterpart.

    Regional population quantities, such as variables measured in `billion
    people`, are summed directly:

    $$
    \text{global population quantity}_t =
    \sum_r \text{population quantity}_{t,r}.
    $$

    Regional cost variables are aggregated when they have `fraction_of_GDP` as
    their unit and contain `costs` in their name.

    If an exported `<variable name>_abs` quantity exists, its regional values are
    used as the numerator:

    $$
    \text{global costs}_t =
    \frac{\sum_r \text{absolute costs}_{t,r}}
    {\href{./#var__global_GDP_gross}{\text{global GDP gross}_t}}.
    $$

    Otherwise, absolute regional costs are reconstructed from the GDP-relative
    values:

    $$
    \text{global costs}_t =
    \frac{\sum_r \left(\text{costs}_{t,r}
    \cdot \href{./#var__GDP_gross}{\text{GDP gross}_{t,r}}\right)}
    {\href{./#var__global_GDP_gross}{\text{global GDP gross}_t}}.
    $$

    Regional adaptation effectiveness variables measured as
    `fraction_of_gross_damages` are weighted by the corresponding sector's
    absolute gross damages. The corresponding gross-damage variable is inferred
    from the name: `<sector>_adaptation_level` uses
    `<sector>_damage_costs_gross`. If global gross damages are zero, the exported
    avoided fraction is `NaN`.

    The resulting `global_*` rows are added only to the exported CSV file. They
    are not added as Pyomo components and therefore cannot be accessed as
    attributes of the model. Global variables that already exist in the model are
    exported normally and are not replaced by this calculation.
    """
    variables_by_name = {useful_var.name: useful_var for useful_var in all_variables}
    existing_names = set(variables_by_name)

    add_indirect_cost_rows(rows, m, variables_by_name)

    people_dimensionality = quant.unit("people", pyomo=False).dimensionality

    for useful_var in all_variables:
        source_var = getattr(useful_var.var, "_var", useful_var.var)
        global_name = f"global_{useful_var.name}"

        if (
            getattr(source_var, "ctype", None) is not Var
            or useful_var.indices != ["t", "regions"]
            or global_name in existing_names
        ):
            continue

        unit_str = str(useful_var.unit) if useful_var.unit is not None else ""
        unit_dimensionality = (
            quant.unit(unit_str, pyomo=False).dimensionality if unit_str else None
        )

        if unit_dimensionality == people_dimensionality:
            global_values = [
                sum(value(useful_var.var[t, r]) for r in m.regions) for t in m.t
            ]
        elif unit_str == "fraction_of_GDP" and "costs" in useful_var.name:
            absolute_costs = variables_by_name.get(f"{useful_var.name}_abs")
            global_values = []
            for t in m.t:
                if absolute_costs is not None:
                    numerator = sum(value(absolute_costs.var[t, r]) for r in m.regions)
                else:
                    numerator = sum(
                        value(useful_var.var[t, r]) * value(m.GDP_gross[t, r])
                        for r in m.regions
                    )
                global_values.append(numerator / value(m.global_GDP_gross[t]))
        elif unit_str == "fraction_of_gross_damages":
            adapt_level_suffix = "_adaptation_level"
            if not useful_var.name.endswith(adapt_level_suffix):
                continue

            sector_name = useful_var.name[: -len(adapt_level_suffix)]
            gross_damages = variables_by_name.get(f"{sector_name}_damage_costs_gross")
            if gross_damages is None:
                continue

            global_values = []
            for t in m.t:
                gross_damages_abs = {
                    r: value(gross_damages.var[t, r]) * value(m.GDP_gross[t, r])
                    for r in m.regions
                }
                denominator = sum(gross_damages_abs.values())
                numerator = sum(
                    value(useful_var.var[t, r]) * gross_damages_abs[r]
                    for r in m.regions
                )
                global_values.append(
                    np.nan if np.isclose(denominator, 0.0) else numerator / denominator
                )
        else:
            continue

        rows.append([global_name, "Global", useful_var.unit, *global_values])