NREL-reV 0.9.7__py3-none-any.whl → 0.12.2__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.9.7.dist-info → nrel_rev-0.12.2.dist-info}/METADATA +28 -32
- {NREL_reV-0.9.7.dist-info → nrel_rev-0.12.2.dist-info}/RECORD +30 -29
- {NREL_reV-0.9.7.dist-info → nrel_rev-0.12.2.dist-info}/WHEEL +1 -1
- {NREL_reV-0.9.7.dist-info → nrel_rev-0.12.2.dist-info}/entry_points.txt +0 -1
- reV/SAM/SAM.py +30 -7
- reV/SAM/defaults/WY Southern-Flat Lands.srw +8765 -0
- reV/SAM/defaults/geothermal.json +27 -16
- reV/SAM/defaults/i_pvwattsv5.json +1 -1
- reV/SAM/defaults.py +3 -19
- reV/SAM/generation.py +18 -52
- reV/bespoke/bespoke.py +39 -81
- reV/bespoke/cli_bespoke.py +0 -2
- reV/bespoke/pack_turbs.py +15 -17
- reV/bespoke/place_turbines.py +2 -25
- reV/config/output_request.py +10 -1
- reV/config/project_points.py +126 -19
- reV/generation/base.py +22 -4
- reV/generation/generation.py +45 -22
- reV/generation/output_attributes/linear_fresnel.json +7 -0
- reV/losses/power_curve.py +3 -0
- reV/losses/scheduled.py +35 -14
- reV/supply_curve/aggregation.py +47 -0
- reV/supply_curve/points.py +54 -0
- reV/supply_curve/sc_aggregation.py +76 -38
- reV/utilities/__init__.py +2 -0
- reV/utilities/_clean_readme.py +28 -0
- reV/utilities/curtailment.py +17 -13
- reV/version.py +1 -1
- reV/bespoke/plotting_functions.py +0 -178
- {NREL_reV-0.9.7.dist-info → nrel_rev-0.12.2.dist-info/licenses}/LICENSE +0 -0
- {NREL_reV-0.9.7.dist-info → nrel_rev-0.12.2.dist-info}/top_level.txt +0 -0
reV/SAM/defaults/geothermal.json
CHANGED
@@ -1,18 +1,23 @@
|
|
1
1
|
{
|
2
2
|
"ui_calculations_only" : 0,
|
3
3
|
"system_use_lifetime_output" : 0,
|
4
|
+
"geotherm_cost_inj_prod_well_ratio" : 0.75,
|
5
|
+
"drilling_success_rate" : 76,
|
6
|
+
"stim_success_rate" : 0,
|
7
|
+
"failed_prod_flow_ratio" : 0.29999999999999999,
|
4
8
|
"file_name" : "./USA AZ Phoenix Sky Harbor Intl Ap (TMY3).csv",
|
5
|
-
|
9
|
+
"resource_potential" : 210,
|
6
10
|
"resource_type" : 0,
|
7
11
|
"resource_temp" : 200,
|
8
12
|
"resource_depth" : 2000,
|
9
|
-
"geothermal_analysis_period" :
|
13
|
+
"geothermal_analysis_period" : 25,
|
10
14
|
"model_choice" : 0,
|
15
|
+
"reservoir_model_inputs" : [ [ 0, 20, 100 ], [ 100, 85.664100000000005, 133.702 ], [ 200, 109.23099999999999, 145.774 ], [ 300, 125.79300000000001, 153.17599999999999 ], [ 400, 138.49600000000001, 158.363 ], [ 500, 148.65600000000001, 162.25800000000001 ], [ 600, 157.00999999999999, 165.316 ], [ 700, 164.02000000000001, 167.79599999999999 ], [ 800, 169.999, 169.857 ], [ 900, 175.16200000000001, 171.595 ], [ 1000, 179.67699999999999, 173.08799999999999 ], [ 2000, 202.05699999999999, 179.34100000000001 ], [ 3000, 214.012, 182.249 ], [ 4000, 221.00299999999999, 183.48400000000001 ], [ 5000, 225.393, 183.88499999999999 ], [ 6000, 228.25200000000001, 183.83000000000001 ], [ 7000, 230.15799999999999, 183.52000000000001 ], [ 8000, 231.42699999999999, 183.06100000000001 ], [ 9000, 232.273, 182.523 ], [ 10000, 232.804, 181.935 ], [ 11611, 233.00700000000001, 180.864 ], [ 13481, 232.952, 179.68700000000001 ], [ 15653, 232.61600000000001, 178.40199999999999 ], [ 18174, 232.018, 177.02500000000001 ], [ 21101, 231.18899999999999, 175.57599999999999 ], [ 24501, 230.154, 174.06899999999999 ], [ 28447, 228.94300000000001, 172.52099999999999 ], [ 33029, 227.58500000000001, 170.95099999999999 ], [ 38350, 226.102, 169.36600000000001 ], [ 44527, 224.52000000000001, 167.78 ], [ 51700, 222.85400000000001, 166.202 ], [ 60028, 221.12200000000001, 164.637 ], [ 69697, 219.34, 163.09100000000001 ], [ 80924, 217.52000000000001, 161.56999999999999 ], [ 93959, 215.672, 160.07900000000001 ], [ 109094, 213.803, 158.61500000000001 ], [ 126667, 211.92500000000001, 157.18600000000001 ], [ 147071, 210.04499999999999, 155.791 ], [ 170762, 208.16900000000001, 154.43100000000001 ], [ 198268, 206.30099999999999, 153.108 ], [ 230206, 204.446, 151.81800000000001 ], [ 267287, 202.60599999999999, 150.56700000000001 ], [ 310342, 200.785, 149.34899999999999 ], [ 360333, 198.98599999999999, 148.167 ], [ 418376, 197.208, 147.018 ], [ 485768, 195.453, 145.904 ], [ 564016, 193.72399999999999, 144.81999999999999 ], [ 654869, 192.02099999999999, 143.77099999999999 ], [ 760356, 190.345, 142.75 ], [ 882835, 188.69499999999999, 141.75999999999999 ], [ 1025040, 187.07300000000001, 140.798 ], [ 1190160, 185.47900000000001, 139.86500000000001 ], [ 1381870, 183.91200000000001, 138.958 ], [ 1604460, 182.374, 138.077 ], [ 1862920, 180.86099999999999, 137.22300000000001 ], [ 2163000, 179.36799999999999, 136.386 ], [ 2511410, 177.898, 135.571 ], [ 2915960, 176.46000000000001, 134.78399999999999 ], [ 3385660, 175.04599999999999, 134.01599999999999 ], [ 3931030, 173.66300000000001, 133.273 ], [ 4564240, 172.30199999999999, 132.54900000000001 ], [ 5299460, 170.97999999999999, 131.84999999999999 ], [ 6153100, 169.667, 131.16399999999999 ], [ 7144250, 168.393, 130.50399999999999 ], [ 8295060, 167.12100000000001, 129.84899999999999 ], [ 9631240, 165.89500000000001, 129.22399999999999 ], [ 11182700, 164.69, 128.614 ], [ 12984000, 163.505, 128.01900000000001 ], [ 15075400, 162.38999999999999, 127.46299999999999 ], [ 17503800, 161.24000000000001, 126.89400000000001 ], [ 20323400, 160.11099999999999, 126.339 ], [ 23597100, 159.00299999999999, 125.798 ], [ 27398100, 157.916, 125.27 ], [ 31811400, 156.84800000000001, 124.75700000000001 ], [ 36935700, 155.80000000000001, 124.256 ], [ 42885300, 154.77000000000001, 123.765 ], [ 49793400, 153.75800000000001, 123.28700000000001 ], [ 57814100, 152.76499999999999, 122.821 ], [ 67126900, 151.78800000000001, 122.366 ], [ 77939800, 150.82900000000001, 121.92100000000001 ], [ 90494500, 149.886, 121.485 ], [ 105071000, 148.959, 121.06 ], [ 121997000, 148.048, 120.646 ], [ 141648000, 147.15100000000001, 120.239 ], [ 164465000, 146.26900000000001, 119.84 ], [ 190957000, 145.40000000000001, 119.45 ], [ 221716000, 144.54499999999999, 119.068 ], [ 257431000, 143.702, 118.69499999999999 ], [ 298898000, 142.87100000000001, 118.328 ], [ 347045000, 142.053, 117.967 ], [ 402948000, 141.233, 117.608 ], [ 467855000, 140.435, 117.26000000000001 ], [ 543218000, 139.64599999999999, 116.919 ], [ 630720000, 138.869, 116.584 ] ],
|
11
16
|
"specified_pump_work_amount" : 0,
|
12
17
|
"nameplate" : 30000,
|
13
18
|
"analysis_type" : 0,
|
14
19
|
"num_wells" : 3,
|
15
|
-
"num_wells_getem" : 4.
|
20
|
+
"num_wells_getem" : 4.0745051952424838,
|
16
21
|
"conversion_type" : 0,
|
17
22
|
"plant_efficiency_input" : 80,
|
18
23
|
"conversion_subtype" : 0,
|
@@ -20,32 +25,35 @@
|
|
20
25
|
"temp_decline_rate" : 0.5,
|
21
26
|
"temp_decline_max" : 30,
|
22
27
|
"dt_prod_well" : 0,
|
23
|
-
|
24
|
-
"wet_bulb_temp" :
|
28
|
+
"prod_well_choice" : 0,
|
29
|
+
"wet_bulb_temp" : 10,
|
30
|
+
"use_weather_file_conditions" : 0,
|
25
31
|
"ambient_pressure" : 14.699999999999999,
|
26
32
|
"well_flow_rate" : 110,
|
27
33
|
"pump_efficiency" : 67.5,
|
28
34
|
"delta_pressure_equip" : 40,
|
29
35
|
"excess_pressure_pump" : 50,
|
30
|
-
"
|
31
|
-
"
|
32
|
-
|
33
|
-
"
|
36
|
+
"geotherm_cost_inj_cost_curve_welltype" : 0,
|
37
|
+
"geotherm_cost_prod_cost_curve_welltype" : 0,
|
38
|
+
"geotherm_cost_inj_cost_curve_welldiam" : 0,
|
39
|
+
"geotherm_cost_prod_cost_curve_welldiam" : 0,
|
34
40
|
"design_temp" : 200,
|
35
41
|
"specify_pump_work" : 0,
|
36
|
-
"rock_thermal_conductivity" :
|
42
|
+
"rock_thermal_conductivity" : 3,
|
37
43
|
"rock_specific_heat" : 950,
|
38
44
|
"rock_density" : 2600,
|
39
45
|
"reservoir_pressure_change_type" : 0,
|
40
|
-
"reservoir_pressure_change" :
|
46
|
+
"reservoir_pressure_change" : 2500,
|
47
|
+
"injectivity_index" : 3000,
|
48
|
+
"exploration_wells_production" : 2,
|
41
49
|
"reservoir_width" : 500,
|
42
50
|
"reservoir_height" : 100,
|
43
51
|
"reservoir_permeability" : 0.050000000000000003,
|
44
52
|
"inj_prod_well_distance" : 1500,
|
45
53
|
"subsurface_water_loss" : 2,
|
46
54
|
"fracture_aperature" : 0.00040000000000000002,
|
47
|
-
|
48
|
-
|
55
|
+
"fracture_length" : 1000,
|
56
|
+
"fracture_spacing" : 50,
|
49
57
|
"fracture_width" : 175,
|
50
58
|
"num_fractures" : 6,
|
51
59
|
"fracture_angle" : 15,
|
@@ -76,7 +84,10 @@
|
|
76
84
|
"hc_ctl8" : 0,
|
77
85
|
"hc_ctl9" : 0,
|
78
86
|
"hybrid_dispatch_schedule" : "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
|
79
|
-
|
80
|
-
|
81
|
-
|
87
|
+
"allow_reservoir_replacements" : 0,
|
88
|
+
"adjust_constant" : 5,
|
89
|
+
"adjust_en_timeindex" : 0,
|
90
|
+
"adjust_en_periods" : 0,
|
91
|
+
"adjust_timeindex" : [ 0, 0, 0, 0, 0, 0, 0 ],
|
92
|
+
"adjust_periods" : [ [ 0, 0, 0 ] ]
|
82
93
|
}
|
reV/SAM/defaults.py
CHANGED
@@ -11,7 +11,6 @@ import PySAM.Pvsamv1 as PySamDetailedPV
|
|
11
11
|
import PySAM.Windpower as PySamWindPower
|
12
12
|
import PySAM.TcsmoltenSalt as PySamCSP
|
13
13
|
import PySAM.Swh as PySamSWH
|
14
|
-
import PySAM.TroughPhysicalProcessHeat as PySamTPPH
|
15
14
|
import PySAM.LinearFresnelDsgIph as PySamLDS
|
16
15
|
import PySAM.Lcoefcr as PySamLCOE
|
17
16
|
import PySAM.Singleowner as PySamSingleOwner
|
@@ -39,7 +38,7 @@ class AbstractDefaultFromConfigFile:
|
|
39
38
|
|
40
39
|
@classmethod
|
41
40
|
def init_default_pysam_obj(cls):
|
42
|
-
"""Initialize a
|
41
|
+
"""Initialize a default PySAM object from a config file."""
|
43
42
|
config_file = os.path.join(DEFAULTSDIR, cls.CONFIG_FILE_NAME)
|
44
43
|
|
45
44
|
# pylint: disable=no-member
|
@@ -48,13 +47,13 @@ class AbstractDefaultFromConfigFile:
|
|
48
47
|
config = json.load(f)
|
49
48
|
|
50
49
|
for k, v in config.items():
|
51
|
-
if '
|
50
|
+
if 'adjust_' in k or 'file' in k:
|
52
51
|
continue
|
53
52
|
if 'geotherm.cost' in k:
|
54
53
|
k = k.replace(".", "_")
|
55
54
|
obj.value(k, v)
|
56
55
|
|
57
|
-
obj.AdjustmentFactors.
|
56
|
+
obj.AdjustmentFactors.adjust_constant = 0.0
|
58
57
|
return obj
|
59
58
|
|
60
59
|
|
@@ -166,21 +165,6 @@ class DefaultSwh:
|
|
166
165
|
return obj
|
167
166
|
|
168
167
|
|
169
|
-
class DefaultTroughPhysicalProcessHeat:
|
170
|
-
"""Class for default parabolic trough process heat"""
|
171
|
-
|
172
|
-
@staticmethod
|
173
|
-
def default():
|
174
|
-
"""Get the default PySAM object"""
|
175
|
-
res_file = os.path.join(DEFAULTSDIR,
|
176
|
-
'USA AZ Phoenix Sky Harbor Intl Ap (TMY3).csv')
|
177
|
-
obj = PySamTPPH.default('PhysicalTroughIPHNone')
|
178
|
-
obj.Weather.file_name = res_file
|
179
|
-
obj.execute()
|
180
|
-
|
181
|
-
return obj
|
182
|
-
|
183
|
-
|
184
168
|
class DefaultLinearFresnelDsgIph:
|
185
169
|
"""Class for default linear direct steam heat"""
|
186
170
|
|
reV/SAM/generation.py
CHANGED
@@ -23,7 +23,6 @@ import PySAM.Pvwattsv7 as PySamPv7
|
|
23
23
|
import PySAM.Pvwattsv8 as PySamPv8
|
24
24
|
import PySAM.Swh as PySamSwh
|
25
25
|
import PySAM.TcsmoltenSalt as PySamCSP
|
26
|
-
import PySAM.TroughPhysicalProcessHeat as PySamTpph
|
27
26
|
import PySAM.Windpower as PySamWindPower
|
28
27
|
|
29
28
|
from reV.losses import PowerCurveLossesMixin, ScheduledLossesMixin
|
@@ -36,7 +35,6 @@ from reV.SAM.defaults import (
|
|
36
35
|
DefaultPvWattsv8,
|
37
36
|
DefaultSwh,
|
38
37
|
DefaultTcsMoltenSalt,
|
39
|
-
DefaultTroughPhysicalProcessHeat,
|
40
38
|
DefaultWindPower,
|
41
39
|
)
|
42
40
|
from reV.SAM.econ import LCOE, SingleOwner
|
@@ -55,6 +53,8 @@ logger = logging.getLogger(__name__)
|
|
55
53
|
class AbstractSamGeneration(RevPySam, ScheduledLossesMixin, ABC):
|
56
54
|
"""Base class for SAM generation simulations."""
|
57
55
|
|
56
|
+
_GEN_KEY = "gen"
|
57
|
+
|
58
58
|
def __init__(
|
59
59
|
self,
|
60
60
|
resource,
|
@@ -365,7 +365,7 @@ class AbstractSamGeneration(RevPySam, ScheduledLossesMixin, ABC):
|
|
365
365
|
1D array of hourly power generation in kW.
|
366
366
|
Datatype is float32 and array length is 8760*time_interval.
|
367
367
|
"""
|
368
|
-
return np.array(self[
|
368
|
+
return np.array(self[self._GEN_KEY], dtype=np.float32)
|
369
369
|
|
370
370
|
def collect_outputs(self, output_lookup=None):
|
371
371
|
"""Collect SAM output_request, convert timeseries outputs to UTC, and
|
@@ -524,12 +524,13 @@ class AbstractSamGeneration(RevPySam, ScheduledLossesMixin, ABC):
|
|
524
524
|
"""
|
525
525
|
# initialize output dictionary
|
526
526
|
out = {}
|
527
|
+
points = points_control.project_points
|
527
528
|
|
528
529
|
# Get the RevPySam resource object
|
529
530
|
resources = RevPySam.get_sam_res(
|
530
531
|
res_file,
|
531
|
-
|
532
|
-
|
532
|
+
points,
|
533
|
+
points.tech,
|
533
534
|
output_request=output_request,
|
534
535
|
gid_map=gid_map,
|
535
536
|
lr_res_file=lr_res_file,
|
@@ -538,14 +539,17 @@ class AbstractSamGeneration(RevPySam, ScheduledLossesMixin, ABC):
|
|
538
539
|
)
|
539
540
|
|
540
541
|
# run resource through curtailment filter if applicable
|
541
|
-
curtailment =
|
542
|
+
curtailment = points.curtailment
|
542
543
|
if curtailment is not None:
|
543
|
-
|
544
|
-
|
545
|
-
|
544
|
+
for curtail_type, curtail_config in curtailment.items():
|
545
|
+
curtail_sites = points.get_sites_from_curtailment(curtail_type)
|
546
|
+
if not curtail_sites:
|
547
|
+
continue
|
548
|
+
resources = curtail(resources, curtail_config, curtail_sites,
|
549
|
+
random_seed=curtail_config.random_seed)
|
546
550
|
|
547
551
|
# iterate through project_points gen_gid values
|
548
|
-
for gen_gid in
|
552
|
+
for gen_gid in points.sites:
|
549
553
|
# Lookup the resource gid if there's a mapping and get the resource
|
550
554
|
# data from the SAMResource object using the res_gid.
|
551
555
|
res_gid = gen_gid if gid_map is None else gid_map[gen_gid]
|
@@ -555,7 +559,7 @@ class AbstractSamGeneration(RevPySam, ScheduledLossesMixin, ABC):
|
|
555
559
|
if drop_leap:
|
556
560
|
site_res_df = cls.drop_leap(site_res_df)
|
557
561
|
|
558
|
-
_, inputs =
|
562
|
+
_, inputs = points[gen_gid]
|
559
563
|
|
560
564
|
# get resource data pass-throughs and resource means
|
561
565
|
res_outs, out_req_cleaned = cls._get_res(
|
@@ -1394,6 +1398,7 @@ class LinearDirectSteam(AbstractSamGenerationFromWeatherFile):
|
|
1394
1398
|
MODULE = "lineardirectsteam"
|
1395
1399
|
PYSAM = PySamLds
|
1396
1400
|
PYSAM_WEATHER_TAG = "file_name"
|
1401
|
+
_GEN_KEY = "gen_heat"
|
1397
1402
|
|
1398
1403
|
def cf_mean(self):
|
1399
1404
|
"""Calculate mean capacity factor (fractional) from SAM.
|
@@ -1422,42 +1427,6 @@ class LinearDirectSteam(AbstractSamGenerationFromWeatherFile):
|
|
1422
1427
|
return DefaultLinearFresnelDsgIph.default()
|
1423
1428
|
|
1424
1429
|
|
1425
|
-
class TroughPhysicalHeat(AbstractSamGenerationFromWeatherFile):
|
1426
|
-
"""
|
1427
|
-
Trough Physical Process Heat generation
|
1428
|
-
"""
|
1429
|
-
|
1430
|
-
MODULE = "troughphysicalheat"
|
1431
|
-
PYSAM = PySamTpph
|
1432
|
-
PYSAM_WEATHER_TAG = "file_name"
|
1433
|
-
|
1434
|
-
def cf_mean(self):
|
1435
|
-
"""Calculate mean capacity factor (fractional) from SAM.
|
1436
|
-
|
1437
|
-
Returns
|
1438
|
-
-------
|
1439
|
-
output : float
|
1440
|
-
Mean capacity factor (fractional).
|
1441
|
-
"""
|
1442
|
-
net_power = (
|
1443
|
-
self["annual_gross_energy"] - self["annual_thermal_consumption"]
|
1444
|
-
) # kW-hr
|
1445
|
-
# q_pb_des is in MW, convert to kW-hr
|
1446
|
-
name_plate = self["q_pb_design"] * 8760 * 1000
|
1447
|
-
|
1448
|
-
return net_power / name_plate
|
1449
|
-
|
1450
|
-
@staticmethod
|
1451
|
-
def default():
|
1452
|
-
"""Get the executed default pysam trough object.
|
1453
|
-
|
1454
|
-
Returns
|
1455
|
-
-------
|
1456
|
-
PySAM.TroughPhysicalProcessHeat
|
1457
|
-
"""
|
1458
|
-
return DefaultTroughPhysicalProcessHeat.default()
|
1459
|
-
|
1460
|
-
|
1461
1430
|
# pylint: disable=line-too-long
|
1462
1431
|
class Geothermal(AbstractSamGenerationFromWeatherFile):
|
1463
1432
|
"""reV-SAM geothermal generation.
|
@@ -1805,11 +1774,8 @@ class Geothermal(AbstractSamGenerationFromWeatherFile):
|
|
1805
1774
|
self["ui_calculations_only"] = 0
|
1806
1775
|
|
1807
1776
|
def _set_costs(self):
|
1808
|
-
"""Set the costs based on
|
1809
|
-
plant_size_kw =
|
1810
|
-
self.sam_sys_inputs["resource_potential"]
|
1811
|
-
/ self._RESOURCE_POTENTIAL_MULT
|
1812
|
-
) * 1000
|
1777
|
+
"""Set the costs based on plant size"""
|
1778
|
+
plant_size_kw = self.sam_sys_inputs["nameplate"]
|
1813
1779
|
|
1814
1780
|
cc_per_kw = self.sam_sys_inputs.pop("capital_cost_per_kw", None)
|
1815
1781
|
if cc_per_kw is not None:
|
reV/bespoke/bespoke.py
CHANGED
@@ -122,6 +122,11 @@ class BespokeMultiPlantData:
|
|
122
122
|
hh: res[f"pressure_{hh}m", :, gids]
|
123
123
|
for hh, gids in self.hh_to_res_gids.items()
|
124
124
|
}
|
125
|
+
if self._pre_load_humidity:
|
126
|
+
self._relative_humidities = {
|
127
|
+
hh: res["relativehumidity_2m", :, gids]
|
128
|
+
for hh, gids in self.hh_to_res_gids.items()
|
129
|
+
}
|
125
130
|
self._time_index = res.time_index
|
126
131
|
if self._pre_load_humidity:
|
127
132
|
self._relative_humidities = {
|
@@ -153,15 +158,12 @@ class BespokeMultiPlantData:
|
|
153
158
|
|
154
159
|
rh = (None if not self._pre_load_humidity
|
155
160
|
else self._relative_humidities[hh][:, data_inds])
|
156
|
-
return BespokeSinglePlantData(
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
self._time_index,
|
163
|
-
rh,
|
164
|
-
)
|
161
|
+
return BespokeSinglePlantData(sc_point_res_gids,
|
162
|
+
self._wind_dirs[hh][:, data_inds],
|
163
|
+
self._wind_speeds[hh][:, data_inds],
|
164
|
+
self._temps[hh][:, data_inds],
|
165
|
+
self._pressures[hh][:, data_inds],
|
166
|
+
self._time_index, rh)
|
165
167
|
|
166
168
|
|
167
169
|
class BespokeSinglePlantData:
|
@@ -172,10 +174,8 @@ class BespokeSinglePlantData:
|
|
172
174
|
reads to a single HDF5 file.
|
173
175
|
"""
|
174
176
|
|
175
|
-
def __init__(
|
176
|
-
|
177
|
-
relative_humidities=None,
|
178
|
-
):
|
177
|
+
def __init__(self, data_inds, wind_dirs, wind_speeds, temps, pressures,
|
178
|
+
time_index, relative_humidities=None):
|
179
179
|
"""Initialize BespokeSinglePlantData
|
180
180
|
|
181
181
|
Parameters
|
@@ -247,37 +247,17 @@ class BespokeSinglePlant:
|
|
247
247
|
DEPENDENCIES = ("shapely",)
|
248
248
|
OUT_ATTRS = copy.deepcopy(Gen.OUT_ATTRS)
|
249
249
|
|
250
|
-
def __init__(
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
balance_of_system_cost_function,
|
262
|
-
min_spacing="5x",
|
263
|
-
wake_loss_multiplier=1,
|
264
|
-
ga_kwargs=None,
|
265
|
-
output_request=("system_capacity", "cf_mean"),
|
266
|
-
ws_bins=(0.0, 20.0, 5.0),
|
267
|
-
wd_bins=(0.0, 360.0, 45.0),
|
268
|
-
excl_dict=None,
|
269
|
-
inclusion_mask=None,
|
270
|
-
data_layers=None,
|
271
|
-
resolution=64,
|
272
|
-
excl_area=None,
|
273
|
-
exclusion_shape=None,
|
274
|
-
eos_mult_baseline_cap_mw=200,
|
275
|
-
prior_meta=None,
|
276
|
-
gid_map=None,
|
277
|
-
bias_correct=None,
|
278
|
-
pre_loaded_data=None,
|
279
|
-
close=True,
|
280
|
-
):
|
250
|
+
def __init__(self, gid, excl, res, tm_dset, sam_sys_inputs,
|
251
|
+
objective_function, capital_cost_function,
|
252
|
+
fixed_operating_cost_function,
|
253
|
+
variable_operating_cost_function,
|
254
|
+
balance_of_system_cost_function, min_spacing='5x',
|
255
|
+
ga_kwargs=None, output_request=('system_capacity', 'cf_mean'),
|
256
|
+
ws_bins=(0.0, 20.0, 5.0), wd_bins=(0.0, 360.0, 45.0),
|
257
|
+
excl_dict=None, inclusion_mask=None, data_layers=None,
|
258
|
+
resolution=64, excl_area=None, exclusion_shape=None,
|
259
|
+
eos_mult_baseline_cap_mw=200, prior_meta=None, gid_map=None,
|
260
|
+
bias_correct=None, pre_loaded_data=None, close=True):
|
281
261
|
"""
|
282
262
|
Parameters
|
283
263
|
----------
|
@@ -353,13 +333,6 @@ class BespokeSinglePlant:
|
|
353
333
|
Minimum spacing between turbines in meters. Can also be a string
|
354
334
|
like "5x" (default) which is interpreted as 5 times the turbine
|
355
335
|
rotor diameter.
|
356
|
-
wake_loss_multiplier : float, optional
|
357
|
-
A multiplier used to scale the annual energy lost due to
|
358
|
-
wake losses.
|
359
|
-
.. WARNING:: This multiplier will ONLY be applied during the
|
360
|
-
optimization process and will NOT be come through in output
|
361
|
-
values such as the hourly profiles,
|
362
|
-
aep, any of the cost functions, or even the output objective.
|
363
336
|
ga_kwargs : dict | None
|
364
337
|
Dictionary of keyword arguments to pass to GA initialization.
|
365
338
|
If `None`, default initialization values are used.
|
@@ -460,9 +433,6 @@ class BespokeSinglePlant:
|
|
460
433
|
"Bespoke objective function: {}".format(objective_function)
|
461
434
|
)
|
462
435
|
logger.debug("Bespoke cost function: {}".format(objective_function))
|
463
|
-
logger.debug(
|
464
|
-
"Bespoke wake loss multiplier: {}".format(wake_loss_multiplier)
|
465
|
-
)
|
466
436
|
logger.debug("Bespoke GA initialization kwargs: {}".format(ga_kwargs))
|
467
437
|
logger.debug(
|
468
438
|
"Bespoke EOS multiplier baseline capacity: {:,} MW".format(
|
@@ -494,7 +464,6 @@ class BespokeSinglePlant:
|
|
494
464
|
)
|
495
465
|
self.balance_of_system_cost_function = balance_of_system_cost_function
|
496
466
|
self.min_spacing = min_spacing
|
497
|
-
self.wake_loss_multiplier = wake_loss_multiplier
|
498
467
|
self.ga_kwargs = ga_kwargs or {}
|
499
468
|
|
500
469
|
self._sam_sys_inputs = sam_sys_inputs
|
@@ -747,6 +716,9 @@ class BespokeSinglePlant:
|
|
747
716
|
mask = self.sc_point._h5_gids == gid
|
748
717
|
weights[i] = self.sc_point.include_mask_flat[mask].sum()
|
749
718
|
|
719
|
+
if "float" not in str(data.dtype):
|
720
|
+
data = data.astype("float32")
|
721
|
+
|
750
722
|
weights /= weights.sum()
|
751
723
|
data = data.astype(np.float32)
|
752
724
|
data *= weights
|
@@ -847,7 +819,12 @@ class BespokeSinglePlant:
|
|
847
819
|
if self._wind_plant_pd is None:
|
848
820
|
return config
|
849
821
|
|
850
|
-
|
822
|
+
layout_config = copy.deepcopy(self._wind_plant_pd.sam_sys_inputs)
|
823
|
+
# `wind_plant_pd` PC may have PC losses applied, so keep the
|
824
|
+
# original PC as to not double count losses here
|
825
|
+
layout_config.pop("wind_turbine_powercurve_powerout", None)
|
826
|
+
config.update(layout_config)
|
827
|
+
|
851
828
|
return config
|
852
829
|
|
853
830
|
@property
|
@@ -1089,9 +1066,7 @@ class BespokeSinglePlant:
|
|
1089
1066
|
self.balance_of_system_cost_function,
|
1090
1067
|
self.include_mask,
|
1091
1068
|
self.pixel_side_length,
|
1092
|
-
self.min_spacing
|
1093
|
-
self.wake_loss_multiplier,
|
1094
|
-
)
|
1069
|
+
self.min_spacing)
|
1095
1070
|
|
1096
1071
|
return self._plant_optm
|
1097
1072
|
|
@@ -1206,7 +1181,7 @@ class BespokeSinglePlant:
|
|
1206
1181
|
ignore=('wind_resource_model_choice',
|
1207
1182
|
'wind_resource_data',
|
1208
1183
|
'wind_turbine_powercurve_powerout',
|
1209
|
-
'
|
1184
|
+
'adjust_hourly',
|
1210
1185
|
'capital_cost',
|
1211
1186
|
'fixed_operating_cost',
|
1212
1187
|
'variable_operating_cost',
|
@@ -1513,8 +1488,8 @@ class BespokeWindPlants(BaseAggregation):
|
|
1513
1488
|
capital_cost_function, fixed_operating_cost_function,
|
1514
1489
|
variable_operating_cost_function,
|
1515
1490
|
balance_of_system_cost_function, project_points,
|
1516
|
-
sam_files, min_spacing='5x',
|
1517
|
-
|
1491
|
+
sam_files, min_spacing='5x', ga_kwargs=None,
|
1492
|
+
output_request=('system_capacity', 'cf_mean'),
|
1518
1493
|
ws_bins=(0.0, 20.0, 5.0), wd_bins=(0.0, 360.0, 45.0),
|
1519
1494
|
excl_dict=None, area_filter_kernel='queen', min_area=None,
|
1520
1495
|
resolution=64, excl_area=None, data_layers=None,
|
@@ -1730,16 +1705,6 @@ class BespokeWindPlants(BaseAggregation):
|
|
1730
1705
|
Minimum spacing between turbines (in meters). This input can
|
1731
1706
|
also be a string like "5x", which is interpreted as 5 times
|
1732
1707
|
the turbine rotor diameter. By default, ``"5x"``.
|
1733
|
-
wake_loss_multiplier : float, optional
|
1734
|
-
A multiplier used to scale the annual energy lost due to
|
1735
|
-
wake losses.
|
1736
|
-
|
1737
|
-
.. WARNING:: This multiplier will ONLY be applied during the
|
1738
|
-
optimization process and will NOT come through in output
|
1739
|
-
values such as the hourly profiles, aep, any of the cost
|
1740
|
-
functions, or even the output objective.
|
1741
|
-
|
1742
|
-
By default, ``1``.
|
1743
1708
|
ga_kwargs : dict, optional
|
1744
1709
|
Dictionary of keyword arguments to pass to GA
|
1745
1710
|
initialization. If ``None``, default initialization values
|
@@ -1973,8 +1938,6 @@ class BespokeWindPlants(BaseAggregation):
|
|
1973
1938
|
.format(variable_operating_cost_function))
|
1974
1939
|
logger.info('Bespoke balance of system cost function: {}'
|
1975
1940
|
.format(balance_of_system_cost_function))
|
1976
|
-
logger.info('Bespoke wake loss multiplier: {}'
|
1977
|
-
.format(wake_loss_multiplier))
|
1978
1941
|
logger.info('Bespoke GA initialization kwargs: {}'.format(ga_kwargs))
|
1979
1942
|
|
1980
1943
|
logger.info(
|
@@ -2012,7 +1975,6 @@ class BespokeWindPlants(BaseAggregation):
|
|
2012
1975
|
self._voc_fun = variable_operating_cost_function
|
2013
1976
|
self._bos_fun = balance_of_system_cost_function
|
2014
1977
|
self._min_spacing = min_spacing
|
2015
|
-
self._wake_loss_multiplier = wake_loss_multiplier
|
2016
1978
|
self._ga_kwargs = ga_kwargs or {}
|
2017
1979
|
self._output_request = SAMOutputRequest(output_request)
|
2018
1980
|
self._ws_bins = ws_bins
|
@@ -2486,8 +2448,8 @@ class BespokeWindPlants(BaseAggregation):
|
|
2486
2448
|
capital_cost_function,
|
2487
2449
|
fixed_operating_cost_function,
|
2488
2450
|
variable_operating_cost_function,
|
2489
|
-
balance_of_system_cost_function,
|
2490
|
-
|
2451
|
+
balance_of_system_cost_function, min_spacing='5x',
|
2452
|
+
ga_kwargs=None,
|
2491
2453
|
output_request=('system_capacity', 'cf_mean'),
|
2492
2454
|
ws_bins=(0.0, 20.0, 5.0), wd_bins=(0.0, 360.0, 45.0),
|
2493
2455
|
excl_dict=None, inclusion_mask=None,
|
@@ -2549,7 +2511,6 @@ class BespokeWindPlants(BaseAggregation):
|
|
2549
2511
|
variable_operating_cost_function,
|
2550
2512
|
balance_of_system_cost_function,
|
2551
2513
|
min_spacing=min_spacing,
|
2552
|
-
wake_loss_multiplier=wake_loss_multiplier,
|
2553
2514
|
ga_kwargs=ga_kwargs,
|
2554
2515
|
output_request=output_request,
|
2555
2516
|
ws_bins=ws_bins,
|
@@ -2638,7 +2599,6 @@ class BespokeWindPlants(BaseAggregation):
|
|
2638
2599
|
self._voc_fun,
|
2639
2600
|
self._bos_fun,
|
2640
2601
|
self._min_spacing,
|
2641
|
-
wake_loss_multiplier=self._wake_loss_multiplier,
|
2642
2602
|
ga_kwargs=self._ga_kwargs,
|
2643
2603
|
output_request=self._output_request,
|
2644
2604
|
ws_bins=self._ws_bins,
|
@@ -2716,7 +2676,6 @@ class BespokeWindPlants(BaseAggregation):
|
|
2716
2676
|
prior_meta = self._get_prior_meta(gid)
|
2717
2677
|
pre_loaded_data = self._pre_loaded_data_for_sc_gid(gid)
|
2718
2678
|
afk = self._area_filter_kernel
|
2719
|
-
wlm = self._wake_loss_multiplier
|
2720
2679
|
i_bc = self._get_bc_for_gid(gid)
|
2721
2680
|
ebc = self._eos_mult_baseline_cap_mw
|
2722
2681
|
|
@@ -2730,7 +2689,6 @@ class BespokeWindPlants(BaseAggregation):
|
|
2730
2689
|
self._voc_fun,
|
2731
2690
|
self._bos_fun,
|
2732
2691
|
min_spacing=self._min_spacing,
|
2733
|
-
wake_loss_multiplier=wlm,
|
2734
2692
|
ga_kwargs=self._ga_kwargs,
|
2735
2693
|
output_request=self._output_request,
|
2736
2694
|
ws_bins=self._ws_bins,
|
reV/bespoke/cli_bespoke.py
CHANGED
@@ -56,8 +56,6 @@ def _log_bespoke_cli_inputs(config):
|
|
56
56
|
.format(config.get("variable_operating_cost_function")))
|
57
57
|
logger.info('Bespoke balance of system cost function: "{}"'
|
58
58
|
.format(config.get("balance_of_system_cost_function")))
|
59
|
-
logger.info('Bespoke wake loss multiplier: "{}"'
|
60
|
-
.format(config.get("wake_loss_multiplier", 1)))
|
61
59
|
logger.info('The following project points were specified: "{}"'
|
62
60
|
.format(config.get('project_points', None)))
|
63
61
|
logger.info('The following SAM configs are available to this run:\n{}'
|
reV/bespoke/pack_turbs.py
CHANGED
@@ -4,10 +4,10 @@ turbine packing module.
|
|
4
4
|
"""
|
5
5
|
import numpy as np
|
6
6
|
from shapely.geometry import Polygon, MultiPolygon, Point
|
7
|
-
from reV.bespoke.plotting_functions import get_xy
|
8
7
|
from reV.utilities.exceptions import WhileLoopPackingError
|
9
8
|
|
10
9
|
|
10
|
+
|
11
11
|
class PackTurbines():
|
12
12
|
"""Framework to maximize plant capacity in a provided wind plant area.
|
13
13
|
"""
|
@@ -81,24 +81,22 @@ class PackTurbines():
|
|
81
81
|
self.turbine_y = np.array([])
|
82
82
|
|
83
83
|
|
84
|
-
def
|
85
|
-
"""
|
86
|
-
|
87
|
-
This function helps break ties in the area of two different
|
88
|
-
geometries using their exterior coordinate values.
|
84
|
+
def get_xy(A):
|
85
|
+
"""separate polygon exterior coordinates to x and y
|
89
86
|
|
90
87
|
Parameters
|
91
88
|
----------
|
92
|
-
|
93
|
-
|
94
|
-
`exterior.coords` coords attribute.
|
89
|
+
A : Polygon.exteroir.coords
|
90
|
+
Exterior coordinates from a shapely Polygon
|
95
91
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
- area of the geometry
|
101
|
-
- minimum exterior coordinate (southwest)
|
102
|
-
- maximum exterior coordinate (northeast)
|
92
|
+
Outputs
|
93
|
+
----------
|
94
|
+
x, y : array
|
95
|
+
Boundary polygon x and y coordinates
|
103
96
|
"""
|
104
|
-
|
97
|
+
x = np.zeros(len(A))
|
98
|
+
y = np.zeros(len(A))
|
99
|
+
for i, _ in enumerate(A):
|
100
|
+
x[i] = A[i][0]
|
101
|
+
y[i] = A[i][1]
|
102
|
+
return x, y
|