Ejemplo n.º 1
0
def test_pass_too_many_things(mock_gencost, mock_pg, mock_scenario):
    with pytest.raises(ValueError):
        calculate_costs(gencost=mock_gencost,
                        pg=mock_pg,
                        scenario=mock_scenario)
Ejemplo n.º 2
0
def test_pass_just_gencost(mock_gencost):
    with pytest.raises(ValueError):
        calculate_costs(gencost=mock_gencost)
Ejemplo n.º 3
0
def test_pass_just_pg(mock_pg):
    with pytest.raises(ValueError):
        calculate_costs(pg=mock_pg)
Ejemplo n.º 4
0
def test_pass_nothing():
    with pytest.raises(ValueError):
        calculate_costs()
Ejemplo n.º 5
0
def test_calculate_cost_equal_both_methods(mock_gencost, mock_pg,
                                           mock_scenario):
    scenario_calculated = calculate_costs(scenario=mock_scenario)
    gencost_pg_calculated = calculate_costs(gencost=mock_gencost, pg=mock_pg)
    assert scenario_calculated.equals(gencost_pg_calculated)
Ejemplo n.º 6
0
def generate_emissions_stats(scenario, pollutant="carbon", method="simple"):
    """Calculate hourly emissions for each generator.

    :param powersimdata.scenario.scenario.Scenario scenario: scenario instance.
    :param str pollutant: pollutant to analyze.
    :param str method: selected method to handle no-load fuel consumption.
    :return: (*pandas.DataFrame*) -- emissions data frame. index: timestamps, column:
        plant id, values: emission in tons.

    .. note:: method descriptions:

        - 'simple' uses a fixed ratio of CO2 to MWh
        - 'always-on' uses generator heat-rate curves including non-zero intercepts
        - 'decommit' uses generator heat-rate curves but de-commits generators if they
          are off (detected by pg < 1 MW).
    """
    _check_scenario_is_in_analyze_state(scenario)
    mi = ModelImmutables(scenario.info["grid_model"])
    allowed_methods = {
        "carbon": {"simple", "always-on", "decommit"},
        "nox": {"simple"},
        "so2": {"simple"},
    }
    emissions_per_mwh = {
        "carbon": mi.plants["carbon_per_mwh"],
        "nox": mi.plants["nox_per_mwh"],
        "so2": mi.plants["so2_per_mwh"],
    }

    if pollutant not in allowed_methods.keys():
        raise ValueError("Unknown pollutant for generate_emissions_stats()")
    if not isinstance(method, str):
        raise TypeError("method must be a str")
    if method not in allowed_methods[pollutant]:
        err_msg = f"method for {pollutant} must be one of: {allowed_methods[pollutant]}"
        raise ValueError(err_msg)

    pg = scenario.state.get_pg()
    grid = scenario.state.get_grid()
    emissions = pd.DataFrame(np.zeros_like(pg),
                             index=pg.index,
                             columns=pg.columns)

    if method == "simple":
        for fuel, val in emissions_per_mwh[pollutant].items():
            indices = (grid.plant["type"] == fuel).to_numpy()
            emissions.loc[:, indices] = pg.loc[:, indices] * val / 1000
    elif method in ("decommit", "always-on"):
        decommit = True if method == "decommit" else False

        costs = calculate_costs(pg=pg,
                                gencost=grid.gencost["before"],
                                decommit=decommit)
        heat = np.zeros_like(costs)

        for fuel, val in mi.plants["carbon_per_mmbtu"].items():
            indices = (grid.plant["type"] == fuel).to_numpy()
            heat[:, indices] = (costs.iloc[:, indices] /
                                grid.plant["GenFuelCost"].values[indices])
            emissions.loc[:, indices] = heat[:, indices] * val * 44 / 12 / 1000
    else:
        raise Exception("I should not be able to get here")

    return emissions