NREL-reV 0.13.1__py3-none-any.whl → 0.14.1__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.
@@ -16,10 +16,10 @@ from warnings import warn
16
16
 
17
17
  import h5py
18
18
  import numpy as np
19
+ from scipy.spatial import cKDTree
19
20
  from rex.resource import Resource
20
21
  from rex.utilities.execution import SpawnProcessPool
21
- from rex.utilities.utilities import res_dist_threshold
22
- from scipy.spatial import cKDTree
22
+ from rex.utilities.utilities import check_res_file, res_dist_threshold
23
23
 
24
24
  from reV.supply_curve.extent import SupplyCurveExtent, LATITUDE, LONGITUDE
25
25
  from reV.utilities.exceptions import FileInputError, FileInputWarning
@@ -30,36 +30,31 @@ logger = logging.getLogger(__name__)
30
30
  class TechMapping:
31
31
  """Framework to create map between tech layer (exclusions), res, and gen"""
32
32
 
33
- def __init__(
34
- self, excl_fpath, res_fpath, sc_resolution=2560, dist_margin=1.05
35
- ):
33
+ def __init__(self, excl_fpath, sc_resolution=1200):
36
34
  """
37
35
  Parameters
38
36
  ----------
39
37
  excl_fpath : str
40
38
  Filepath to exclusions h5 file, must contain latitude and longitude
41
39
  arrays to allow for mapping to resource points
42
- res_fpath : str
43
- Filepath to .h5 resource file that we're mapping to.
44
40
  sc_resolution : int | None, optional
45
- Supply curve resolution, does not affect the exclusion to resource
46
- (tech) mapping, but defines how many exclusion pixels are mapped
47
- at a time, by default 2560
48
- dist_margin : float, optional
49
- Extra margin to multiply times the computed distance between
50
- neighboring resource points, by default 1.05
41
+ Defines how many exclusion pixels are mapped at a time. Units
42
+ indicate the length of one dimension, in pixels, of each square
43
+ chunk to be mapped. By default, this value is 1200, which will
44
+ map the exclusion pixels in 1200x1200 pixel chunks.
45
+
46
+ .. Note:: This parameter does not affect the exclusion to resource
47
+ (tech) mapping, which deviates from how the effect of the
48
+ ``sc_resolution`` parameter works in other functionality within
49
+ ``reV``.
50
+
51
51
  """
52
52
  self._excl_fpath = excl_fpath
53
53
  self._check_fout()
54
54
 
55
- self._tree, self._dist_thresh = self._build_tree(
56
- res_fpath, dist_margin=dist_margin
57
- )
58
-
59
55
  with SupplyCurveExtent(
60
56
  self._excl_fpath, resolution=sc_resolution
61
57
  ) as sc:
62
- self._sc_resolution = sc.resolution
63
58
  self._gids = np.array(list(range(len(sc))), dtype=np.uint32)
64
59
  self._excl_shape = sc.exclusions.shape
65
60
  self._n_excl = np.prod(self._excl_shape)
@@ -74,19 +69,6 @@ class TechMapping:
74
69
  )
75
70
  )
76
71
 
77
- @property
78
- def distance_threshold(self):
79
- """Get the upper bound on NN distance between excl and res points.
80
-
81
- Returns
82
- -------
83
- float
84
- Estimate the distance between resource points. Calculated as half
85
- of the diagonal between closest resource points, with desired
86
- extra margin
87
- """
88
- return self._dist_thresh
89
-
90
72
  @staticmethod
91
73
  def _build_tree(res_fpath, dist_margin=1.05):
92
74
  """
@@ -110,7 +92,8 @@ class TechMapping:
110
92
  of the diagonal between closest resource points, with desired
111
93
  extra margin
112
94
  """
113
- with Resource(res_fpath) as f:
95
+ __, hsds = check_res_file(res_fpath)
96
+ with Resource(res_fpath, hsds=hsds) as f:
114
97
  lat_lons = f.lat_lon
115
98
 
116
99
  # pylint: disable=not-callable
@@ -181,16 +164,17 @@ class TechMapping:
181
164
  return row_slice, col_slice
182
165
 
183
166
  @classmethod
184
- def _get_excl_coords(cls, excl_fpath, gids, sc_row_indices, sc_col_indices,
167
+ def _get_excl_coords(cls, excl_fpath, gid, sc_row_indices, sc_col_indices,
185
168
  excl_row_slices, excl_col_slices,
186
169
  coord_labels=(LATITUDE, LONGITUDE)):
187
170
  """
188
- Extract the exclusion coordinates for the desired gids for TechMapping.
171
+ Extract the exclusion coordinates for the desired supply curve point
172
+ gid for TechMapping.
189
173
 
190
174
  Parameters
191
175
  ----------
192
- gids : np.ndarray
193
- Supply curve gids with tech exclusion points to map to the
176
+ gid : int
177
+ Supply curve gid with tech exclusion points to map to the
194
178
  resource meta points.
195
179
  excl_fpath : str
196
180
  Filepath to exclusions h5 file, must contain latitude and longitude
@@ -213,72 +197,50 @@ class TechMapping:
213
197
 
214
198
  Returns
215
199
  -------
216
- coords_out : list
217
- List of arrays of the un-projected latitude, longitude array of
218
- tech exclusion points. List entries correspond to input gids.
200
+ coords_out : ndarray
201
+ 2D array (Nx2) of the un-projected latitude, longitude of
202
+ tech exclusion pixels within the specified gid point. Rows
203
+ correspond to exclusion pixels of the specified gid, columns
204
+ correspond to latitude and longitude, respectively.
219
205
  """
220
- coords_out = []
221
206
  with h5py.File(excl_fpath, "r") as f:
222
- for gid in gids:
223
- row_slice, col_slice = cls._get_excl_slices(
224
- gid,
225
- sc_row_indices,
226
- sc_col_indices,
227
- excl_row_slices,
228
- excl_col_slices,
207
+ row_slice, col_slice = cls._get_excl_slices(
208
+ gid,
209
+ sc_row_indices,
210
+ sc_col_indices,
211
+ excl_row_slices,
212
+ excl_col_slices,
213
+ )
214
+ try:
215
+ lats = f[coord_labels[0]][row_slice, col_slice]
216
+ lons = f[coord_labels[1]][row_slice, col_slice]
217
+ coords_out = np.vstack((lats.flatten(), lons.flatten())).T
218
+ except Exception as e:
219
+ m = (
220
+ "Could not unpack coordinates for gid {} with "
221
+ "row/col slice {}/{}. Received the following "
222
+ "error:\n{}".format(gid, row_slice, col_slice, e)
229
223
  )
230
- try:
231
- lats = f[coord_labels[0]][row_slice, col_slice]
232
- lons = f[coord_labels[1]][row_slice, col_slice]
233
- emeta = np.vstack((lats.flatten(), lons.flatten())).T
234
- except Exception as e:
235
- m = (
236
- "Could not unpack coordinates for gid {} with "
237
- "row/col slice {}/{}. Received the following "
238
- "error:\n{}".format(gid, row_slice, col_slice, e)
239
- )
240
- logger.error(m)
241
- raise e
242
-
243
- coords_out.append(emeta)
224
+ logger.error(m)
225
+ raise e
244
226
 
245
227
  return coords_out
246
228
 
247
229
  @classmethod
248
230
  def map_resource_gids(
249
231
  cls,
250
- gids,
251
- excl_fpath,
252
- sc_row_indices,
253
- sc_col_indices,
254
- excl_row_slices,
255
- excl_col_slices,
232
+ excl_coords,
256
233
  tree,
257
234
  dist_thresh,
258
235
  ):
259
- """Map exclusion gids to the resource meta.
236
+ """Map exclusion pixels to the resource meta.
260
237
 
261
238
  Parameters
262
239
  ----------
263
- gids : np.ndarray
264
- Supply curve gids with tech exclusion points to map to the
265
- resource meta points.
266
- excl_fpath : str
267
- Filepath to exclusions h5 file, must contain latitude and longitude
268
- arrays to allow for mapping to resource points
269
- sc_row_indices : list
270
- List of row indices in exclusion array for for every sc_point gid
271
- sc_col_indices : list
272
- List of column indices in exclusion array for for every sc_point
273
- gid
274
- excl_row_slices : list
275
- List representing the supply curve points rows. Each list entry
276
- contains the exclusion row slice that are included in the sc
277
- point.
278
- excl_col_slices : list
279
- List representing the supply curve points columns. Each list entry
280
- contains the exclusion columns slice that are included in the sc
281
- point.
240
+ excl_coords : ndarray
241
+ 2D Array of the un-projected latitude, longitude array of
242
+ tech exclusion pixels. Rows correspond to exclusion pixels,
243
+ columns correspond to latitude and longitude, respectively.
282
244
  tree : cKDTree
283
245
  cKDTree built from resource lat, lon coordinates
284
246
  dist_tresh : float
@@ -288,100 +250,51 @@ class TechMapping:
288
250
 
289
251
  Returns
290
252
  -------
291
- ind : list
292
- List of arrays of index values from the NN. List entries correspond
293
- to input gids.
253
+ ind : ndarray
254
+ 1D arrays of index values from the NN. Entries correspond
255
+ to input exclusion pixels.
294
256
  """
295
- logger.debug(
296
- "Getting tech map coordinates for chunks {} through {}".format(
297
- gids[0], gids[-1]
298
- )
299
- )
300
- ind_out = []
301
- coords_out = cls._get_excl_coords(
302
- excl_fpath,
303
- gids,
304
- sc_row_indices,
305
- sc_col_indices,
306
- excl_row_slices,
307
- excl_col_slices,
308
- )
257
+ dist, ind = tree.query(excl_coords)
258
+ ind[(dist >= dist_thresh)] = -1
309
259
 
310
- logger.debug(
311
- "Running tech mapping for chunks {} through {}".format(
312
- gids[0], gids[-1]
313
- )
314
- )
315
- for i, _ in enumerate(gids):
316
- dist, ind = tree.query(coords_out[i])
317
- ind[(dist >= dist_thresh)] = -1
318
- ind_out.append(ind)
260
+ return ind
319
261
 
320
- return ind_out
321
-
322
- @staticmethod
323
- def save_tech_map(
324
- excl_fpath,
325
- dset,
326
- indices,
327
- distance_threshold=None,
328
- res_fpath=None,
329
- chunks=(128, 128),
330
- ):
331
- """Save tech mapping indices and coordinates to an h5 output file.
262
+ def initialize_dataset(self, dset, chunks=(128, 128)):
263
+ """
264
+ Initialize output dataset in exclusions h5 file. If dataset already
265
+ exists, a warning will be issued.
332
266
 
333
267
  Parameters
334
268
  ----------
335
- excl_fpath : str
336
- Filepath to exclusions h5 file to add techmap to as 'dset'
337
269
  dset : str
338
- Dataset name in fpath_out to save mapping results to.
339
- indices : np.ndarray
340
- Index values of the NN resource point. -1 if no res point found.
341
- 2D integer array with shape equal to the exclusions extent shape.
342
- distance_threshold : float
343
- Distance upper bound to save as attr.
344
- res_fpath : str, optional
345
- Filepath to .h5 resource file that we're mapping to,
346
- by default None
347
- chunks : tuple
348
- Chunk shape of the 2D output datasets.
270
+ Name of the dataset in the exclusions H5 file to create.
271
+ chunks : tuple, optional
272
+ Chunk size for the dataset, by default (128, 128).
349
273
  """
350
- logger.info('Writing tech map "{}" to {}'.format(dset, excl_fpath))
351
274
 
352
- shape = indices.shape
353
- chunks = (np.min((shape[0], chunks[0])), np.min((shape[1], chunks[1])))
354
-
355
- with h5py.File(excl_fpath, "a") as f:
275
+ with h5py.File(self._excl_fpath, "a") as f:
356
276
  if dset in list(f):
357
277
  wmsg = (
358
- 'TechMap results dataset "{}" is being replaced '
278
+ 'TechMap results dataset "{}" already exists '
359
279
  'in pre-existing Exclusions TechMapping file "{}"'.format(
360
- dset, excl_fpath
280
+ dset, self._excl_fpath
361
281
  )
362
282
  )
363
283
  logger.warning(wmsg)
364
284
  warn(wmsg, FileInputWarning)
365
- f[dset][...] = indices
366
285
  else:
286
+ logger.info(
287
+ f"Initializing tech map dataset {dset} in "
288
+ f"{self._excl_fpath}"
289
+ )
367
290
  f.create_dataset(
368
291
  dset,
369
- shape=shape,
370
- dtype=indices.dtype,
371
- data=indices,
292
+ shape=self._excl_shape,
293
+ dtype=np.int32,
372
294
  chunks=chunks,
295
+ fillvalue=-1
373
296
  )
374
297
 
375
- if distance_threshold:
376
- f[dset].attrs["distance_threshold"] = distance_threshold
377
-
378
- if res_fpath:
379
- f[dset].attrs["src_res_fpath"] = res_fpath
380
-
381
- logger.info(
382
- 'Successfully saved tech map "{}" to {}'.format(dset, excl_fpath)
383
- )
384
-
385
298
  def _check_fout(self):
386
299
  """Check the TechMapping output file for cached data."""
387
300
  with h5py.File(self._excl_fpath, 'r') as f:
@@ -393,134 +306,166 @@ class TechMapping:
393
306
  logger.exception(emsg)
394
307
  raise FileInputError(emsg)
395
308
 
396
- def map_resource(self, max_workers=None, points_per_worker=10):
309
+ def map_resource(self, dset, res_fpath, dist_margin=1.05,
310
+ max_workers=None, batch_size=100):
397
311
  """
398
- Map all resource gids to exclusion gids
312
+ Map all resource gids to exclusion gids. Save results to dset in
313
+ exclusions h5 file.
399
314
 
400
315
  Parameters
401
316
  ----------
317
+ dset : str, optional
318
+ Name of the output dataset in the exclusions H5 file to which the
319
+ tech map will be saved.
320
+ res_fpath : str
321
+ Filepath to .h5 resource file that we're mapping to.
322
+ dist_margin : float, optional
323
+ Extra margin to multiply times the computed distance between
324
+ neighboring resource points, by default 1.05
402
325
  max_workers : int, optional
403
326
  Number of cores to run mapping on. None uses all available cpus,
404
327
  by default None
405
- points_per_worker : int, optional
406
- Number of supply curve points to map to resource gids on each
407
- worker, by default 10
408
-
409
- Returns
410
- -------
411
- indices : np.ndarray
412
- Index values of the NN resource point. -1 if no res point found.
413
- 2D integer array with shape equal to the exclusions extent shape.
328
+ batch_size : int, optional
329
+ Number of tasks to be submitted to parallel worker pool at one
330
+ time, by default 1000. As a rule of thumb, this number should be
331
+ set to ~10x the number of max_workers. Higher values are not
332
+ necessarily better, and may slow down processing and/or result in
333
+ out-of-memory errors. Values less than the number of workers can
334
+ also lead to slower processing, due to poor load balancing.
414
335
  """
415
- gid_chunks = ceil(len(self._gids) / points_per_worker)
416
- gid_chunks = np.array_split(self._gids, gid_chunks)
336
+ loggers = [__name__, "reV"]
417
337
 
418
- # init full output arrays
419
- indices = -1 * np.ones((self._n_excl,), dtype=np.int32)
420
- iarr = self._make_excl_iarr(self._excl_shape)
338
+ logger.info(
339
+ f"Computing cKDtree for tech mapping using {res_fpath=!r} "
340
+ f"and {dist_margin=!r}"
341
+ )
342
+ tree, dist_thresh = self._build_tree(
343
+ res_fpath, dist_margin=dist_margin
344
+ )
345
+ with h5py.File(self._excl_fpath, "a") as f:
346
+ f[dset].attrs["distance_threshold"] = dist_thresh
347
+ f[dset].attrs["src_res_fpath"] = res_fpath
421
348
 
422
- futures = {}
423
- loggers = [__name__, "reV"]
349
+ n_jobs = len(self._gids)
350
+ n_batches = ceil(n_jobs / batch_size)
351
+ gid_batches = np.array_split(self._gids, n_batches)
352
+
353
+ logger.info(
354
+ f"Kicking off {n_jobs} resource mapping jobs in {n_batches} "
355
+ "batches."
356
+ )
357
+ n_finished = 0
424
358
  with SpawnProcessPool(max_workers=max_workers, loggers=loggers) as exe:
425
- # iterate through split executions, submitting each to worker
426
- for i, gid_set in enumerate(gid_chunks):
427
- # submit executions and append to futures list
428
- futures[
429
- exe.submit(
430
- self.map_resource_gids,
431
- gid_set,
359
+ for gid_batch in gid_batches:
360
+ futures = {}
361
+ # iterate through split executions, submitting each to worker
362
+ for i, gid in enumerate(gid_batch):
363
+ # submit executions and append to futures list
364
+ excl_coords = self._get_excl_coords(
432
365
  self._excl_fpath,
366
+ gid,
433
367
  self._sc_row_indices,
434
368
  self._sc_col_indices,
435
369
  self._excl_row_slices,
436
370
  self._excl_col_slices,
437
- self._tree,
438
- self.distance_threshold,
439
371
  )
440
- ] = i
372
+ futures[
373
+ exe.submit(
374
+ self.map_resource_gids,
375
+ excl_coords,
376
+ tree,
377
+ dist_thresh,
378
+ )
379
+ ] = i
380
+
381
+ with h5py.File(self._excl_fpath, "a") as f:
382
+ indices = f[dset]
383
+ for future in as_completed(futures):
384
+ i = futures[future]
385
+ result = future.result()
386
+
387
+ gid = gid_batch[i]
388
+ row_slice, col_slice = self._get_excl_slices(
389
+ gid,
390
+ self._sc_row_indices,
391
+ self._sc_col_indices,
392
+ self._excl_row_slices,
393
+ self._excl_col_slices,
394
+ )
395
+ n_rows = row_slice.stop - row_slice.start
396
+ n_cols = col_slice.stop - col_slice.start
397
+ result_shape = (n_rows, n_cols)
398
+ indices[row_slice, col_slice] = result.reshape(
399
+ result_shape
400
+ )
441
401
 
442
- n_finished = 0
443
- for future in as_completed(futures):
444
402
  n_finished += 1
445
403
  logger.info(
446
- "Parallel TechMapping futures collected: "
447
- "{} out of {}".format(n_finished, len(futures))
404
+ "Parallel TechMapping batches completed: "
405
+ f"{n_finished} out of {n_batches}"
448
406
  )
449
407
 
450
- i = futures[future]
451
- result = future.result()
452
-
453
- for j, gid in enumerate(gid_chunks[i]):
454
- row_slice, col_slice = self._get_excl_slices(
455
- gid,
456
- self._sc_row_indices,
457
- self._sc_col_indices,
458
- self._excl_row_slices,
459
- self._excl_col_slices,
460
- )
461
- ind_slice = iarr[row_slice, col_slice].flatten()
462
- indices[ind_slice] = result[j]
463
-
464
- indices = indices.reshape(self._excl_shape)
465
-
466
- return indices
467
-
468
408
  @classmethod
469
409
  def run(
470
410
  cls,
471
411
  excl_fpath,
472
412
  res_fpath,
473
- dset=None,
474
- sc_resolution=2560,
413
+ dset,
414
+ sc_resolution=1200,
475
415
  dist_margin=1.05,
476
416
  max_workers=None,
477
- points_per_worker=10,
417
+ batch_size=1000,
478
418
  ):
479
419
  """Run parallel mapping and save to h5 file.
480
420
 
481
421
  Parameters
482
422
  ----------
483
423
  excl_fpath : str
484
- Filepath to exclusions h5 (tech layer). dset will be
485
- created in excl_fpath.
424
+ Filepath to exclusions data HDF5 file. This file must must contain
425
+ latitude and longitude datasets.
486
426
  res_fpath : str
487
- Filepath to .h5 resource file that we're mapping to.
488
- dset : str, optional
489
- Dataset name in excl_fpath to save mapping results to, if None
490
- do not save tech_map to excl_fpath, by default None
427
+ Filepath to HDF5 resource file (e.g. WTK or NSRDB) to which
428
+ the exclusions will be mapped. Can refer to a single file (e.g.,
429
+ "/path/to/nsrdb_2024.h5" or a wild-card e.g.,
430
+ "/path/to/nsrdb_{}.h5")
431
+ dset : str
432
+ Dataset name in the `excl_fpath` file to which the the
433
+ techmap (exclusions-to-resource mapping data) will be saved.
434
+
435
+ .. Important:: If this dataset already exists in the h5 file,
436
+ it will be overwritten.
437
+
491
438
  sc_resolution : int | None, optional
492
- Supply curve resolution, does not affect the exclusion to resource
493
- (tech) mapping, but defines how many exclusion pixels are mapped
494
- at a time, by default 2560
439
+ Defines how many exclusion pixels are mapped at a time. Units
440
+ indicate the length of one dimension, in pixels, of each square
441
+ chunk to be mapped. By default, this value is 1200, which will
442
+ map the exclusion pixels in 1200x1200 pixel chunks.
443
+
444
+ .. Note:: This parameter does not affect the exclusion to resource
445
+ (tech) mapping, which deviates from how the effect of the
446
+ ``sc_resolution`` parameter works in other functionality within
447
+ ``reV``.
448
+
495
449
  dist_margin : float, optional
496
450
  Extra margin to multiply times the computed distance between
497
451
  neighboring resource points, by default 1.05
498
452
  max_workers : int, optional
499
453
  Number of cores to run mapping on. None uses all available cpus,
500
454
  by default None
501
- points_per_worker : int, optional
502
- Number of supply curve points to map to resource gids on each
503
- worker, by default 10
504
-
505
- Returns
506
- -------
507
- indices : np.ndarray
508
- Index values of the NN resource point. -1 if no res point found.
509
- 2D integer array with shape equal to the exclusions extent shape.
455
+ batch_size : int, optional
456
+ Number of tasks to be submitted to parallel worker pool at one
457
+ time, by default 1000. As a rule of thumb, this number should be
458
+ set to ~10x the number of max_workers. Higher values are not
459
+ necessarily better, and may slow down processing and/or result in
460
+ out-of-memory errors. Values less than the number of workers can
461
+ also lead to slower processing, due to poor load balancing.
510
462
  """
511
- kwargs = {"dist_margin": dist_margin, "sc_resolution": sc_resolution}
512
- mapper = cls(excl_fpath, res_fpath, **kwargs)
513
- indices = mapper.map_resource(
514
- max_workers=max_workers, points_per_worker=points_per_worker
463
+ mapper = cls(excl_fpath, sc_resolution=sc_resolution)
464
+ mapper.initialize_dataset(dset)
465
+ mapper.map_resource(
466
+ dset=dset,
467
+ res_fpath=res_fpath,
468
+ dist_margin=dist_margin,
469
+ max_workers=max_workers,
470
+ batch_size=batch_size,
515
471
  )
516
-
517
- if dset:
518
- mapper.save_tech_map(
519
- excl_fpath,
520
- dset,
521
- indices,
522
- distance_threshold=mapper.distance_threshold,
523
- res_fpath=res_fpath,
524
- )
525
-
526
- return indices
reV/utilities/__init__.py CHANGED
@@ -149,14 +149,16 @@ class SupplyCurveField(FieldEnum):
149
149
  MEAN_LCOE_FRICTION = "lcoe_friction_usd_per_mwh"
150
150
  RAW_LCOE = "lcoe_raw_usd_per_mwh"
151
151
  EOS_MULT = "multiplier_cc_eos"
152
+ FIXED_EOS_MULT = "multiplier_foc_eos"
153
+ VAR_EOS_MULT = "multiplier_voc_eos"
152
154
  REG_MULT = "multiplier_cc_regional"
153
155
  SC_POINT_ANNUAL_ENERGY_MWH = "annual_energy_site_mwh"
154
- COST_BASE_OCC_USD_PER_AC_MW = "cost_base_occ_usd_per_ac_mw"
155
- COST_SITE_OCC_USD_PER_AC_MW = "cost_site_occ_usd_per_ac_mw"
156
+ COST_BASE_CC_USD_PER_AC_MW = "cost_base_cc_usd_per_ac_mw"
157
+ COST_SITE_CC_USD_PER_AC_MW = "cost_site_cc_usd_per_ac_mw"
156
158
  COST_BASE_FOC_USD_PER_AC_MW = "cost_base_foc_usd_per_ac_mw"
157
159
  COST_SITE_FOC_USD_PER_AC_MW = "cost_site_foc_usd_per_ac_mw"
158
- COST_BASE_VOC_USD_PER_AC_MW = "cost_base_voc_usd_per_ac_mw"
159
- COST_SITE_VOC_USD_PER_AC_MW = "cost_site_voc_usd_per_ac_mw"
160
+ COST_BASE_VOC_USD_PER_AC_MWH = "cost_base_voc_usd_per_ac_mwh"
161
+ COST_SITE_VOC_USD_PER_AC_MWH = "cost_site_voc_usd_per_ac_mwh"
160
162
  FIXED_CHARGE_RATE = "fixed_charge_rate"
161
163
 
162
164
  # Bespoke outputs
@@ -266,6 +268,8 @@ class _LegacySCAliases(Enum):
266
268
  CONVEX_HULL_AREA = "convex_hull_area"
267
269
  CONVEX_HULL_CAPACITY_DENSITY = "convex_hull_capacity_density"
268
270
  FULL_CELL_CAPACITY_DENSITY = "full_cell_capacity_density"
271
+ COST_BASE_CC_USD_PER_AC_MW = "cost_base_occ_usd_per_ac_mw"
272
+ COST_SITE_CC_USD_PER_AC_MW = "cost_site_occ_usd_per_ac_mw"
269
273
 
270
274
 
271
275
  class ModuleName(str, Enum):
@@ -293,6 +297,7 @@ class ModuleName(str, Enum):
293
297
  REP_PROFILES = "rep-profiles"
294
298
  SUPPLY_CURVE = "supply-curve"
295
299
  SUPPLY_CURVE_AGGREGATION = "supply-curve-aggregation"
300
+ TECH_MAPPING = "tech-mapping"
296
301
 
297
302
  def __str__(self):
298
303
  return self.value
reV/version.py CHANGED
@@ -2,4 +2,4 @@
2
2
  reV Version number
3
3
  """
4
4
 
5
- __version__ = "0.13.1"
5
+ __version__ = "0.14.1"