def test_capacity_factor_zero(request):
    """Test zero capacity factor (CF) in a time slice.

    "solar_pv_ppl" is active in "day" and NOT at "night" (CF = 0). It is expected that
    the model will be infeasible, because "demand" at night cannot be met.
    """
    # Dictionary of technology input/output
    tec_dict = {
        "solar_pv_ppl": {
            "time_origin": [],
            "time": ["day", "night"],
            "time_dest": ["day", "night"],
        },
    }

    # Build model and solve (should raise GAMS error)
    with pytest.raises(ModelError):
        make_subannual(
            request,
            tec_dict,
            com_dict={"solar_pv_ppl": {"input": "fuel", "output": "electr"}},
            time_steps=TS_0,
            demand={"day": 2, "night": 1},
            capacity={"solar_pv_ppl": {"inv_cost": 0.2, "technical_lifetime": 5}},
            capacity_factor={"solar_pv_ppl": {"day": 0.8, "night": 0}},
        )
def test_linked_three_temporal_levels_season_to_year(request):
    """Test three linked temporal levels from season to year.

    "season" is linked to "year". Model solves.
    """
    # Dictionary of technology input/output
    tec_dict = {
        "gas_ppl": {
            "time_origin": ["winter", "winter"],
            "time": ["Jan", "Feb"],
            "time_dest": ["year", "year"],
        },
        "gas_supply": {
            "time_origin": [],
            "time": ["winter", "summer"],
            "time_dest": ["winter", "summer"],
        },
    }
    scen = make_subannual(
        request,
        tec_dict,
        time_steps=TS_1,
        demand={"year": 2},
        com_dict=COM_DICT,
    )
    check_solution(scen)
def test_linked_three_temporal_levels_time_act(request):
    """Test three linked temporal levels, with activity only at "time".

    Model solves.
    """
    # Dictionary of technology input/output
    tec_dict = {
        "gas_ppl": {
            "time_origin": ["year", "year"],
            "time": ["summer", "winter"],
            "time_dest": ["year", "year"],
        },
        "gas_supply": {
            "time_origin": [],
            "time": ["year"],
            "time_dest": ["year"],
        },
    }

    scen = make_subannual(
        request,
        tec_dict,
        time_steps=TS_0,
        demand={"year": 2},
        com_dict=COM_DICT,
    )
    check_solution(scen)
def test_seasons_to_seasons(request):
    """Test two seasons at one temporal level.

    "demand" in two time slices: "summer" and "winter" (duration = 0.5). Model solves
    and "gas_supply" is active.
    """
    # Dictionary of technology input/output
    tec_dict = {
        "gas_ppl": {
            "time_origin": ["summer", "winter"],
            "time": ["summer", "winter"],
            "time_dest": ["summer", "winter"],
        },
        "gas_supply": {
            "time_origin": [],
            "time": ["summer", "winter"],
            "time_dest": ["summer", "winter"],
        },
    }

    scen = make_subannual(
        request,
        tec_dict,
        time_steps=TS_0,
        demand={
            "summer": 1,
            "winter": 1
        },
        com_dict=COM_DICT,
    )
    check_solution(scen)
def test_temporal_levels_not_linked(request):
    """Test two unlinked temporal levels.

    "gas_ppl" is active in "summer" and NOT linked to "gas_supply" in "year". This
    setup should not solve.
    """
    tec_dict = TD_0.copy()
    tec_dict["gas_ppl"]["time_origin"] = ["summer"]

    # Check the model not solve if there is no link between fuel supply and power plant
    with pytest.raises(ModelError):
        make_subannual(
            request,
            tec_dict,
            time_steps=[("summer", 1, "season", "year")],
            demand={"summer": 2},
            com_dict=COM_DICT,
        )
def test_unlinked_three_temporal_levels(request):
    """Test three unlinked temporal levels.

    "month" is defined under "season" BUT "season" not linked to "year". Model should
    not solve.
    """

    # Check the model shouldn't solve
    with pytest.raises(ModelError):
        make_subannual(
            request,
            TD_2,
            time_steps=TS_1[
                2:],  # Exclude the definitions of "summer" and "winter"
            demand={
                "Jan": 1,
                "Feb": 1
            },
            com_dict=COM_DICT,
        )
def test_linked_three_temporal_levels_different_duration(request):
    """Test three linked temporal levels with different duration times.

    Model solves, linking "month" through "season" to "year".
    """
    scen = make_subannual(
        request,
        TD_3,
        time_steps=TS_1,
        demand={"year": 2},
        com_dict=COM_DICT,
    )
    check_solution(scen)
def test_linked_three_temporal_levels_month_to_year(request):
    """Test three linked temporal levels from month to season and year.

    "month" is linked to "season", and "season" is linked to "year". Model solves.
    """

    scen = make_subannual(
        request,
        TD_3,
        time_steps=TS_1,
        demand={"year": 2},
        com_dict=COM_DICT,
    )
    check_solution(scen)
def test_capacity_factor_unequal_time(request):
    """``capacity_factor`` is calculated correctly when ``duration_time`` is uneven."""
    # Build model and solve
    scen = make_subannual(
        request,
        TD_0,
        time_steps=[
            ("summer", 0.3, "season", "year"),
            ("winter", 0.7, "season", "year"),
        ],
        demand={"summer": 2, "winter": 1},
        capacity_factor={"gas_ppl": {"summer": 0.8, "winter": 0.8}},
        var_cost={"gas_ppl": {"summer": 0.2, "winter": 0.2}},
    )
    check_solution(scen)
def test_capacity_factor_time(request):
    """``capacity_factor`` is calculated correctly when it varies by time slice."""
    # Build model and solve
    scen = make_subannual(
        request,
        TD_0,
        time_steps=[
            ("summer", 0.5, "season", "year"),
            ("winter", 0.5, "season", "year"),
        ],
        demand={"summer": 2, "winter": 1},
        capacity_factor={"gas_ppl": {"summer": 0.8, "winter": 0.6}},
        var_cost={"gas_ppl": {"summer": 0.2, "winter": 0.2}},
    )
    check_solution(scen)
def test_linked_three_temporal_levels(request):
    """Test three linked temporal levels.

    "month" is defined under "season", and "season" is linked to "year". Model solves.
    """
    scen = make_subannual(
        request,
        TD_2,
        time_steps=TS_1,
        demand={
            "Jan": 1,
            "Feb": 1
        },
        com_dict=COM_DICT,
    )
    check_solution(scen)
def test_two_seasons_to_year(request):
    """Test two linked temporal levels with two seasons.

    "demand" in two time slices: "summer" and "winter" (duration = 0.5). Model solves
    and "gas_supply" is active.
    """
    scen = make_subannual(
        request,
        TD_1,
        time_steps=TS_0,
        demand={
            "summer": 1,
            "winter": 1
        },
        com_dict=COM_DICT,
    )
    check_solution(scen)
def test_capacity_factor_zero_two(request):
    """Test zero capacity factor (CF) in a time slice.

    "solar_pv_ppl" is active in "day" and NOT at "night" (CF = 0). The model output
    should show no activity of "solar_pv_ppl" at "night". So, "gas_ppl" is active at
    "night", even though a more expensive technology.
    """
    # Dictionary of technology input/output
    tec_dict = {
        "solar_pv_ppl": {
            "time_origin": [],
            "time": ["day", "night"],
            "time_dest": ["day", "night"],
        },
        "gas_ppl": {
            "time_origin": [],
            "time": ["day", "night"],
            "time_dest": ["day", "night"],
        },
    }

    # Build model and solve
    scen = make_subannual(
        request,
        tec_dict,
        com_dict={
            "solar_pv_ppl": {"input": "fuel", "output": "electr"},
            "gas_ppl": {"input": "fuel", "output": "electr"},
        },
        time_steps=TS_0,
        demand={"day": 2, "night": 1},
        capacity={
            "solar_pv_ppl": {"inv_cost": 0.1, "technical_lifetime": 5},
            "gas_ppl": {"inv_cost": 0.1, "technical_lifetime": 5},
        },
        capacity_factor={
            "solar_pv_ppl": {"day": 0.8, "night": 0},
            "gas_ppl": {"day": 0.8, "night": 0.8},
        },
        var_cost={
            "solar_pv_ppl": {"day": 0, "night": 0},
            "gas_ppl": {"day": 0.2, "night": 0.2},
        },
    )
    check_solution(scen)
def test_season_to_year(request):
    """Test two linked temporal levels.

    Linking "gas_ppl" and "gas_supply" at one temporal level (e.g., "year")
    Only one "season" (duration = 1) and "demand" is defined only at "summer"
    Model solves and "gas_supply" is active.
    """
    tec_dict = TD_0.copy()
    tec_dict["gas_ppl"]["time_origin"] = ["year"]

    scen = make_subannual(
        request,
        tec_dict,
        time_steps=[("summer", 1, "season", "year")],
        demand={"summer": 2},
        com_dict=COM_DICT,
    )
    check_solution(scen)
def test_linked_three_temporal_levels_relative(request):
    """Test three linked temporal levels with a relative time.

    "month" is defined under "season", and "season" is linked to "year". Model solves,
    but assertions fail.
    """
    scen = make_subannual(
        request,
        TD_2,
        time_steps=TS_1,
        time_relative=["year", "summer"],
        demand={
            "Jan": 1,
            "Feb": 1
        },
        com_dict=COM_DICT,
    )
    # Shouldn't pass with a relative time duration
    with pytest.raises(AssertionError):
        check_solution(scen)
def test_two_seasons_to_year_relative(request):
    """Test two linked temporal levels with two seasons and a relative time.

    "demand" in two time slices: "summer" and "winter" (duration = 0.5). Model solves,
    but assertions fail.
    """
    scen = make_subannual(
        request,
        TD_1,
        time_steps=TS_0,
        time_relative=["year"],
        demand={
            "summer": 1,
            "winter": 1
        },
        com_dict=COM_DICT,
    )
    # Shouldn't pass the test, if adding relative duration time
    with pytest.raises(AssertionError):
        check_solution(scen)