NREL-reV 0.8.7__py3-none-any.whl → 0.9.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. {NREL_reV-0.8.7.dist-info → NREL_reV-0.9.0.dist-info}/METADATA +13 -10
  2. {NREL_reV-0.8.7.dist-info → NREL_reV-0.9.0.dist-info}/RECORD +43 -43
  3. {NREL_reV-0.8.7.dist-info → NREL_reV-0.9.0.dist-info}/WHEEL +1 -1
  4. reV/SAM/SAM.py +217 -133
  5. reV/SAM/econ.py +18 -14
  6. reV/SAM/generation.py +611 -422
  7. reV/SAM/windbos.py +93 -79
  8. reV/bespoke/bespoke.py +681 -377
  9. reV/bespoke/cli_bespoke.py +2 -0
  10. reV/bespoke/place_turbines.py +187 -43
  11. reV/config/output_request.py +2 -1
  12. reV/config/project_points.py +218 -140
  13. reV/econ/econ.py +166 -114
  14. reV/econ/economies_of_scale.py +91 -45
  15. reV/generation/base.py +331 -184
  16. reV/generation/generation.py +326 -200
  17. reV/generation/output_attributes/lcoe_fcr_inputs.json +38 -3
  18. reV/handlers/__init__.py +0 -1
  19. reV/handlers/exclusions.py +16 -15
  20. reV/handlers/multi_year.py +57 -26
  21. reV/handlers/outputs.py +6 -5
  22. reV/handlers/transmission.py +44 -27
  23. reV/hybrids/hybrid_methods.py +30 -30
  24. reV/hybrids/hybrids.py +305 -189
  25. reV/nrwal/nrwal.py +262 -168
  26. reV/qa_qc/cli_qa_qc.py +14 -10
  27. reV/qa_qc/qa_qc.py +217 -119
  28. reV/qa_qc/summary.py +228 -146
  29. reV/rep_profiles/rep_profiles.py +349 -230
  30. reV/supply_curve/aggregation.py +349 -188
  31. reV/supply_curve/competitive_wind_farms.py +90 -48
  32. reV/supply_curve/exclusions.py +138 -85
  33. reV/supply_curve/extent.py +75 -50
  34. reV/supply_curve/points.py +735 -390
  35. reV/supply_curve/sc_aggregation.py +357 -248
  36. reV/supply_curve/supply_curve.py +604 -347
  37. reV/supply_curve/tech_mapping.py +144 -82
  38. reV/utilities/__init__.py +274 -16
  39. reV/utilities/pytest_utils.py +8 -4
  40. reV/version.py +1 -1
  41. {NREL_reV-0.8.7.dist-info → NREL_reV-0.9.0.dist-info}/LICENSE +0 -0
  42. {NREL_reV-0.8.7.dist-info → NREL_reV-0.9.0.dist-info}/entry_points.txt +0 -0
  43. {NREL_reV-0.8.7.dist-info → NREL_reV-0.9.0.dist-info}/top_level.txt +0 -0
reV/SAM/windbos.py CHANGED
@@ -1,8 +1,8 @@
1
1
  # -*- coding: utf-8 -*-
2
- """
3
- SAM Wind Balance of System Cost Model
4
- """
2
+ """SAM Wind Balance of System Cost Model"""
3
+
5
4
  from copy import deepcopy
5
+
6
6
  import numpy as np
7
7
  from PySAM.PySSC import ssc_sim_from_dict
8
8
 
@@ -12,45 +12,47 @@ from reV.utilities.exceptions import SAMInputError
12
12
  class WindBos:
13
13
  """Wind Balance of System Cost Model."""
14
14
 
15
- MODULE = 'windbos'
15
+ MODULE = "windbos"
16
16
 
17
17
  # keys for the windbos input data dictionary.
18
18
  # Some keys may not be found explicitly in the SAM input.
19
- KEYS = ('tech_model',
20
- 'financial_model',
21
- 'machine_rating',
22
- 'rotor_diameter',
23
- 'hub_height',
24
- 'number_of_turbines',
25
- 'interconnect_voltage',
26
- 'distance_to_interconnect',
27
- 'site_terrain',
28
- 'turbine_layout',
29
- 'soil_condition',
30
- 'construction_time',
31
- 'om_building_size',
32
- 'quantity_test_met_towers',
33
- 'quantity_permanent_met_towers',
34
- 'weather_delay_days',
35
- 'crane_breakdowns',
36
- 'access_road_entrances',
37
- 'turbine_capital_cost',
38
- 'turbine_cost_per_kw',
39
- 'tower_top_mass',
40
- 'delivery_assist_required',
41
- 'pad_mount_transformer_required',
42
- 'new_switchyard_required',
43
- 'rock_trenching_required',
44
- 'mv_thermal_backfill',
45
- 'mv_overhead_collector',
46
- 'performance_bond',
47
- 'contingency',
48
- 'warranty_management',
49
- 'sales_and_use_tax',
50
- 'overhead',
51
- 'profit_margin',
52
- 'development_fee',
53
- 'turbine_transportation')
19
+ KEYS = (
20
+ "tech_model",
21
+ "financial_model",
22
+ "machine_rating",
23
+ "rotor_diameter",
24
+ "hub_height",
25
+ "number_of_turbines",
26
+ "interconnect_voltage",
27
+ "distance_to_interconnect",
28
+ "site_terrain",
29
+ "turbine_layout",
30
+ "soil_condition",
31
+ "construction_time",
32
+ "om_building_size",
33
+ "quantity_test_met_towers",
34
+ "quantity_permanent_met_towers",
35
+ "weather_delay_days",
36
+ "crane_breakdowns",
37
+ "access_road_entrances",
38
+ "turbine_capital_cost",
39
+ "turbine_cost_per_kw",
40
+ "tower_top_mass",
41
+ "delivery_assist_required",
42
+ "pad_mount_transformer_required",
43
+ "new_switchyard_required",
44
+ "rock_trenching_required",
45
+ "mv_thermal_backfill",
46
+ "mv_overhead_collector",
47
+ "performance_bond",
48
+ "contingency",
49
+ "warranty_management",
50
+ "sales_and_use_tax",
51
+ "overhead",
52
+ "profit_margin",
53
+ "development_fee",
54
+ "turbine_transportation",
55
+ )
54
56
 
55
57
  def __init__(self, inputs):
56
58
  """
@@ -64,14 +66,15 @@ class WindBos:
64
66
  self._datadict = {}
65
67
 
66
68
  self._inputs = inputs
67
- self._special = {'tech_model': 'windbos',
68
- 'financial_model': 'none',
69
- 'machine_rating': self.machine_rating,
70
- 'hub_height': self.hub_height,
71
- 'rotor_diameter': self.rotor_diameter,
72
- 'number_of_turbines': self.number_of_turbines,
73
- 'turbine_capital_cost': self.turbine_capital_cost,
74
- }
69
+ self._special = {
70
+ "tech_model": "windbos",
71
+ "financial_model": "none",
72
+ "machine_rating": self.machine_rating,
73
+ "hub_height": self.hub_height,
74
+ "rotor_diameter": self.rotor_diameter,
75
+ "number_of_turbines": self.number_of_turbines,
76
+ "turbine_capital_cost": self.turbine_capital_cost,
77
+ }
75
78
  self._parse_inputs()
76
79
  self._out = ssc_sim_from_dict(self._datadict)
77
80
 
@@ -83,52 +86,55 @@ class WindBos:
83
86
  if k in self._special:
84
87
  self._datadict[k] = self._special[k]
85
88
  elif k not in self._inputs:
86
- raise SAMInputError('Windbos requires input key: "{}"'
87
- .format(k))
89
+ raise SAMInputError(
90
+ 'Windbos requires input key: "{}"'.format(k)
91
+ )
88
92
  else:
89
93
  self._datadict[k] = self._inputs[k]
90
94
 
91
95
  @property
92
96
  def machine_rating(self):
93
97
  """Single turbine machine rating either from input or power curve."""
94
- if 'machine_rating' in self._inputs:
95
- return self._inputs['machine_rating']
98
+ if "machine_rating" in self._inputs:
99
+ return self._inputs["machine_rating"]
96
100
  else:
97
- return np.max(self._inputs['wind_turbine_powercurve_powerout'])
101
+ return np.max(self._inputs["wind_turbine_powercurve_powerout"])
98
102
 
99
103
  @property
100
104
  def hub_height(self):
101
105
  """Turbine hub height."""
102
- if 'wind_turbine_hub_ht' in self._inputs:
103
- return self._inputs['wind_turbine_hub_ht']
106
+ if "wind_turbine_hub_ht" in self._inputs:
107
+ return self._inputs["wind_turbine_hub_ht"]
104
108
  else:
105
- return self._inputs['hub_height']
109
+ return self._inputs["hub_height"]
106
110
 
107
111
  @property
108
112
  def rotor_diameter(self):
109
113
  """Turbine rotor diameter."""
110
- if 'wind_turbine_rotor_diameter' in self._inputs:
111
- return self._inputs['wind_turbine_rotor_diameter']
114
+ if "wind_turbine_rotor_diameter" in self._inputs:
115
+ return self._inputs["wind_turbine_rotor_diameter"]
112
116
  else:
113
- return self._inputs['rotor_diameter']
117
+ return self._inputs["rotor_diameter"]
114
118
 
115
119
  @property
116
120
  def number_of_turbines(self):
117
121
  """Number of turbines either based on input or system (farm) capacity
118
122
  and machine rating"""
119
123
 
120
- if 'number_of_turbines' in self._inputs:
121
- return self._inputs['number_of_turbines']
124
+ if "number_of_turbines" in self._inputs:
125
+ return self._inputs["number_of_turbines"]
122
126
  else:
123
- return self._inputs['system_capacity'] / self.machine_rating
127
+ return (
128
+ self._inputs['system_capacity'] / self.machine_rating
129
+ )
124
130
 
125
131
  @property
126
132
  def turbine_capital_cost(self):
127
133
  """Returns zero (no turbine capital cost for WindBOS input,
128
134
  and assigns any input turbine_capital_cost to an attr"""
129
135
 
130
- if 'turbine_capital_cost' in self._inputs:
131
- self._turbine_capital_cost = self._inputs['turbine_capital_cost']
136
+ if "turbine_capital_cost" in self._inputs:
137
+ self._turbine_capital_cost = self._inputs["turbine_capital_cost"]
132
138
  else:
133
139
  self._turbine_capital_cost = 0.0
134
140
  return 0.0
@@ -136,23 +142,23 @@ class WindBos:
136
142
  @property
137
143
  def bos_cost(self):
138
144
  """Get the balance of system cost ($)."""
139
- return self._out['project_total_budgeted_cost']
145
+ return self._out["project_total_budgeted_cost"]
140
146
 
141
147
  @property
142
148
  def turbine_cost(self):
143
149
  """Get the turbine cost ($)."""
144
- tcost = ((self._inputs['turbine_cost_per_kw']
145
- * self.machine_rating
146
- * self.number_of_turbines)
147
- + (self._turbine_capital_cost
148
- * self.number_of_turbines))
150
+ tcost = (
151
+ self._inputs["turbine_cost_per_kw"]
152
+ * self.machine_rating
153
+ * self.number_of_turbines
154
+ ) + (self._turbine_capital_cost * self.number_of_turbines)
149
155
  return tcost
150
156
 
151
157
  @property
152
158
  def sales_tax_mult(self):
153
159
  """Get a sales tax multiplier (frac of the total installed cost)."""
154
- basis = self._inputs.get('sales_tax_basis', 0) / 100
155
- tax = self._datadict.get('sales_and_use_tax', 0) / 100
160
+ basis = self._inputs.get("sales_tax_basis", 0) / 100
161
+ tax = self._datadict.get("sales_and_use_tax", 0) / 100
156
162
  return basis * tax
157
163
 
158
164
  @property
@@ -168,16 +174,23 @@ class WindBos:
168
174
  @property
169
175
  def output(self):
170
176
  """Get a dictionary containing the cost breakdown."""
171
- output = {'total_installed_cost': self.total_installed_cost,
172
- 'turbine_cost': self.turbine_cost,
173
- 'sales_tax_cost': self.sales_tax_cost,
174
- 'bos_cost': self.bos_cost}
177
+ output = {
178
+ "total_installed_cost": self.total_installed_cost,
179
+ "turbine_cost": self.turbine_cost,
180
+ "sales_tax_cost": self.sales_tax_cost,
181
+ "bos_cost": self.bos_cost,
182
+ }
175
183
  return output
176
184
 
177
185
  # pylint: disable-msg=W0613
178
186
  @classmethod
179
- def reV_run(cls, points_control, site_df,
180
- output_request=('total_installed_cost',), **kwargs):
187
+ def reV_run(
188
+ cls,
189
+ points_control,
190
+ site_df,
191
+ output_request=("total_installed_cost",),
192
+ **kwargs,
193
+ ):
181
194
  """Execute SAM SingleOwner simulations based on reV points control.
182
195
 
183
196
  Parameters
@@ -216,7 +229,8 @@ class WindBos:
216
229
 
217
230
  wb = cls(site_inputs)
218
231
 
219
- out[site] = {k: v for k, v in wb.output.items()
220
- if k in output_request}
232
+ out[site] = {
233
+ k: v for k, v in wb.output.items() if k in output_request
234
+ }
221
235
 
222
236
  return out