Ejemplo n.º 1
0
def storage_setup(test_mp, time_duration, comment):

    # First, building a simple model and adding seasonality
    scen = Scenario(test_mp, "no_storage", "standard", version="new")
    model_setup(scen, [2020])
    add_seasonality(scen, time_duration)
    # Fixed share for parameters that don't change across timesteps
    fixed_share = {"a": 1, "b": 1, "c": 1, "d": 1}
    year_to_time(scen, "output", fixed_share)
    year_to_time(scen, "var_cost", fixed_share)
    # Variable share for parameters that are changing in each timestep
    # share of demand in each season from annual demand
    demand_share = {"a": 0.15, "b": 0.2, "c": 0.4, "d": 0.25}
    year_to_time(scen, "demand", demand_share)
    scen.commit("initialized a model with timesteps")
    scen.solve(case="no_storage" + comment)

    # Second, adding upper bound on activity of the cheap technology (wind_ppl)
    scen.remove_solution()
    scen.check_out()
    for h in time_duration.keys():
        scen.add_par(
            "bound_activity_up", ["node", "wind_ppl", 2020, "mode", h], 0.25, "GWa"
        )
    scen.commit("activity bounded")
    scen.solve(case="no_storage_bounded" + comment)
    cost_no_stor = scen.var("OBJ")["lvl"]
    act_no_stor = scen.var("ACT", {"technology": "gas_ppl"})["lvl"].sum()

    # Third, adding storage technologies but with no input to storage device
    scen.remove_solution()
    scen.check_out()
    # Chronological order of timesteps in the year
    time_order = {"a": 1, "b": 2, "c": 3, "d": 4}
    add_storage_data(scen, time_order)
    scen.commit("storage data added")
    scen.solve(case="with_storage_no_input" + comment)
    act = scen.var("ACT")

    # Forth, adding storage technologies and providing input to storage device
    scen.remove_solution()
    scen.check_out()
    # Adding a new technology "cooler" to provide input of "cooling" to dam
    scen.add_set("technology", "cooler")
    df = scen.par("output", {"technology": "turbine"})
    df["technology"] = "cooler"
    df["commodity"] = "cooling"
    scen.add_par("output", df)
    # Changing input of dam from 1 to 1.2 to test commodity balance
    df = scen.par("input", {"technology": "dam"})
    df["value"] = 1.2
    scen.add_par("input", df)
    scen.commit("storage needs no separate input")
    scen.solve(case="with_storage_and_input" + comment)
    cost_with_stor = scen.var("OBJ")["lvl"]
    act_with_stor = scen.var("ACT", {"technology": "gas_ppl"})["lvl"].sum()

    # Fifth. Tests for the functionality of storage
    # 1. Check that "dam" is not active if no "input" commodity is defined
    assert "dam" not in act[act["lvl"] > 0]["technology"].tolist()

    # 2. Testing functionality of storage
    # Check the contribution of storage to the system cost
    assert cost_with_stor < cost_no_stor
    # Activity of expensive technology should be lower with storage
    assert act_with_stor < act_no_stor

    # 3. Activity of discharger <= activity of charger + initial content
    act_pump = scen.var("ACT", {"technology": "pump"})["lvl"]
    act_turb = scen.var("ACT", {"technology": "turbine"})["lvl"]
    initial_content = float(scen.par("storage_initial")["value"])
    assert act_turb.sum() <= act_pump.sum() + initial_content

    # 4. Activity of input provider to storage = act of storage * storage input
    for ts in time_duration.keys():
        act_cooler = scen.var("ACT", {"technology": "cooler", "time": ts})["lvl"]
        inp = scen.par("input", {"technology": "dam", "time": ts})["value"]
        act_stor = scen.var("ACT", {"technology": "dam", "time": ts})["lvl"]
        assert float(act_cooler) == float(inp) * float(act_stor)

    # 5. Max activity of charger <= max activity of storage
    max_pump = max(act_pump)
    act_storage = scen.var("ACT", {"technology": "dam"})["lvl"]
    max_stor = max(act_storage)
    assert max_pump <= max_stor

    # 6. Max activity of discharger <= max storage act - self discharge losses
    max_turb = max(act_turb)
    loss = scen.par("storage_self_discharge")["value"][0]
    assert max_turb <= max_stor * (1 - loss)

    # Sixth, testing equations of storage (when added to ixmp variables)
    if scen.has_var("STORAGE"):
        # 1. Equality: storage content in the beginning and end is related
        storage_first = scen.var("STORAGE", {"time": "a"})["lvl"]
        storage_last = scen.var("STORAGE", {"time": "d"})["lvl"]
        relation = scen.par("relation_storage", {"time_first": "d", "time_last": "a"})[
            "value"
        ][0]
        assert storage_last >= storage_first * relation

        # 2. Storage content should never exceed storage activity
        assert max(scen.var("STORAGE")["lvl"]) <= max_stor

        # 3. Commodity balance: charge - discharge - losses = 0
        change = scen.var("STORAGE_CHARGE").set_index(["year_act", "time"])["lvl"]
        loss = scen.par("storage_self_discharge").set_index(["year", "time"])["value"]
        assert sum(change[change > 0] * (1 - loss)) == -sum(change[change < 0])

        # 4. Energy balance: storage change + losses = storage content
        storage = scen.var("STORAGE").set_index(["year", "time"])["lvl"]
        assert storage[(2020, "b")] * (1 - loss[(2020, "b")]) == -change[(2020, "c")]
Ejemplo n.º 2
0
def storage_setup(test_mp, time_duration, comment):

    # First, building a simple model and adding seasonality
    scen = Scenario(test_mp, 'no_storage', 'standard', version='new')
    model_setup(scen, [2020])
    add_seasonality(scen, time_duration)
    # Fixed share for parameters that don't change across timesteps
    fixed_share = {'a': 1, 'b': 1, 'c': 1, 'd': 1}
    year_to_time(scen, 'output', fixed_share)
    year_to_time(scen, 'var_cost', fixed_share)
    # Variable share for parameters that are changing in each timestep
    # share of demand in each season from annual demand
    demand_share = {'a': 0.15, 'b': 0.2, 'c': 0.4, 'd': 0.25}
    year_to_time(scen, 'demand', demand_share)
    scen.commit('initialized a model with timesteps')
    scen.solve(case='no_storage' + comment)

    # Second, adding upper bound on activity of the cheap technology (wind_ppl)
    scen.remove_solution()
    scen.check_out()
    for h in time_duration.keys():
        scen.add_par('bound_activity_up',
                     ['node', 'wind_ppl', 2020, 'mode', h], 0.25, 'GWa')
    scen.commit('activity bounded')
    scen.solve(case='no_storage_bounded' + comment)
    cost_no_stor = scen.var('OBJ')['lvl']
    act_no_stor = scen.var('ACT', {'technology': 'gas_ppl'})['lvl'].sum()

    # Third, adding storage technologies but with no input to storage device
    scen.remove_solution()
    scen.check_out()
    # Chronological order of timesteps in the year
    time_order = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
    add_storage_data(scen, time_order)
    scen.commit('storage data added')
    scen.solve(case='with_storage_no_input' + comment)
    act = scen.var('ACT')

    # Forth, adding storage technologies and providing input to storage device
    scen.remove_solution()
    scen.check_out()
    # Adding a new technology "cooler" to provide input of "cooling" to dam
    scen.add_set('technology', 'cooler')
    df = scen.par('output', {'technology': 'turbine'})
    df['technology'] = 'cooler'
    df['commodity'] = 'cooling'
    scen.add_par('output', df)
    # Changing input of dam from 1 to 1.2 to test commodity balance
    df = scen.par('input', {'technology': 'dam'})
    df['value'] = 1.2
    scen.add_par('input', df)
    scen.commit('storage needs no separate input')
    scen.solve(case='with_storage_and_input' + comment)
    cost_with_stor = scen.var('OBJ')['lvl']
    act_with_stor = scen.var('ACT', {'technology': 'gas_ppl'})['lvl'].sum()

    # Fifth. Tests for the functionality of storage
    # 1. Check that "dam" is not active if no "input" commodity is defined
    assert 'dam' not in act[act['lvl'] > 0]['technology'].tolist()

    # 2. Testing functionality of storage
    # Check the contribution of storage to the system cost
    assert cost_with_stor < cost_no_stor
    # Activity of expensive technology should be lower with storage
    assert act_with_stor < act_no_stor

    # 3. Activity of discharger <= activity of charger + initial content
    act_pump = scen.var('ACT', {'technology': 'pump'})['lvl']
    act_turb = scen.var('ACT', {'technology': 'turbine'})['lvl']
    initial_content = float(scen.par('storage_initial')['value'])
    assert act_turb.sum() <= act_pump.sum() + initial_content

    # 4. Activity of input provider to storage = act of storage * storage input
    for ts in time_duration.keys():
        act_cooler = scen.var('ACT', {
            'technology': 'cooler',
            'time': ts
        })['lvl']
        inp = scen.par('input', {'technology': 'dam', 'time': ts})['value']
        act_stor = scen.var('ACT', {'technology': 'dam', 'time': ts})['lvl']
        assert float(act_cooler) == float(inp) * float(act_stor)

    # 5. Max activity of charger <= max activity of storage
    max_pump = max(act_pump)
    act_storage = scen.var('ACT', {'technology': 'dam'})['lvl']
    max_stor = max(act_storage)
    assert max_pump <= max_stor

    # 6. Max activity of discharger <= max storage act - self discharge losses
    max_turb = max(act_turb)
    loss = scen.par('storage_self_discharge')['value'][0]
    assert max_turb <= max_stor * (1 - loss)

    # Sixth, testing equations of storage (when added to ixmp variables)
    if scen.has_var('STORAGE'):
        # 1. Equality: storage content in the beginning and end is related
        storage_first = scen.var('STORAGE', {'time': 'a'})['lvl']
        storage_last = scen.var('STORAGE', {'time': 'd'})['lvl']
        relation = scen.par('relation_storage', {
            'time_first': 'd',
            'time_last': 'a'
        })['value'][0]
        assert storage_last >= storage_first * relation

        # 2. Storage content should never exceed storage activity
        assert max(scen.var('STORAGE')['lvl']) <= max_stor

        # 3. Commodity balance: charge - discharge - losses = 0
        change = scen.var('STORAGE_CHARGE').set_index(['year_act',
                                                       'time'])['lvl']
        loss = scen.par('storage_self_discharge').set_index(['year',
                                                             'time'])['value']
        assert sum(change[change > 0] * (1 - loss)) == -sum(change[change < 0])

        # 4. Energy balance: storage change + losses = storage content
        storage = scen.var('STORAGE').set_index(['year', 'time'])['lvl']
        assert storage[(2020,
                        'b')] * (1 - loss[(2020, 'b')]) == -change[(2020, 'c')]
Ejemplo n.º 3
0
def storage_setup(test_mp, time_duration, comment):
    # First building a simple model and adding seasonality
    scen = Scenario(test_mp, 'no_storage', 'standard', version='new')
    model_setup(scen, [2020])
    add_seasonality(scen, time_duration)
    fixed_share = {'a': 1, 'b': 1, 'c': 1, 'd': 1}
    year_to_time(scen, 'output', fixed_share)
    year_to_time(scen, 'var_cost', fixed_share)
    demand_share = {'a': 0.15, 'b': 0.2, 'c': 0.4, 'd': 0.25}
    year_to_time(scen, 'demand', demand_share)
    scen.commit('initialized test model')
    scen.solve(case='no_storage' + comment)

    # Second adding bound on the activity of the cheap technology
    scen.remove_solution()
    scen.check_out()
    for h in time_duration.keys():
        scen.add_par('bound_activity_up', ['node', 'tec1', 2020, 'mode', h],
                     0.25, 'GWa')
    scen.commit('activity bounded')
    scen.solve(case='no_storage_bounded' + comment)
    cost_no_storage = scen.var('OBJ')['lvl']
    act_no = scen.var('ACT', {'technology': 'tec2'})['lvl'].sum()

    # Third, adding storage technologies and their parameters
    scen.remove_solution()
    scen.check_out()
    time_order = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
    add_storage_data(scen, time_order)
    scen.commit('storage added')
    scen.solve(case='with_storage' + comment)
    cost_with_storage = scen.var('OBJ')['lvl']
    act_with = scen.var('ACT', {'technology': 'tec2'})['lvl'].sum()

    # I. Tests for functionality of storage
    # I.1. Contribution of storage to the system
    assert cost_with_storage < cost_no_storage
    # Or, activity of expensive technology should be lower with storage
    assert act_with < act_no

    # I.2. Activity of discharger should be always <= activity of charger
    act_pump = scen.var('ACT', {'technology': 'pump'})['lvl']
    act_turb = scen.var('ACT', {'technology': 'turbine'})['lvl']
    assert act_turb.sum() <= act_pump.sum()

    # I.3. Max activity of charger is lower than storage capacity
    max_pump = max(act_pump)
    cap_storage = float(scen.var('CAP', {'technology': 'dam'})['lvl'])
    assert max_pump <= cap_storage

    # I.4. Max activity of discharger is lower than storage capacity - losses
    max_turb = max(act_turb)
    loss = scen.par('storage_loss')['value'][0]
    assert max_turb <= cap_storage * (1 - loss)

    # II. Testing equations of storage (when added to ixmp variables)
    if scen.has_var('STORAGE'):
        # II.1. Equality: storage content in the beginning and end is equal
        storage_first = scen.var('STORAGE', {'time': 'a'})['lvl']
        storage_last = scen.var('STORAGE', {'time': 'd'})['lvl']
        assert storage_first == storage_last

        # II.2. Storage content should never exceed storage capacity
        assert max(scen.var('STORAGE')['lvl']) <= cap_storage

        # II.3. Commodity balance: charge - discharge - losses = 0
        change = scen.var('STORAGE_CHG').set_index(['year_act', 'time'])['lvl']
        loss = scen.par('storage_loss').set_index(['year', 'time'])['value']
        assert sum(change[change > 0] * (1 - loss)) == -sum(change[change < 0])

        # II.4. Energy balance: storage change + losses = storage content
        storage = scen.var('STORAGE').set_index(['year', 'time'])['lvl']
        assert storage[(2020,
                        'b')] * (1 - loss[(2020, 'b')]) == -change[(2020, 'c')]