Skip to content

Commit

Permalink
Merge pull request #117 from intvenlab/addl_curtailment
Browse files Browse the repository at this point in the history
Set additional curtailment function within capacity framework
  • Loading branch information
dmuldrew authored Mar 25, 2020
2 parents 310a5d3 + 2da7469 commit 17d4393
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 18 deletions.
40 changes: 26 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,14 @@ discrepancies between the branch attribute of the `Grid` object and the

## 3. Capacity Planning Framework

First import the framework:
The capacity planning framework replaces an earlier spreadsheet method with
a more flexible design backed up by tests. Additionally, scenario
specific parameters are now automatically imported. More information can
be found at this Dropbox location:

Dropbox(IVL)\Results\DataAnalysis\RenewablesScalingForScenarios\Clean Energy Capacity Planning Framework.pptx

Importing the framework:

``` python
from powersimdata.scaling.clean_capacity_scaling.auto_capacity_scaling \
Expand All @@ -264,7 +271,7 @@ from powersimdata.scaling.clean_capacity_scaling.auto_capacity_scaling \

### A. Create Strategy Object that will generate next capacities

Currently independent and collaborative strategies are implemented. The
Currently two strategies (independent and collaborative) are implemented. The
first step is create an empty strategy object:
``` python
independent_strategy_manager = IndependentStrategyManager()
Expand Down Expand Up @@ -309,8 +316,22 @@ independent_strategy_manager.populate_targets_with_resources(
collaborative_strategy_manager.populate_targets_with_resources(
scenario_info, start_time, end_time):
```
### D. Optional step: Set additional curtailment for regional resources

Additional curtailment is a parameter to iterate from initial anchor
scenario results (defined as a scenario to manually make adjustments from to
account for nonlinearities in grid curtailment)

The interface to set these values has the form:
```
strategy.set_addl_curtailment({‘Alabama’:{‘solar’: 0.2},
‘Maryland’: {‘wind’: 0.1}})
```
which sets additional curtailment for a region and particular resource type
. In this example, the value `0.2` denotes a 20% reduction of solar capacity
factor compared to the reference scenario.

### D. Calculate Next Capacities
### E. Calculate Next Capacities

Once we the regional target information and scenario-specific resource
information, we can calculate the next capacities.
Expand All @@ -321,15 +342,6 @@ collaborative_next_capacities =
collaborative_strategy_manager.data_frame_of_next_capacities()
```

### F. Future Feature: Set additional curtailment for regional resources
### F. Future Feature

Additional curtailment is a parameter to iterate from initial anchor
scenario results (defined as a scenario to manually make adjustments from to
account for nonlinearities in grid curtailment)

The interface will likely have the form:
```
strategy.set_addl_curtailment({‘Alabama’:{‘solar’: .2},
‘Maryland’: {‘wind’: .1}})
```
which sets additional curtailment for a region and particular resource type.
Direct output of the new change table
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,28 @@ def populate_targets_with_resources(self, scenario_info, start_time,
start_time,
end_time)

def set_addl_curtailment(self, additional_curtailment_table):
"""
Sets additional curtailment for a region and particular resource type
:param additional_curtailment_table: nested dictionary structure of
the form: {‘Alabama’:{‘solar’: .2}, ‘Maryland’: {‘wind’: .1}}
The numbers are curtailment factors between 0 and 1.
"""
for region_name, target_obj in additional_curtailment_table.items():
for resource_name, curtailment_factor in target_obj.items():
assert (0 <= curtailment_factor <= 1), \
f"***Curtailment factor for region {region_name} and " \
f"resource {resource_name} must be between 0 and 1!***"
try:
self.targets[region_name].resources[
resource_name].set_addl_curtailment(curtailment_factor)
print(f'Additional curtailment added {region_name}:'
f'{resource_name}!')
except KeyError as e:
raise KeyError(
f"***Region {region_name} and resource "
f"{resource_name} not found***") from e

def add_target(self, target_manager_obj):
"""
Add target to strategy object
Expand Down Expand Up @@ -762,8 +784,8 @@ def set_addl_curtailment(self, addl_curtailment):
Set additional curtailment to included in capacity calculations
:param addl_curtailment: additional curtailment
"""
assert (addl_curtailment >= 0), \
"addl_curtailment must be greater than zero"
assert (0 <= addl_curtailment <= 1), \
"additional_curtailment must be between 0 and 1"
self.addl_curtailment = addl_curtailment

def calculate_expected_cap_factor(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from powersimdata.scaling.clean_capacity_scaling.auto_capacity_scaling\
import Resource, TargetManager, AbstractStrategyManager, \
CollaborativeStrategyManager
from pytest import approx
IndependentStrategyManager, CollaborativeStrategyManager
from pytest import approx, raises


def test_independent_capacity_strategy():
Expand Down Expand Up @@ -548,3 +548,72 @@ def test_collaborative_capacity_strategy():
solar_scaling == approx(4200 + 10447.5)
assert collab.targets['Atlantic'].resources['wind'].prev_capacity *\
wind_scaling == approx(4100 + 10198.75)


def test_adding_addl_curtailment():
# create Pacific
pacific_solar = Resource('solar', 3)
pacific_solar.set_capacity(0.25, 3700, 0.215379)
pacific_solar.set_generation(7000 * 1000)
pacific_solar.set_curtailment(0.138483)
pacific_solar.set_addl_curtailment(0)

pacific_wind = Resource('wind', 3)
pacific_wind.set_capacity(0.4, 3600, 0.347855)
pacific_wind.set_generation(11000 * 1000)
pacific_wind.set_curtailment(0.130363)
pacific_wind.set_addl_curtailment(0)

pacific_target = TargetManager('Pacific', 0.25, 'renewables',
200000 * 1000)
pacific_target.set_allowed_resources(['solar', 'wind', 'geo'])

pacific_target.add_resource(pacific_solar)
pacific_target.add_resource(pacific_wind)

# create Atlantic
atlantic_solar = Resource('solar', 3)
atlantic_solar.set_capacity(0.3, 4200, 0.284608)
atlantic_solar.set_generation(10500 * 1000)
atlantic_solar.set_curtailment(0.051305)
atlantic_solar.set_addl_curtailment(0)

atlantic_wind = Resource('wind', 3)
atlantic_wind.set_capacity(0.35, 4100, 0.319317)
atlantic_wind.set_generation(11500 * 1000)
atlantic_wind.set_curtailment(0.087667)
atlantic_wind.set_addl_curtailment(0)

atlantic_target = TargetManager('Atlantic', 0.4, 'clean', 300000 * 1000)
atlantic_target.set_allowed_resources(['solar', 'wind', 'geo', 'hydro',
'nuclear'])
atlantic_target.add_resource(atlantic_solar)
atlantic_target.add_resource(atlantic_wind)

independent_strategy_manager = IndependentStrategyManager()
independent_strategy_manager.add_target(pacific_target)
independent_strategy_manager.add_target(atlantic_target)

independent_strategy_manager.set_addl_curtailment({"Pacific": {
"solar": .2, "wind": .5}})

assert independent_strategy_manager.targets["Pacific"].resources[
'solar'].addl_curtailment == .2
assert independent_strategy_manager.targets["Pacific"].resources[
'wind'].addl_curtailment == .5
assert independent_strategy_manager.targets["Atlantic"].resources[
'solar'].addl_curtailment == 0
assert independent_strategy_manager.targets["Atlantic"].resources[
'wind'].addl_curtailment == 0


def test_addl_curtailment_key_error():
with raises(KeyError):
atlantic_target = TargetManager('Atlantic', 0.4, 'clean',
300000 * 1000)

independent_strategy_manager = IndependentStrategyManager()
independent_strategy_manager.add_target(atlantic_target)

independent_strategy_manager.set_addl_curtailment({"Texas": {
"solar": .2, "wind": .5}})

0 comments on commit 17d4393

Please sign in to comment.