NREL-reV 0.8.7__py3-none-any.whl → 0.8.9__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.
- {NREL_reV-0.8.7.dist-info → NREL_reV-0.8.9.dist-info}/METADATA +12 -10
- {NREL_reV-0.8.7.dist-info → NREL_reV-0.8.9.dist-info}/RECORD +38 -38
- {NREL_reV-0.8.7.dist-info → NREL_reV-0.8.9.dist-info}/WHEEL +1 -1
- reV/SAM/SAM.py +182 -133
- reV/SAM/econ.py +18 -14
- reV/SAM/generation.py +608 -419
- reV/SAM/windbos.py +93 -79
- reV/bespoke/bespoke.py +690 -445
- reV/bespoke/place_turbines.py +6 -6
- reV/config/project_points.py +220 -140
- reV/econ/econ.py +165 -113
- reV/econ/economies_of_scale.py +57 -34
- reV/generation/base.py +310 -183
- reV/generation/generation.py +298 -190
- reV/handlers/exclusions.py +16 -15
- reV/handlers/multi_year.py +12 -9
- reV/handlers/outputs.py +6 -5
- reV/hybrids/hybrid_methods.py +28 -30
- reV/hybrids/hybrids.py +304 -188
- reV/nrwal/nrwal.py +262 -168
- reV/qa_qc/cli_qa_qc.py +14 -10
- reV/qa_qc/qa_qc.py +217 -119
- reV/qa_qc/summary.py +228 -146
- reV/rep_profiles/rep_profiles.py +349 -230
- reV/supply_curve/aggregation.py +349 -188
- reV/supply_curve/competitive_wind_farms.py +90 -48
- reV/supply_curve/exclusions.py +138 -85
- reV/supply_curve/extent.py +75 -50
- reV/supply_curve/points.py +536 -309
- reV/supply_curve/sc_aggregation.py +366 -225
- reV/supply_curve/supply_curve.py +505 -308
- reV/supply_curve/tech_mapping.py +144 -82
- reV/utilities/__init__.py +199 -16
- reV/utilities/pytest_utils.py +8 -4
- reV/version.py +1 -1
- {NREL_reV-0.8.7.dist-info → NREL_reV-0.8.9.dist-info}/LICENSE +0 -0
- {NREL_reV-0.8.7.dist-info → NREL_reV-0.8.9.dist-info}/entry_points.txt +0 -0
- {NREL_reV-0.8.7.dist-info → NREL_reV-0.8.9.dist-info}/top_level.txt +0 -0
reV/handlers/exclusions.py
CHANGED
@@ -2,17 +2,18 @@
|
|
2
2
|
"""
|
3
3
|
Exclusion layers handler
|
4
4
|
"""
|
5
|
-
import logging
|
6
5
|
import json
|
6
|
+
import logging
|
7
|
+
|
7
8
|
import numpy as np
|
9
|
+
from rex.multi_file_resource import MultiFileResource
|
10
|
+
from rex.resource import Resource
|
11
|
+
from rex.utilities.parse_keys import parse_keys
|
8
12
|
|
9
13
|
from reV.utilities.exceptions import HandlerKeyError, MultiFileExclusionError
|
10
14
|
|
11
|
-
from rex.utilities.parse_keys import parse_keys
|
12
|
-
from rex.resource import Resource
|
13
|
-
from rex.multi_file_resource import MultiFileResource
|
14
|
-
|
15
15
|
logger = logging.getLogger(__name__)
|
16
|
+
LATITUDE, LONGITUDE = "latitude", "longitude"
|
16
17
|
|
17
18
|
|
18
19
|
class ExclusionLayers:
|
@@ -81,8 +82,8 @@ class ExclusionLayers:
|
|
81
82
|
|
82
83
|
def _preflight_multi_file(self):
|
83
84
|
"""Run simple multi-file exclusion checks."""
|
84
|
-
lat_shape = self.h5.shapes[
|
85
|
-
lon_shape = self.h5.shapes[
|
85
|
+
lat_shape = self.h5.shapes[LATITUDE]
|
86
|
+
lon_shape = self.h5.shapes[LONGITUDE]
|
86
87
|
for layer in self.layers:
|
87
88
|
lshape = self.h5.shapes[layer]
|
88
89
|
lshape = lshape[1:] if len(lshape) > 2 else lshape
|
@@ -231,7 +232,7 @@ class ExclusionLayers:
|
|
231
232
|
"""
|
232
233
|
shape = self.h5.attrs.get('shape', None)
|
233
234
|
if shape is None:
|
234
|
-
shape = self.h5.shapes[
|
235
|
+
shape = self.h5.shapes[LATITUDE]
|
235
236
|
|
236
237
|
return tuple(shape)
|
237
238
|
|
@@ -247,7 +248,7 @@ class ExclusionLayers:
|
|
247
248
|
"""
|
248
249
|
chunks = self.h5.attrs.get('chunks', None)
|
249
250
|
if chunks is None:
|
250
|
-
chunks = self.h5.chunks[
|
251
|
+
chunks = self.h5.chunks[LATITUDE]
|
251
252
|
|
252
253
|
return chunks
|
253
254
|
|
@@ -260,7 +261,7 @@ class ExclusionLayers:
|
|
260
261
|
-------
|
261
262
|
ndarray
|
262
263
|
"""
|
263
|
-
return self[
|
264
|
+
return self[LATITUDE]
|
264
265
|
|
265
266
|
@property
|
266
267
|
def longitude(self):
|
@@ -271,7 +272,7 @@ class ExclusionLayers:
|
|
271
272
|
-------
|
272
273
|
ndarray
|
273
274
|
"""
|
274
|
-
return self[
|
275
|
+
return self[LONGITUDE]
|
275
276
|
|
276
277
|
def get_layer_profile(self, layer):
|
277
278
|
"""
|
@@ -384,13 +385,13 @@ class ExclusionLayers:
|
|
384
385
|
lat : ndarray
|
385
386
|
Latitude coordinates
|
386
387
|
"""
|
387
|
-
if
|
388
|
+
if LATITUDE not in self.h5:
|
388
389
|
msg = ('"latitude" is missing from {}'
|
389
390
|
.format(self.h5_file))
|
390
391
|
logger.error(msg)
|
391
392
|
raise HandlerKeyError(msg)
|
392
393
|
|
393
|
-
ds_slice = (
|
394
|
+
ds_slice = (LATITUDE, ) + ds_slice
|
394
395
|
|
395
396
|
lat = self.h5[ds_slice]
|
396
397
|
|
@@ -410,13 +411,13 @@ class ExclusionLayers:
|
|
410
411
|
lon : ndarray
|
411
412
|
Longitude coordinates
|
412
413
|
"""
|
413
|
-
if
|
414
|
+
if LONGITUDE not in self.h5:
|
414
415
|
msg = ('"longitude" is missing from {}'
|
415
416
|
.format(self.h5_file))
|
416
417
|
logger.error(msg)
|
417
418
|
raise HandlerKeyError(msg)
|
418
419
|
|
419
|
-
ds_slice = (
|
420
|
+
ds_slice = (LONGITUDE, ) + ds_slice
|
420
421
|
|
421
422
|
lon = self.h5[ds_slice]
|
422
423
|
|
reV/handlers/multi_year.py
CHANGED
@@ -3,22 +3,25 @@
|
|
3
3
|
Classes to collect reV outputs from multiple annual files.
|
4
4
|
"""
|
5
5
|
import glob
|
6
|
-
import time
|
7
6
|
import logging
|
8
|
-
import numpy as np
|
9
7
|
import os
|
10
|
-
import
|
8
|
+
import time
|
11
9
|
from warnings import warn
|
12
10
|
|
13
|
-
|
14
|
-
|
15
|
-
get_lat_lon_cols)
|
11
|
+
import numpy as np
|
12
|
+
import pandas as pd
|
16
13
|
from gaps.pipeline import parse_previous_status
|
14
|
+
from rex import Resource
|
15
|
+
from rex.utilities.utilities import (
|
16
|
+
get_class_properties,
|
17
|
+
get_lat_lon_cols,
|
18
|
+
parse_year,
|
19
|
+
)
|
17
20
|
|
18
|
-
from reV.handlers.outputs import Outputs
|
19
21
|
from reV.config.output_request import SAMOutputRequest
|
20
|
-
from reV.
|
21
|
-
from reV.utilities import
|
22
|
+
from reV.handlers.outputs import Outputs
|
23
|
+
from reV.utilities import ModuleName, log_versions
|
24
|
+
from reV.utilities.exceptions import ConfigError, HandlerRuntimeError
|
22
25
|
|
23
26
|
logger = logging.getLogger(__name__)
|
24
27
|
|
reV/handlers/outputs.py
CHANGED
@@ -2,15 +2,16 @@
|
|
2
2
|
"""
|
3
3
|
Classes to handle reV h5 output files.
|
4
4
|
"""
|
5
|
+
import json
|
5
6
|
import logging
|
7
|
+
import sys
|
8
|
+
|
6
9
|
import NRWAL
|
7
10
|
import PySAM
|
8
11
|
import rex
|
9
|
-
import
|
10
|
-
import json
|
12
|
+
from rex.outputs import Outputs as rexOutputs
|
11
13
|
|
12
14
|
from reV.version import __version__
|
13
|
-
from rex.outputs import Outputs as rexOutputs
|
14
15
|
|
15
16
|
logger = logging.getLogger(__name__)
|
16
17
|
|
@@ -28,8 +29,8 @@ class Outputs(rexOutputs):
|
|
28
29
|
>>> import pandas as pd
|
29
30
|
>>> import numpy as np
|
30
31
|
>>>
|
31
|
-
>>> meta = pd.DataFrame({
|
32
|
-
>>>
|
32
|
+
>>> meta = pd.DataFrame({SupplyCurveField.LATITUDE: np.ones(100),
|
33
|
+
>>> SupplyCurveField.LONGITUDE: np.ones(100)})
|
33
34
|
>>>
|
34
35
|
>>> time_index = pd.date_range('20210101', '20220101', freq='1h',
|
35
36
|
>>> closed='right')
|
reV/hybrids/hybrid_methods.py
CHANGED
@@ -3,18 +3,12 @@
|
|
3
3
|
|
4
4
|
@author: ppinchuk
|
5
5
|
"""
|
6
|
+
from reV.utilities import SupplyCurveField
|
6
7
|
|
7
8
|
|
8
9
|
def aggregate_solar_capacity(h):
|
9
10
|
"""Compute the total solar capcity allowed in hybridization.
|
10
11
|
|
11
|
-
Note
|
12
|
-
----
|
13
|
-
No limiting is done on the ratio of wind to solar. This method
|
14
|
-
checks for an existing 'hybrid_solar_capacity'. If one does not exist,
|
15
|
-
it is assumed that there is no limit on the solar to wind capacity
|
16
|
-
ratio and the solar capacity is copied into this new column.
|
17
|
-
|
18
12
|
Parameters
|
19
13
|
----------
|
20
14
|
h : `reV.hybrids.Hybridization`
|
@@ -26,27 +20,25 @@ def aggregate_solar_capacity(h):
|
|
26
20
|
-------
|
27
21
|
data : Series | None
|
28
22
|
A series of data containing the capacity allowed in the hybrid
|
29
|
-
capacity sum, or `None` if 'hybrid_solar_capacity' already
|
23
|
+
capacity sum, or `None` if 'hybrid_solar_capacity' already
|
24
|
+
exists.
|
30
25
|
|
31
26
|
Notes
|
32
27
|
-----
|
33
|
-
|
28
|
+
No limiting is done on the ratio of wind to solar. This method
|
29
|
+
checks for an existing 'hybrid_solar_capacity'. If one does not
|
30
|
+
exist, it is assumed that there is no limit on the solar to wind
|
31
|
+
capacity ratio and the solar capacity is copied into this new
|
32
|
+
column.
|
34
33
|
"""
|
35
|
-
if '
|
34
|
+
if f'hybrid_solar_{SupplyCurveField.CAPACITY}' in h.hybrid_meta:
|
36
35
|
return None
|
37
|
-
return h.hybrid_meta['
|
36
|
+
return h.hybrid_meta[f'solar_{SupplyCurveField.CAPACITY}']
|
38
37
|
|
39
38
|
|
40
39
|
def aggregate_wind_capacity(h):
|
41
40
|
"""Compute the total wind capcity allowed in hybridization.
|
42
41
|
|
43
|
-
Note
|
44
|
-
----
|
45
|
-
No limiting is done on the ratio of wind to solar. This method
|
46
|
-
checks for an existing 'hybrid_wind_capacity'. If one does not exist,
|
47
|
-
it is assumed that there is no limit on the solar to wind capacity
|
48
|
-
ratio and the wind capacity is copied into this new column.
|
49
|
-
|
50
42
|
Parameters
|
51
43
|
----------
|
52
44
|
h : `reV.hybrids.Hybridization`
|
@@ -58,15 +50,19 @@ def aggregate_wind_capacity(h):
|
|
58
50
|
-------
|
59
51
|
data : Series | None
|
60
52
|
A series of data containing the capacity allowed in the hybrid
|
61
|
-
capacity sum, or `None` if 'hybrid_solar_capacity' already
|
53
|
+
capacity sum, or `None` if 'hybrid_solar_capacity' already
|
54
|
+
exists.
|
62
55
|
|
63
56
|
Notes
|
64
57
|
-----
|
65
|
-
|
58
|
+
No limiting is done on the ratio of wind to solar. This method
|
59
|
+
checks for an existing 'hybrid_wind_capacity'. If one does not
|
60
|
+
exist, it is assumed that there is no limit on the solar to wind
|
61
|
+
capacity ratio and the wind capacity is copied into this new column.
|
66
62
|
"""
|
67
|
-
if '
|
63
|
+
if f'hybrid_wind_{SupplyCurveField.CAPACITY}' in h.hybrid_meta:
|
68
64
|
return None
|
69
|
-
return h.hybrid_meta['
|
65
|
+
return h.hybrid_meta[f'wind_{SupplyCurveField.CAPACITY}']
|
70
66
|
|
71
67
|
|
72
68
|
def aggregate_capacity(h):
|
@@ -85,8 +81,8 @@ def aggregate_capacity(h):
|
|
85
81
|
A series of data containing the aggregated capacity, or `None`
|
86
82
|
if the capacity columns are missing.
|
87
83
|
"""
|
88
|
-
|
89
|
-
|
84
|
+
sc = f'hybrid_solar_{SupplyCurveField.CAPACITY}'
|
85
|
+
wc = f'hybrid_wind_{SupplyCurveField.CAPACITY}'
|
90
86
|
missing_solar_cap = sc not in h.hybrid_meta.columns
|
91
87
|
missing_wind_cap = wc not in h.hybrid_meta.columns
|
92
88
|
if missing_solar_cap or missing_wind_cap:
|
@@ -113,8 +109,10 @@ def aggregate_capacity_factor(h):
|
|
113
109
|
if the capacity and/or mean_cf columns are missing.
|
114
110
|
"""
|
115
111
|
|
116
|
-
sc
|
117
|
-
|
112
|
+
sc = f'hybrid_solar_{SupplyCurveField.CAPACITY}'
|
113
|
+
wc = f'hybrid_wind_{SupplyCurveField.CAPACITY}'
|
114
|
+
scf = f'solar_{SupplyCurveField.MEAN_CF}'
|
115
|
+
wcf = f'wind_{SupplyCurveField.MEAN_CF}'
|
118
116
|
missing_solar_cap = sc not in h.hybrid_meta.columns
|
119
117
|
missing_wind_cap = wc not in h.hybrid_meta.columns
|
120
118
|
missing_solar_mean_cf = scf not in h.hybrid_meta.columns
|
@@ -132,8 +130,8 @@ def aggregate_capacity_factor(h):
|
|
132
130
|
|
133
131
|
|
134
132
|
HYBRID_METHODS = {
|
135
|
-
'
|
136
|
-
'
|
137
|
-
'
|
138
|
-
'
|
133
|
+
f'hybrid_solar_{SupplyCurveField.CAPACITY}': aggregate_solar_capacity,
|
134
|
+
f'hybrid_wind_{SupplyCurveField.CAPACITY}': aggregate_wind_capacity,
|
135
|
+
f'hybrid_{SupplyCurveField.CAPACITY}': aggregate_capacity,
|
136
|
+
f'hybrid_{SupplyCurveField.MEAN_CF}': aggregate_capacity_factor
|
139
137
|
}
|