예제 #1
0
def test_price_duality(test_mp):
    years = [2020, 2025, 2030, 2040, 2050]
    for c in [0.25, 0.5, 0.75]:
        # set up a scenario for cumulative constraints
        scen = Scenario(test_mp, MODEL, 'cum_many_tecs', version='new')
        model_setup(scen, years, simple_tecs=False)
        scen.add_cat('year', 'cumulative', years)
        scen.add_par('bound_emission', ['World', 'ghg', 'all', 'cumulative'],
                     0.5, 'tCO2')
        scen.commit('initialize test scenario')
        scen.solve()

        # set up a new scenario with emissions taxes
        tax_scen = Scenario(test_mp, MODEL, 'tax_many_tecs', version='new')
        model_setup(tax_scen, years, simple_tecs=False)
        for y in years:
            tax_scen.add_cat('year', y, y)

        # use emission prices from cumulative-constraint scenario as taxes
        taxes = scen.var('PRICE_EMISSION')\
            .rename(columns={'year': 'type_year', 'lvl': 'value'})
        taxes['unit'] = 'USD/tCO2'
        tax_scen.add_par('tax_emission', taxes)
        tax_scen.commit('initialize test scenario for taxes')
        tax_scen.solve()

        # check that emissions are close between cumulative and tax scenario
        filters = {'node': 'World'}
        emiss = scen.var('EMISS', filters).set_index('year').lvl
        emiss_tax = tax_scen.var('EMISS', filters).set_index('year').lvl
        npt.assert_allclose(emiss, emiss_tax, rtol=0.20)
예제 #2
0
def test_price_duality(test_mp):
    years = [2020, 2025, 2030, 2040, 2050]
    for c in [0.25, 0.5, 0.75]:
        # set up a scenario for cumulative constraints
        scen = Scenario(test_mp, MODEL, "cum_many_tecs", version="new")
        model_setup(scen, years, simple_tecs=False)
        scen.add_cat("year", "cumulative", years)
        scen.add_par("bound_emission", ["World", "ghg", "all", "cumulative"],
                     0.5, "tCO2")
        scen.commit("initialize test scenario")
        scen.solve()

        # set up a new scenario with emissions taxes
        tax_scen = Scenario(test_mp, MODEL, "tax_many_tecs", version="new")
        model_setup(tax_scen, years, simple_tecs=False)
        for y in years:
            tax_scen.add_cat("year", y, y)

        # use emission prices from cumulative-constraint scenario as taxes
        taxes = scen.var("PRICE_EMISSION").rename(columns={
            "year": "type_year",
            "lvl": "value"
        })
        taxes["unit"] = "USD/tCO2"
        tax_scen.add_par("tax_emission", taxes)
        tax_scen.commit("initialize test scenario for taxes")
        tax_scen.solve()

        # check that emissions are close between cumulative and tax scenario
        filters = {"node": "World"}
        emiss = scen.var("EMISS", filters).set_index("year").lvl
        emiss_tax = tax_scen.var("EMISS", filters).set_index("year").lvl
        npt.assert_allclose(emiss, emiss_tax, rtol=0.20)
예제 #3
0
def test_bound_emission_year(test_mp):
    scen = Scenario(test_mp, "test_bound_emission", "standard", version="new")
    model_setup(scen, [2020, 2030])
    scen.commit("initialize test model")
    add_bound_emission(scen, bound=1.250, year=2020)
    scen.solve(case="bound_emission_year")
    assert_function(scen, year=2020)
예제 #4
0
def test_add_bound_activity_up(test_mp):
    scen = Scenario(test_mp, *msg_args)
    scen.solve()

    # data for act bound
    exp = 0.5 * calculate_activity(scen).sum()
    data = pd.DataFrame({
        'node_loc': 'seattle',
        'technology': 'transport_from_seattle',
        'year_act': 2010,
        'time': 'year',
        'unit': 'cases',
        'mode': 'to_chicago',
        'value': exp,
    }, index=[0])

    # test limiting one mode
    clone = scen.clone('foo', 'bar', keep_solution=False)
    clone.check_out()
    clone.add_par('bound_activity_up', data)
    clone.commit('foo')
    clone.solve()
    obs = calculate_activity(clone).loc['to_chicago']
    assert np.isclose(obs, exp)

    orig_obj = scen.var('OBJ')['lvl']
    new_obj = clone.var('OBJ')['lvl']
    assert new_obj >= orig_obj
예제 #5
0
def test_add_bound_activity_up_all_modes(message_test_mp):
    scen = Scenario(message_test_mp, **SCENARIO['dantzig']).clone()
    scen.solve()

    # data for act bound
    exp = 0.95 * calculate_activity(scen).sum()
    data = pd.DataFrame(
        {
            'node_loc': 'seattle',
            'technology': 'transport_from_seattle',
            'year_act': _year,
            'time': 'year',
            'unit': 'cases',
            'mode': 'all',
            'value': exp,
        },
        index=[0])

    # test limiting all modes
    clone = scen.clone('foo', 'baz', keep_solution=False)
    clone.check_out()
    clone.add_par('bound_activity_up', data)
    clone.commit('foo')
    clone.solve()
    obs = calculate_activity(clone).sum()
    assert np.isclose(obs, exp)

    orig_obj = scen.var('OBJ')['lvl']
    new_obj = clone.var('OBJ')['lvl']
    assert new_obj >= orig_obj
예제 #6
0
def test_solve_modified(caplog, message_test_mp):
    base = Scenario(message_test_mp, **SCENARIO["dantzig"])

    # Base objective value
    base.solve()
    base_obj = base.var("OBJ")["lvl"]

    with solve_modified(base, "new scenario name") as scenario:
        # Scenario is not yet solved
        assert not scenario.has_solution()

        # Scenario has the indicated new name
        assert "new scenario name" == scenario.scenario

        # Change one demand parameter from 325 to 326
        scenario.add_par(
            "demand",
            make_df(
                "demand",
                node=["new-york"],
                commodity=["cases"],
                level="consumption",
                year=1963,
                time="year",
                value=326,
                unit="case",
            ),
        )

    # Scenario is solved at the end of the with: statement
    assert scenario.has_solution()

    assert scenario.var("OBJ")["lvl"] != base_obj
def test_bound_emission_5y(test_mp):
    scen = Scenario(test_mp, "test_bound_emission", "standard", version="new")
    model_setup(scen, [2020, 2025, 2030, 2040])
    scen.commit("initialize test model")
    add_bound_emission(scen, bound=1.250)
    scen.solve(case="bound_emission_5y", quiet=True)
    assert_function(scen, year="cumulative")
예제 #8
0
def test_years_active_extend3(test_mp):
    test_mp.add_unit("year")
    scen = Scenario(test_mp, **SCENARIO["dantzig"], version="new")
    scen.add_set("node", "foo")
    scen.add_set("technology", "bar")

    # Periods of uneven length
    years = [1990, 1995, 2000, 2005, 2010, 2020, 2030]

    scen.add_horizon(year=years, firstmodelyear=2010)

    scen.add_set("year", [1992])
    scen.add_par("duration_period", "1992", 2, "y")
    scen.add_par("duration_period", "1995", 3, "y")

    scen.add_par(
        "technical_lifetime",
        pd.DataFrame(
            dict(
                node_loc="foo",
                technology="bar",
                unit="year",
                value=[20],
                year_vtg=1990,
            ),
        ),
    )

    obs = scen.years_active("foo", "bar", 1990)

    assert obs == [1990, 1992, 1995, 2000, 2005]
def test_add_bound_activity_up_all_modes(message_test_mp):
    scen = Scenario(message_test_mp, **SCENARIO["dantzig"]).clone()
    scen.solve(quiet=True)

    # data for act bound
    exp = 0.95 * calculate_activity(scen).sum()
    data = pd.DataFrame(
        {
            "node_loc": "seattle",
            "technology": "transport_from_seattle",
            "year_act": _year,
            "time": "year",
            "unit": "cases",
            "mode": "all",
            "value": exp,
        },
        index=[0],
    )

    # test limiting all modes
    clone = scen.clone("foo", "baz", keep_solution=False)
    clone.check_out()
    clone.add_par("bound_activity_up", data)
    clone.commit("foo")
    clone.solve()
    obs = calculate_activity(clone).sum()
    assert np.isclose(obs, exp)

    orig_obj = scen.var("OBJ")["lvl"]
    new_obj = clone.var("OBJ")["lvl"]
    assert new_obj >= orig_obj
예제 #10
0
def test_new_timeseries_long_name64plus(message_test_mp):
    scen = Scenario(message_test_mp, **SCENARIO["dantzig multi-year"])
    scen = scen.clone(keep_solution=False)
    scen.check_out(timeseries_only=True)
    df = pd.DataFrame(
        {
            "region": [
                "India",
            ],
            "variable": [
                (
                    "Emissions|CO2|Energy|Demand|Transportation|Aviation|"
                    "Domestic|Freight|Oil"
                ),
            ],
            "unit": [
                "Mt CO2/yr",
            ],
            "2012": [
                0.257009,
            ],
        }
    )
    scen.add_timeseries(df)
    scen.commit("importing a testing timeseries")
예제 #11
0
def test_bound_emission_5y(test_mp):
    scen = Scenario(test_mp, 'test_bound_emission', 'standard', version='new')
    model_setup(scen, [2020, 2025, 2030, 2040])
    scen.commit('initialize test model')
    add_bound_emission(scen, bound=1.250)
    scen.solve(case='bound_emission_5y')
    assert_function(scen, year='cumulative')
예제 #12
0
def test_years_active(test_mp):
    test_mp.add_unit('year')
    scen = Scenario(test_mp, *msg_args, version='new')
    scen.add_set('node', 'foo')
    scen.add_set('technology', 'bar')

    # Periods of uneven length
    years = [1990, 1995, 2000, 2005, 2010, 2020, 2030]

    # First period length is immaterial
    duration = [1900, 5, 5, 5, 5, 10, 10]
    scen.add_horizon({'year': years, 'firstmodelyear': years[-1]})
    scen.add_par('duration_period',
                 pd.DataFrame(zip(years, duration), columns=['year', 'value']))

    # 'bar' built in period '1995' with 25-year lifetime:
    # - is constructed in 1991-01-01.
    # - by 1995-12-31, has operated 5 years.
    # - operates until 2015-12-31. This is within the period '2020'.
    scen.add_par('technical_lifetime', pd.DataFrame(dict(
        node_loc='foo',
        technology='bar',
        unit='year',
        value=25,
        year_vtg=years[1]), index=[0]))

    result = scen.years_active('foo', 'bar', years[1])

    # Correct return type
    assert isinstance(years, list)
    assert isinstance(years[0], int)

    # Years 1995 through 2020
    npt.assert_array_equal(result, years[1:-1])
예제 #13
0
def base_scen_mp(test_mp):
    scen = Scenario(test_mp, "model", "standard", version="new")

    data = {2020: 1, 2030: 2, 2040: 3}

    years = sorted(list(set(data.keys())))
    scen.add_set("node", "node")
    scen.add_set("commodity", "comm")
    scen.add_set("level", "level")
    scen.add_set("year", years)
    scen.add_set("technology", "tec")
    scen.add_set("mode", "mode")
    output_specs = ["node", "comm", "level", "year", "year"]

    for (yr, value) in data.items():
        scen.add_par("demand", ["node", "comm", "level", yr, "year"], 1, "GWa")
        scen.add_par("technical_lifetime", ["node", "tec", yr], 10, "y")
        tec_specs = ["node", "tec", yr, yr, "mode"]
        scen.add_par("output", tec_specs + output_specs, 1, "-")
        scen.add_par("var_cost", tec_specs + ["year"], value, "USD/GWa")

    scen.commit("initialize test model")
    scen.solve(case="original_years", quiet=True)

    yield scen, test_mp
예제 #14
0
def base_scen_mp(test_mp):
    scen = Scenario(test_mp, 'model', 'standard', version='new')

    data = {2020: 1, 2030: 2, 2040: 3}

    years = sorted(list(set(data.keys())))
    scen.add_set('node', 'node')
    scen.add_set('commodity', 'comm')
    scen.add_set('level', 'level')
    scen.add_set('year', years)
    scen.add_set('technology', 'tec')
    scen.add_set('mode', 'mode')
    output_specs = ['node', 'comm', 'level', 'year', 'year']

    for (yr, value) in data.items():
        scen.add_par('demand', ['node', 'comm', 'level', yr, 'year'], 1, 'GWa')
        scen.add_par('technical_lifetime', ['node', 'tec', yr], 10, 'y')
        tec_specs = ['node', 'tec', yr, yr, 'mode']
        scen.add_par('output', tec_specs + output_specs, 1, '-')
        scen.add_par('var_cost', tec_specs + ['year'], value, 'USD/GWa')

    scen.commit('initialize test model')
    scen.solve(case='original_years')

    yield scen, test_mp
예제 #15
0
def test_add_year_cli(message_ix_cli, base_scen_mp):
    scen_ref, test_mp = base_scen_mp

    # Information about the base Scenario
    platform_name = test_mp.name
    model = scen_ref.model
    scenario = scen_ref.scenario

    cmd = [
        "--platform",
        platform_name,
        "--model",
        model,
        "--scenario",
        scenario,
        "add-years",
        "--years_new",
        repr(YEARS_NEW),
        "--model_new",
        "add_year",
        "--scen_new",
        "standard",
    ]

    # Delete the objects so that the database connection is closed
    del test_mp, scen_ref

    r = message_ix_cli(*cmd)
    print(r.output, r.exception)
    assert r.exit_code == 0

    # Re-load the base Scenario
    mp = Platform(name=platform_name)
    scen_ref = Scenario(mp, model=model, scenario=scenario)

    # Load the created Scenario
    scen_new = Scenario(mp, model="add_year", scenario="standard")

    assert_function(scen_ref, scen_new, YEARS_NEW, yr_test=2025)

    # Same, except with --dry-run
    r = message_ix_cli(*cmd, "--dry-run")
    assert r.exit_code == 0

    # Bad usage: not giving the base scenario info
    r = message_ix_cli(*cmd[6:], "--dry-run")
    assert r.exit_code == 2
예제 #16
0
def adding_years(test_mp, scen_ref, years_new):
    scen_new = Scenario(test_mp,
                        model="add_year",
                        scenario="standard",
                        version="new",
                        annotation=" ")
    add_year(scen_ref, scen_new, years_new)
    return scen_new
def test_commodity_price(test_mp):
    scen = Scenario(test_mp, "test_commodity_price", "standard", version="new")
    model_setup(scen)
    scen.commit("initialize test model")
    scen.solve(case="price_commodity_standard")

    assert scen.var("OBJ")["lvl"] == 1
    assert scen.var("PRICE_COMMODITY")["lvl"][0] == 1
예제 #18
0
def test_solve_legacy_scenario(test_legacy_mp):
    scen = Scenario(test_legacy_mp, *msg_args)
    exp = scen.var('OBJ')['lvl']

    # solve scenario, assert that the new objective value is close to previous
    scen.remove_solution()
    scen.solve()
    assert np.isclose(exp, scen.var('OBJ')['lvl'])
예제 #19
0
def test_commodity_price(test_mp):
    scen = Scenario(test_mp, 'test_commodity_price', 'standard', version='new')
    model_setup(scen)
    scen.commit('initialize test model')
    scen.solve(case='price_commodity_standard')

    assert scen.var('OBJ')['lvl'] == 1
    assert scen.var('PRICE_COMMODITY')['lvl'][0] == 1
예제 #20
0
def adding_years(test_mp, scen_ref, years_new):
    scen_new = Scenario(test_mp,
                        model='add_year',
                        scenario='standard',
                        version='new',
                        annotation=' ')
    add_year(scen_ref, scen_new, years_new)
    return scen_new
예제 #21
0
def test_vintage_and_active_years(test_mp):
    scen = Scenario(test_mp, *msg_args, version='new')
    scen.add_horizon({'year': ['2000', '2010', '2020'],
                      'firstmodelyear': '2010'})
    obs = scen.vintage_and_active_years()
    exp = pd.DataFrame({'year_vtg': (2000, 2000, 2010, 2010, 2020),
                        'year_act': (2010, 2020, 2010, 2020, 2020)})
    pdt.assert_frame_equal(exp, obs, check_like=True)  # ignore col order
예제 #22
0
def test_add_cat_unique(test_mp):
    scen = Scenario(test_mp, *msg_multiyear_args)
    scen2 = scen.clone(keep_solution=False)
    scen2.check_out()
    scen2.add_cat('year', 'firstmodelyear', 2020, True)
    df = scen2.cat('year', 'firstmodelyear')
    npt.assert_array_equal(df, ['2020'])
    scen2.discard_changes()
예제 #23
0
def test_share_commodity_lo(test_mp):
    scen = Scenario(test_mp, *msg_args)
    scen.solve()

    # data for share bound
    def calc_share(s):
        a = calculate_activity(
            s, tec='transport_from_seattle').loc['to_new-york']
        b = calculate_activity(
            s, tec='transport_from_san-diego').loc['to_new-york']
        return a / (a + b)

    exp = 1. * calc_share(scen)

    # add share constraints
    clone = scen.clone(scenario='share_commodity_lo', keep_solution=False)
    clone.check_out()
    clone.add_cat('technology', 'share', 'transport_from_seattle')
    clone.add_cat('technology', 'total', ['transport_from_seattle',
                                          'transport_from_san-diego'])
    clone.add_set('shares', 'test-share')
    clone.add_set('map_shares_commodity_share',
                  pd.DataFrame({
                      'shares': 'test-share',
                      'node_share': 'new-york',
                      'node': 'new-york',
                      'type_tec': 'share',
                      'mode': 'all',
                      'commodity': 'cases',
                      'level': 'consumption',
                  }, index=[0]))
    clone.add_set('map_shares_commodity_total',
                  pd.DataFrame({
                      'shares': 'test-share',
                      'node_share': 'new-york',
                      'node': 'new-york',
                      'type_tec': 'total',
                      'mode': 'all',
                      'commodity': 'cases',
                      'level': 'consumption',
                  }, index=[0]))
    clone.add_par('share_commodity_lo',
                  pd.DataFrame({
                      'shares': 'test-share',
                      'node_share': 'new-york',
                      'year_act': 2010,
                      'time': 'year',
                      'unit': 'cases',
                      'value': exp,
                  }, index=[0]))
    clone.commit('foo')
    clone.solve()
    obs = calc_share(clone)
    assert np.isclose(obs, exp)

    orig_obj = scen.var('OBJ')['lvl']
    new_obj = clone.var('OBJ')['lvl']
    assert new_obj >= orig_obj
예제 #24
0
def test_excel_read_write(test_mp):
    fname = 'test_excel_read_write.xlsx'

    scen1 = Scenario(test_mp, *msg_args)
    scen1.to_excel(fname)

    scen2 = Scenario(test_mp, model='foo', scenario='bar', version='new')
    scen2.read_excel(fname)

    exp = scen1.par('input')
    obs = scen2.par('input')
    pdt.assert_frame_equal(exp, obs)

    scen2.commit('foo')  # must be checked in
    scen2.solve()
    assert np.isclose(scen2.var('OBJ')['lvl'], 153.675)

    os.remove(fname)
예제 #25
0
def test_excel_read_write(message_test_mp, tmp_path):
    # Path to temporary file
    tmp_path /= 'excel_read_write.xlsx'
    # Convert to string to ensure this can be handled
    fname = str(tmp_path)

    scen1 = Scenario(message_test_mp, **SCENARIO['dantzig'])
    scen1 = scen1.clone(keep_solution=False)
    scen1.check_out()
    scen1.init_set('new_set')
    scen1.add_set('new_set', 'member')
    scen1.init_par('new_par', idx_sets=['new_set'])
    scen1.add_par('new_par', 'member', 2, '-')
    scen1.commit('new set and parameter added.')

    # Writing to Excel without solving
    scen1.to_excel(fname)

    # Writing to Excel when scenario has a solution
    scen1.solve()
    scen1.to_excel(fname)

    scen2 = Scenario(message_test_mp,
                     model='foo',
                     scenario='bar',
                     version='new')

    # Fails without init_items=True
    with pytest.raises(ValueError, match="no set 'new_set'"):
        scen2.read_excel(fname)

    # Succeeds with init_items=True
    scen2.read_excel(fname, init_items=True, commit_steps=True)

    exp = scen1.par('input')
    obs = scen2.par('input')
    pdt.assert_frame_equal(exp, obs)

    assert scen2.has_par('new_par')
    assert float(scen2.par('new_par')['value']) == 2

    scen2.commit('foo')  # must be checked in
    scen2.solve()
    assert np.isclose(scen2.var('OBJ')['lvl'], scen1.var('OBJ')['lvl'])
예제 #26
0
def test_reporter(test_mp):
    scen = Scenario(test_mp,
                    'canning problem (MESSAGE scheme)',
                    'standard')

    # Varies between local & CI contexts
    # DEBUG may be due to reuse of test_mp in a non-deterministic order
    if not scen.has_solution():
        scen.solve()

    # IXMPReporter can be initialized on a MESSAGE Scenario
    rep_ix = ixmp_Reporter.from_scenario(scen)

    # message_ix.Reporter can also be initialized
    rep = Reporter.from_scenario(scen)

    # Number of quantities available in a rudimentary MESSAGEix Scenario
    assert len(rep.graph['all']) == 120

    # Quantities have short dimension names
    assert 'demand:n-c-l-y-h' in rep.graph

    # Aggregates are available
    assert 'demand:n-l-h' in rep.graph

    # Quantities contain expected data
    dims = dict(coords=['chicago new-york topeka'.split()], dims=['n'])
    demand = xr.DataArray([300, 325, 275], **dims)

    # NB the call to squeeze() drops the length-1 dimensions c-l-y-h
    obs = rep.get('demand:n-c-l-y-h').squeeze(drop=True)
    # TODO: Squeeze on AttrSeries still returns full index, whereas xarray
    # drops everything except node
    obs = obs.reset_index(['c', 'l', 'y', 'h'], drop=True)
    # check_dtype is false because of casting in pd.Series to float
    # check_attrsis false because we don't get the unit addition in bare xarray
    assert_qty_equal(obs.sort_index(), demand,
                     check_attrs=False, check_dtype=False)

    # ixmp.Reporter pre-populated with only model quantities and aggregates
    assert len(rep_ix.graph) == 5088

    # message_ix.Reporter pre-populated with additional, derived quantities
    assert len(rep.graph) == 7975

    # Derived quantities have expected dimensions
    vom_key = rep.full_key('vom')
    assert vom_key not in rep_ix
    assert vom_key == 'vom:nl-t-yv-ya-m-h'

    # …and expected values
    vom = (
        rep.get(rep.full_key('ACT')) * rep.get(rep.full_key('var_cost'))
    ).dropna()
    # check_attrs false because `vom` multiply above does not add units
    assert_qty_equal(vom, rep.get(vom_key), check_attrs=False)
예제 #27
0
def test_years_active_extend(test_mp):
    scen = Scenario(test_mp, *msg_multiyear_args)
    scen = scen.clone(keep_solution=False)
    scen.check_out()
    scen.add_set('year', ['2040', '2050'])
    scen.add_par('duration_period', '2040', 10, 'y')
    scen.add_par('duration_period', '2050', 10, 'y')
    df = scen.years_active('seattle', 'canning_plant', '2020')
    npt.assert_array_equal(df, [2020, 2030, 2040])
    scen.discard_changes()
예제 #28
0
def test_add_cat(test_mp):
    scen = Scenario(test_mp, *msg_args)
    scen2 = scen.clone(keep_solution=False)
    scen2.check_out()
    scen2.add_cat('technology', 'trade',
                  ['transport_from_san-diego', 'transport_from_seattle'])
    df = scen2.cat('technology', 'trade')
    npt.assert_array_equal(
        df, ['transport_from_san-diego', 'transport_from_seattle'])
    scen2.discard_changes()
예제 #29
0
def test_rename_technology(test_mp):
    scen = Scenario(test_mp, *msg_args)
    assert scen.par('output')['technology'].isin(['canning_plant']).any()

    clone = scen.clone('foo', 'bar')
    clone.rename('technology', {'canning_plant': 'foo_bar'})
    assert not clone.par('output')['technology'].isin(['canning_plant']).any()
    assert clone.par('output')['technology'].isin(['foo_bar']).any()
    clone.solve()
    assert np.isclose(clone.var('OBJ')['lvl'], 153.675)
예제 #30
0
def test_no_constraint(test_mp):
    scen = Scenario(test_mp, MODEL, "no_constraint", version="new")
    model_setup(scen, [2020, 2030])
    scen.commit("initialize test scenario")
    scen.solve(quiet=True)

    # without emissions constraint, the zero-cost technology satisfies demand
    assert scen.var("OBJ")["lvl"] == 0
    # without emissions constraint, there are no emission prices
    assert scen.var("PRICE_EMISSION").empty