def test_start_off_with_initial_down_time_equal_to_min_down_time(): forward_data = pd.DataFrame({ 'interval': [0, 1, 2], 'nsw-energy': [200, 200, 200] }) p = planner.DispatchPlanner(dispatch_interval=60, planning_horizon=3) u = units.GenericUnit(p, initial_dispatch=0.0) u.set_service_region('energy', 'nsw') u.add_to_market_energy_flow(100.0) u.add_primary_energy_source(100.0) u.add_unit_minimum_operating_level(min_loading=50.0, shutdown_ramp_rate=100.0, start_up_ramp_rate=100.0, min_up_time=60, min_down_time=120, time_in_initial_state=120) p.add_regional_market('nsw', 'energy', forward_data) p.optimise() dispatch = u.get_dispatch() expect_dispatch = pd.DataFrame({ 'interval': [0, 1, 2], 'net_dispatch': [100.0, 100.0, 100.0] }) assert_frame_equal(expect_dispatch, dispatch)
def test_energy_storage_over_two_intervals_with_inelastic_prices(): forward_data = pd.DataFrame({'interval': [0, 1], 'nsw-energy': [100, 200]}) p = planner.DispatchPlanner(dispatch_interval=60, planning_horizon=2) u = units.GenericUnit(p, initial_dispatch=0.0) u.set_service_region('energy', 'nsw') u.add_to_market_energy_flow(capacity=100.0) u.add_from_market_energy_flow(capacity=100.0) u.add_storage(mwh=100.0, initial_mwh=0.0, output_capacity=100.0, input_capacity=100.0, output_efficiency=1.0, input_efficiency=1.0) p.add_regional_market('nsw', 'energy', forecast=forward_data) p.optimise() dispatch = u.get_dispatch() expect_dispatch = pd.DataFrame({ 'interval': [0, 1], 'net_dispatch': [-100.0, 100.0] }) assert_frame_equal(expect_dispatch, dispatch)
def test_energy_storage_over_three_intervals_with_elastic_prices(): historical_data = pd.DataFrame({ 'interval': np.linspace(0, 100, num=101).astype(int), 'nsw-energy': np.linspace(0, 500, num=101), 'nsw-demand': np.linspace(0, 500, num=101) }) forward_data = pd.DataFrame({ 'interval': [0, 1, 2], 'nsw-demand': [100.0, 400.0, 400.0] }) f = planner.Forecaster() f.train(historical_data, train_sample_fraction=1.0, target_col='nsw-energy') price_forecast = f.price_forecast_with_generation_sensitivities( forward_data, region='nsw', market='energy', min_delta=-50, max_delta=50, steps=100) p = planner.DispatchPlanner(dispatch_interval=60, planning_horizon=3) u = units.GenericUnit(p, initial_dispatch=0.0) u.set_service_region('energy', 'nsw') u.add_to_market_energy_flow(capacity=50.0) u.add_from_market_energy_flow(capacity=50.0) u.add_storage(mwh=50.0, initial_mwh=0.0, output_capacity=50.0, input_capacity=50.0, output_efficiency=1.0, input_efficiency=1.0) p.add_regional_market('nsw', 'energy', forecast=price_forecast) p.optimise() dispatch = u.get_dispatch() expect_dispatch = pd.DataFrame({ 'interval': [0, 1, 2], 'net_dispatch': [-50.0, 25.0, 25.0] }) assert_frame_equal(expect_dispatch, dispatch)
def test_initial_down_time_cold_start_costs_should_turn_on(): forward_data = pd.DataFrame({ 'interval': [0, 1, 2, 3, 4, 5], 'nsw-energy': [200.0, 0.0, 0.0, 0.0, 0.0, 0.0] }) p = planner.DispatchPlanner(dispatch_interval=60, planning_horizon=6) u = units.GenericUnit(p, initial_dispatch=0.0) u.set_service_region('energy', 'nsw') u.add_to_market_energy_flow(100.0) u.add_primary_energy_source(100.0, cost=100.0) u.add_unit_minimum_operating_level(min_loading=50.0, shutdown_ramp_rate=100.0, start_up_ramp_rate=100.0, min_up_time=60, min_down_time=60, time_in_initial_state=60 * 9) hot_start_cost = 100 * 100 - 1 cold_start_cost = hot_start_cost * 2 u.add_startup_costs(hot_start_cost=hot_start_cost, cold_start_cost=cold_start_cost, time_to_go_cold=60 * 10) p.add_regional_market('nsw', 'energy', forward_data) p.optimise() dispatch = u.get_dispatch() expect_dispatch = pd.DataFrame({ 'interval': [0, 1, 2, 3, 4, 5], 'net_dispatch': [100.0, 0.0, 0.0, 0.0, 0.0, 0.0] }) assert_frame_equal(expect_dispatch, dispatch)
# Extract just the baseline forecast for running the price taker assumption optimisation. baseline_forecast = price_forecast.loc[:, ['interval', 0]] baseline_forecast.columns = ['interval', 'nsw-energy'] # Get historical price data for forecast period. price_data = historical_inputs.get_regional_prices(start_time_forward_data, end_time_forward_data, raw_data_cache) price_data = price_data.reset_index(drop=True) price_data['interval'] = price_data.index # Do dispatch planning assuming price taker assumption. Planner uses actual historical price data and assumes # fleet dispatch does not impact price. price_taker_planner = planner.DispatchPlanner(dispatch_interval=5, planning_horizon=len( forward_data.index)) # Add unit commitment model to dispatch planner battery_storage = units.GenericUnit(price_taker_planner, initial_dispatch=0.0) battery_storage.set_service_region('energy', 'nsw') battery_storage.add_to_market_energy_flow(capacity=1000.0) battery_storage.add_from_market_energy_flow(capacity=1000.0) battery_storage.add_storage(mwh=4000.0, initial_mwh=2000.0, output_capacity=1000.0, input_capacity=1000.0, output_efficiency=0.9, input_efficiency=0.9) price_taker_planner.add_regional_market('nsw',