Source code for reV.config.curtailment

# -*- coding: utf-8 -*-
"""
reV config for curtailment inputs.

Created on Mon Jan 28 11:43:27 2019

@author: gbuster
"""
import logging
from rex.utilities import check_eval_str
from gaps.config import load_config
from reV.config.base_config import BaseConfig

logger = logging.getLogger(__name__)


[docs]class Curtailment(BaseConfig): """Config for generation curtailment.""" def __init__(self, curtailment_parameters): """ Parameters ---------- curtailment_parameters : str | dict Configuration json file (with path) containing curtailment information. Could also be a pre-extracted curtailment config dictionary (the contents of the curtailment json). """ if isinstance(curtailment_parameters, str): # received json, extract to dictionary curtailment_parameters = load_config(curtailment_parameters) # intialize config object with curtailment parameters super().__init__(curtailment_parameters) @property def wind_speed(self): """Get the wind speed threshold below which curtailment is possible. Returns ------- _wind_speed : float | None Wind speed threshold below which curtailment is possible. """ return self.get('wind_speed', None) @property def dawn_dusk(self): """Get the solar zenith angle that signifies dawn and dusk. Returns ------- _dawn_dusk : float Solar zenith angle at dawn and dusk. Default is nautical, 12 degrees below the horizon (sza=102). """ # preset commonly used dawn/dusk values in solar zenith angles. presets = {'nautical': 102.0, 'astronomical': 108.0, 'civil': 96.0} # set a default value dd = presets['nautical'] if 'dawn_dusk' in self: if isinstance(self['dawn_dusk'], str): # Use a pre-set dawn/dusk dd = presets[self['dawn_dusk']] if isinstance(self['dawn_dusk'], (int, float)): # Use an explicit solar zenith angle dd = float(self['dawn_dusk']) return dd @property def months(self): """Get the months during which curtailment is possible (inclusive). This can be overridden by the date_range input. Returns ------- months : tuple | None Tuple of month integers. These are the months during which curtailment could be in effect. Default is None. """ m = self.get('months', None) if isinstance(m, list): m = tuple(m) return m @property def date_range(self): """Get the date range tuple (start, end) over which curtailment is possible (inclusive, exclusive) ("MMDD", "MMDD"). This overrides the months input. Returns ------- date_range : tuple Two-entry tuple of the starting date (inclusive) and ending date (exclusive) over which curtailment is possible. Input format is a zero-padded string: "MMDD". """ dr = self.get('date_range', None) if dr is not None: msg = 'date_range input needs to be a tuple!' assert isinstance(dr, (list, tuple)), msg msg = 'date_range input needs to have two entries!' assert len(dr) == 2, msg dr = (str(int(dr[0])).zfill(4), str(int(dr[1])).zfill(4)) return dr @property def temperature(self): """Get the temperature (C) over which curtailment is possible. Returns ------- temperature : float | NoneType Temperature over which curtailment is possible. Defaults to None. """ return self.get('temperature', None) @property def precipitation(self): """Get the precip rate (mm/hour) under which curtailment is possible. Returns ------- precipitation : float | NoneType Precipitation rate under which curtailment is possible. This is compared to the WTK resource dataset "precipitationrate_0m" in mm/hour. Defaults to None. """ return self.get('precipitation', None) @property def equation(self): """Get an equation-based curtailment scenario. Returns ------- equation : str A python equation based on other curtailment variables (wind_speed, temperature, precipitation_rate, solar_zenith_angle) that returns a True or False output to signal curtailment. """ eq = self.get('equation', None) if isinstance(eq, str): check_eval_str(eq) return eq @property def probability(self): """Get the probability that curtailment is in-effect if all other screening criteria are met. Returns ------- probability : float Fractional probability that curtailment is in-effect if all other screening criteria are met. Defaults to 1 (curtailment is always in effect if all other criteria are met). """ return float(self.get('probability', 1.0)) @property def random_seed(self): """ Random seed to use for curtailment probability Returns ------- int """ return int(self.get('random_seed', 0))