eeco package

Submodules

eeco.costs module

Functions to calculate costs from electricity consumption data.

eeco.costs.add_to_charge_array(charge_dict, key_str, charge_array)[source]

Add to an existing charge array, or an array of all zeros if this charge array does not exist.

This functionality is useful for noncontiguous charges that should be saved under the same key. For example, partial peak hours from 3-5 and 8-10 PM that are billing as a single demand period.

Modifies charge_dict in-place, so nothing is returned.

Parameters:
  • charge_dict (dict of numpy.ndarray) – Dictionary of arrays with keys of the form utility`_`charge_type`_`name`_`start_date`_`end_date`_`charge_limit and values being the $ per kW (electric demand), kWh (electric energy/export), cubic meter / hour (gas demand), cubic meter (gas energy), or $ / month (customer)

  • key_str (str) – The key for the charge array we’d like to modify of the form utility`_`charge_type`_`name`_`start_date`_`end_date`_`charge_limit

  • charge_array (numpy.ndarray) – Value of the charge to add in $ per kW (electric demand), kWh (electric energy/export), cubic meter / hour (gas demand), cubic meter (gas energy), or $ / month (customer)

eeco.costs.build_pyomo_costing(charge_dict, consumption_data_dict, model, electric_consumption_units=<Unit('kilowatt')>, gas_consumption_units=<Unit('meter ** 3 / hour')>, resolution='15m', prev_demand_dict=None, prev_consumption_dict=None, consumption_estimate=0, desired_utility=None, desired_charge_type=None, demand_scale_factor=1, additional_objective_terms=None, varstr_alias_func=<function default_varstr_alias_func>)[source]

Wrapper for calculate_cost to build the cost components into a Pyomo model. An objective function will be created in model.objective.

Parameters:
  • charge_dict (dict) – dictionary of arrays with keys of the form utility`_`charge_type`_`name`_`start_date`_`end_date`_`charge_limit and values being the $ per kW (electric demand), kWh (electric energy/export), cubic meter / hour (gas demand), cubic meter (gas energy), or $ / month (customer)

  • consumption_data_dict (dict) – Baseline electrical and gas usage data as an optimization variable object with keys “electric” and “gas”. Values of the dictionary must be of type numpy.ndarray, cvxpy.Expression, or pyomo.environ.Var

  • model (pyomo.Model) – The model object associated with the problem.

  • electric_consumption_units (pint.Unit) – Units for the electricity consumption data. Default is kW

  • gas_consumption_units (pint.Unit) – Units for the natural gas consumption data. Default is cubic meters / hour

  • resolution (str) – String of the form [int][str] giving the temporal resolution on which charges are assessed, the str portion corresponds to numpy.timedelta64 types for example ‘15m’ specifying demand charges that are applied to 15-minute intervals of electricity consumption

  • prev_demand_dict (dict) – Nested dictionary previous maximmum demand charges with an entry of the form {“cost” : float, “demand” : float} for each charge. Default is None, which results in an a prev_demand and prev_demand_cost of zero for all charges.

  • prev_consumption_dict (dict) – Dictionary of previous total energy consumption with a key for each charge to be used when starting the cost calculation partway into a billing period (e.g., while using a moving horizon that is shorter than a month). Default is None, resulting in an a prev_consumption of zero for all charges.

  • consumption_estimate (float) – Estimate of the total monthly demand or energy consumption from baseline data. Only used when consumption_data is cvxpy.Expression or pyomo.environ.Var for convex relaxation of tiered charges, while numpy.ndarray consumption_data will use actual consumption and ignore the estimate.

  • desired_charge_type (list or str) – Name of desired charge type for itemized costs. Either ‘customer’, ‘energy’, ‘demand’, ‘export’, or a list of charge types. Default is None, meaning that all costs will be summed together.

  • desired_utility (list or str) – Name of desired utility for itemized costs. Either ‘electric’, ‘gas’, or a list of utilities (e.g., [‘electric’, ‘gas’]). Default is None, meaning that all costs will be summed together.

  • demand_scale_factor (float) – Optional factor for scaling demand charges relative to energy charges when the optimization/simulation period is not a full billing cycle. Applied to monthly charges where end_date - start_date > 1 day. Default is 1

  • additional_objective_terms (list) – Additional terms to be added to the objective function. Must be a list of pyomo Expressions.

  • varstr_alias_func (function) – Function to generate variable name for pyomo, should take in a 6 inputs and generate a string output. The function will receive following six inputs:

    • utility: str

    • charge_type: str

    • name: str

    • start_date: str

    • end_date: str

    • charge_limit: str

    Examples of functions:

    f_no_dates=lambda utility, charge_type, name, start_date, end_date, charge_limit: f”{utility}_{charge_type}_{name}_{charge_limit}”

Raises:

ValueError – When invalid utility, charge_type, or assessed is provided in charge_arrays

Returns:

The model object associated with the problem with costing components added.

Return type:

pyomo.Model

eeco.costs.calculate_cost(charge_dict, consumption_data_dict, electric_consumption_units=<Unit('kilowatt')>, gas_consumption_units=<Unit('meter ** 3 / hour')>, resolution='15m', prev_demand_dict=None, prev_consumption_dict=None, consumption_estimate=0, desired_utility=None, desired_charge_type=None, demand_scale_factor=1, model=None, varstr_alias_func=<function default_varstr_alias_func>)[source]

Calculates the cost of given charges (demand or energy) for the given billing rate structure, utility, and consumption information as a cvxpy expression or numpy array

Parameters:
  • charge_dict (dict) – dictionary of arrays with keys of the form utility`_`charge_type`_`name`_`start_date`_`end_date`_`charge_limit and values being the $ per kW (electric demand), kWh (electric energy/export), cubic meter / hour (gas demand), cubic meter (gas energy), or $ / month (customer)

  • consumption_data_dict (dict) – Baseline electrical and gas usage data as an optimization variable object with keys “electric” and “gas”. Values of the dictionary must be of type numpy.ndarray, cvxpy.Expression, or pyomo.environ.Var

  • electric_consumption_units (pint.Unit) – Units for the electricity consumption data. Default is kW

  • gas_consumption_units (pint.Unit) – Units for the natural gas consumption data. Default is cubic meters / hour

  • resolution (str) – String of the form [int][str] giving the temporal resolution on which charges are assessed, the str portion corresponds to numpy.timedelta64 types for example ‘15m’ specifying demand charges that are applied to 15-minute intervals of electricity consumption

  • prev_demand_dict (dict) – Nested dictionary previous maximmum demand charges with an entry of the form {“cost” : float, “demand” : float} for each charge. Default is None, which results in an a prev_demand and prev_demand_cost of zero for all charges.

  • prev_consumption_dict (dict) – Dictionary of previous total energy consumption with a key for each charge to be used when starting the cost calculation partway into a billing period (e.g., while using a moving horizon that is shorter than a month). Default is None, resulting in an a prev_consumption of zero for all charges.

  • consumption_estimate (float, array, dict) – Estimate of the total monthly demand or energy consumption from baseline data. Only used when consumption_data is cvxpy.Expression or pyomo.environ.Var for convex relaxation of tiered charges, while numpy.ndarray consumption_data will use actual consumption and ignore the estimate. If consumption estimate is a float, int, it is assumed to carry units of kWh, therms OR m3. If consumption estimate is array-like it is assumed to carry units of kW, therms/hr OR m3/hr. If consumption estimate is a dict, it should have keys matching the charge dict.

  • desired_charge_type (list or str) – Name of desired charge type for itemized costs. Either ‘customer’, ‘energy’, ‘demand’, ‘export’, or a list of charge types. Default is None, meaning that all costs will be summed together.

  • desired_utility (list or str) – Name of desired utility for itemized costs. Either ‘electric’, ‘gas’, or a list of utilities (e.g., [‘electric’, ‘gas’]). Default is None, meaning that all costs will be summed together.

  • demand_scale_factor (float) – Optional factor for scaling demand charges relative to energy charges when the optimization/simulation period is not a full billing cycle. Applied to monthly charges where end_date - start_date > 1 day. Default is 1

  • model (pyomo.Model) – The model object associated with the problem. Only used in the case of Pyomo, so None by default.

  • additional_objective_terms (pyomo.Expression, list) – Additional terms to be added to the objective function. Can be a single pyomo Expression or a list of pyomo Expressions. Only used in the case of Pyomo, so None by default.

  • varstr_alias_func (function) – Function to generate variable name for pyomo, should take in a 6 inputs and generate a string output. The function will receive following six inputs:

    • utility: str

    • charge_type: str

    • name: str

    • start_date: str

    • end_date: str

    • charge_limit: str

    Examples of functions:

    f_no_dates=lambda utility, charge_type, name, start_date, end_date, charge_limit: f”{utility}_{charge_type}_{name}_{charge_limit}”

Raises:

ValueError – When invalid utility, charge_type, or assessed is provided in charge_arrays

Returns:

tuple with the first entry being a float, cvxpy Expression, or pyomo Var representing energy charge costs in USD for the given charge_array and consumption_data and the second entry being the pyomo model object (or None)

Return type:

(numpy.Array, cvxpy.Expression, or pyomo.environ.Var), pyomo.Model

eeco.costs.calculate_demand_cost(charge_array, consumption_data, limit=0, next_limit=inf, prev_demand=0, prev_demand_cost=0, consumption_estimate=0, scale_factor=1, model=None, varstr='')[source]

Calculates the cost of given demand charges for the given billing rate structure, utility, and consumption information

Parameters:
  • charge_array (array) – Array of charge cost (in $/kW)

  • consumption_data (numpy.ndarray, cvxpy.Expression, or pyomo.environ.Var) – Baseline electrical or gas usage data as an optimization variable object

  • limit (float) – The total consumption, or limit, that this charge came into effect. Default is 0

  • next_limit (float) – The total consumption, or limit, that the next charge comes into effect. Default is float(‘inf’) indicating that there is no higher tier

  • prev_demand (float) – The previous maximum demand for this charge during the same billing period. Only used for optimizing on a horizon shorter than the billing period, so the default is 0

  • prev_demand_cost (float) – The previous cost for this demand charge during the same billing period. Only used for optimizing on a horizon shorter than the billing period, so the default is 0

  • consumption_estimate (float, array) – Estimate of the total consumption from baseline data in kW, therms/hr OR m3/hr. Only used when consumption_data is cvxpy.Expression or pyomo.environ.Var for convex relaxation of tiered charges, while numpy.ndarray consumption_data will use actual consumption and ignore the estimate.

  • scale_factor (float) – Optional factor for scaling demand charges relative to energy charges when the optimization/simulation period is not a full billing cycle. Applied to monthly charges where end_date - start_date > 1 day. Default is 1.

  • model (pyomo.Model) – The model object associated with the problem. Only used in the case of Pyomo, so None by default.

  • varstr (str) – Name of the variable to be created if using a Pyomo model

Returns:

tuple with the first entry being a float, cvxpy Expression, or pyomo Var representing demand charge costs in USD for the given charge_array and consumption_data and the second entry being the pyomo model object (or None)

Return type:

(cvxpy.Expression, pyomo.environ.Var, or float), pyomo.Model

eeco.costs.calculate_energy_cost(charge_array, consumption_data, divisor, limit=0, next_limit=inf, prev_consumption=0, consumption_estimate=0, model=None, varstr='')[source]

Calculates the cost of given energy charges for the given billing rate structure, utility, and consumption information.

Parameters:
  • charge_array (numpy.ndarray) – Array of the charges in $/kWh for electric and $/cubic meter for gas

  • consumption_data (numpy.ndarray cvxpy.Expression, or pyomo.environ.Var) – Baseline electrical or gas usage data as an optimization variable object

  • divisor (int) – Divisor for the energy charges, based on the timeseries resolution

  • limit (float) – The total consumption, or limit, that this charge came into effect. Default is 0

  • next_limit (float) – The total consumption, or limit, that the next charge comes into effect. Default is float(‘inf’) indicating that there is no higher tier

  • prev_consumption (float) – Consumption from within this billing period but outside the horizon window (e.g., previously in the month). Necessary for moving-horizon optimization. Default is 0

  • consumption_estimate (float, array) – Estimate of the total monthly energy consumption from baseline data in kWh, therms, or cubic meters. Only used when consumption_data is cvxpy.Expression or pyomo.environ.Var for convex relaxation of tiered charges, while numpy.ndarray consumption_data will use actual consumption and ignore the estimate.

  • model (pyomo.Model) – The model object associated with the problem. Only used in the case of Pyomo, so None by default.

  • varstr (str) – Name of the variable to be created if using a Pyomo model

Raises:

ValueError – When invalid utility, charge_type, or assessed is provided in charge_arrays

Returns:

tuple with the first entry being a float, cvxpy Expression, or pyomo Var representing energy charge costs in USD for the given charge_array and consumption_data and the second entry being the pyomo model object (or None)

Return type:

(cvxpy.Expression, pyomo.environ.Var, or float), pyomo.Model

eeco.costs.calculate_export_revenues(charge_array, export_data, divisor, model=None, varstr='')[source]

Calculates the export revenues for the given billing rate structure, utility, and consumption information.

Only flat rates for exports are supported (in $ / kWh). Returns positive revenue values that should be subtracted from total cost.

Parameters:
  • charge_array (numpy.ndarray) – array with price per kWh sold back to the grid

  • consumption_data (numpy.ndarray, cvxpy.Expression, or pyomo.environ.Var) – Baseline electrical or gas usage data as an optimization variable object

  • divisor (int) – Divisor for the export revenue, based on the timeseries resolution

  • model (pyomo.Model) – The model object associated with the problem. Only used in the case of Pyomo, so None by default.

  • varstr (str) – Name of the variable to be created if using a Pyomo model

Returns:

tuple with the first entry being a float, cvxpy Expression, or pyomo Var representing export revenues in USD for the given charge_array and consumption_data and the second entry being the pyomo model object (or None)

Return type:

(cvxpy.Expression, pyomo.environ.Var, or float), pyomo.Model

eeco.costs.calculate_itemized_cost(charge_dict, consumption_data_dict, electric_consumption_units=<Unit('kilowatt')>, gas_consumption_units=<Unit('meter ** 3 / hour')>, resolution='15m', prev_demand_dict=None, prev_consumption_dict=None, consumption_estimate=0, desired_utility=None, demand_scale_factor=1, model=None, varstr_alias_func=<function default_varstr_alias_func>)[source]

Calculates itemized costs as a nested dictionary

Parameters:
  • charge_dict (dict) – dictionary of arrays with keys of the form utility`_`charge_type`_`name`_`start_date`_`end_date`_`charge_limit and values being the $ per kW (electric demand), kWh (electric energy/export), cubic meter / hour (gas demand), cubic meter (gas energy), or $ / month (customer)

  • consumption_data_dict (dict) – Baseline electrical and gas usage data as an optimization variable object with keys “electric” and “gas”. Values of the dictionary must be of type numpy.ndarray, cvxpy.Expression, or pyomo.environ.Var

  • electric_consumption_units (pint.Unit) – Units for the electricity consumption data. Default is kW

  • gas_consumption_units (pint.Unit) – Units for the natura gas consumption data. Default is cubic meters / hour

  • resolution (str) – String of the form [int][str] giving the temporal resolution on which charges are assessed, the str portion corresponds to numpy.timedelta64 types for example ‘15m’ specifying demand charges that are applied to 15-minute intervals of electricity consumption

  • prev_demand_dict (dict) – Nested dictionary previous maximmum demand charges with an entry of the form {“cost” : float, “demand” : float} for each charge. Default is None, which results in an a prev_demand and prev_demand_cost of zero for all charges.

  • prev_consumption_dict (dict) – Dictionary of previous total energy consumption with a key for each charge to be used when starting the cost calculation partway into a billing period (e.g., while using a moving horizon that is shorter than a month). Default is None, resulting in an a prev_consumption of zero for all charges.

  • consumption_estimate (float) – Estimate of the total monthly demand or energy consumption from baseline data. Only used when consumption_data is cvxpy.Expression for convex relaxation of tiered charges, while numpy.ndarray consumption_data will use actual consumption and ignore the estimate.

  • demand_scale_factor (float) – Optional factor for scaling demand charges relative to energy charges when the optimization/simulation period is not a full billing cycle. Applied to monthly charges where end_date - start_date > 1 day. Default is 1

  • model (pyomo.Model) – The model object associated with the problem. Only used in the case of Pyomo, so None by default.

Returns:

{

“electric”: {

“customer”: float

”energy”: float

”demand”: float

”export”: float

”total”: float

}

”gas”: {

“customer”: float,

”energy”: float

”demand”: float

”export”: float

”total”: float

}

”total”: float

}

Return type:

dict

eeco.costs.create_charge_array(charge, datetime, effective_start_date, effective_end_date)[source]

Creates a single charge array based on the given parameters.

Parameters:
  • charge (pandas.DataFrame) – data for the charge including columns month_start, month_end, weekday_start, weekday_end, hour_start, hour_end, and charge

  • datetime (pandas.DataFrame, pandas.Series, or numpy.ndarray) – If a pandas Series, it must be of type datetime. If a DataFrame it must have a column “DateTime” and row for each timestep

  • effective_start_date (datetime.datetime) – date on which this charge becomes effective

  • effective_end_date (datetime.datetime) – date at which this charge is no longer in effect (i.e., this day is excluded)

Raises:

TypeError – When datetime is not pandas.DataFrame, pandas.Series, or numpy.ndarray

Returns:

timeseries of the cost of the charge with irrelevant timesteps zeroed out

Return type:

panda.Series

eeco.costs.default_varstr_alias_func(utility, charge_type, name, start_date, end_date, charge_limit)[source]

Default function for creating the variable name strings for each charge in the tariff sheet. Can be overwritten in the function call to calculate_cost to customize variable names.

Parameters:
  • utility (str) – Name of the utility (‘electric’ or ‘gas’)

  • charge_type (str) – Name of the charge_type (‘demand’, ‘energy’, or ‘customer’)

  • name (str) – The name of the period for this charge (e.g., ‘all-day’ or ‘on-peak’)

  • start_date – The inclusive start date for this charge

  • end_date (str) – The exclusive end date for this charge

  • charge_limit (str) – The consumption limit for this tier of charges converted to a string

Returns:

Variable name of the form utility`_`charge_type`_`name`_`start_date`_`end_date`_`charge_limit

Return type:

str

eeco.costs.detect_charge_periods(rate_data, charge_type, month, weekday, resolution_minutes=30)[source]

Categorize charges into charge periods (peak, half-peak, off-peak, super-off-peak) for a particular month, weekday and charge_type.

Parameters:
  • rate_data (pandas.DataFrame) – Tariff data with required columns

  • charge_type (str) – Type of charge (ENERGY or DEMAND)

  • month (int) – Month (1-12)

  • weekday (int) – Weekday (0-6)

  • resolution_minutes (int) – Time resolution in minutes for checking full day coverage. Default 30

Returns:

  • period_categories: dict with period classifications for each row index: - PEAK: highest charge periods - HALF_PEAK: periods adjacent to peak - OFF_PEAK: average charge periods - SUPER_OFF_PEAK: below average charge periods

  • base_charge: the most frequent charge value

  • has_overlapping: the most frequent charge value

Return type:

tuple with

eeco.costs.get_charge_array_duration(key)[source]

Parse a charge array key to determine the duration of the charge period.

Parameters:

key (str) – Charge key of form utility_charge_type_name_start_date_end_date_charge_limit where start_date and end_date are in YYYYMMDD or YYYY-MM-DD format

Returns:

Duration of the charge period in days

Return type:

int

Raises:

ValueError – If the key format is invalid or dates cannot be parsed

eeco.costs.get_charge_df(start_dt, end_dt, rate_data, resolution='15m', keep_fixed_charges=True, scale_fixed_charges=True, scale_demand_charges=False)[source]

Creates a dictionary where the values are charge arrays and keys are of the form {utility}_{type}_{name}_{start_date}_{end_date}_{limit}

Parameters:
  • start_dt (datetime.datetime) – first timestep to be included in the cost analysis

  • end_dt (datetime.datetime) – last timestep to be included in the cost analysis

  • rate_data (pandas.DataFrame) – tariff data with required columns utility, type, basic_charge_limit, name, month_start, month_end, weekday_start, weekday_end, hour_start, hour_end, and charge and optional columns assessed, effective_start_date, and effective_end_date

  • resolution (str) – granularity of each timestep in string form with default value of “15m”

  • keep_fixed_charges (bool) – If True, fixed charges will included. If False, fixed charges will be dropped from the output. Default is False.

  • scale_fixed_charges (bool) – If True, fixed charges will be divided amongst all time steps and scaled by timesteps in the month. If False, they will not be scaled but included in the first timestep only. Default is True.

  • scale_demand_charges (bool) – If True, demand charges will be scaled by the number of timesteps in the month. If False, they will not be scaled. Default is False.

Returns:

DataFrame of charge arrays

Return type:

pandas.DataFrame

eeco.costs.get_charge_dict(start_dt, end_dt, rate_data, resolution='15m')[source]

Creates a dictionary where the values are charge arrays and keys are of the form {utility}_{type}_{name}_{start_date}_{end_date}_{limit}

Parameters:
  • start_dt (datetime.datetime) – first timestep to be included in the cost analysis

  • end_dt (datetime.datetime) – last timestep to be included in the cost analysis

  • rate_data (pandas.DataFrame) – tariff data with required columns utility, type, basic_charge_limit, name, month_start, month_end, weekday_start, weekday_end, hour_start, hour_end, and charge and optional columns assessed, effective_start_date, and effective_end_date

  • resolution (str) – granularity of each timestep in string form with default value of “15m”

Returns:

dictionary of charge arrays

Return type:

dict

eeco.costs.get_next_limit(key_substr, current_limit, keys)[source]

Finds the next charge limit for the charge represented by key

Parameters:
  • key_substr (str) – The beginnging of the key for which we want to get the next limit (i.e., {utility}_{type}_{name}_{start_date}_{end_date})

  • current_limit (int) – The limit for the current tier

  • keys (list of str) – List of all the keys in the charge dictionary

Returns:

limit in the tier after key, which is inf if there is no higher tier

Return type:

float

eeco.costs.get_unique_row_name(charge, index=None)[source]

Get a unique row name for each row of charge df.

Parameters:
  • charge (dict or pandas.Series) – The charge row data containing NAME and PERIOD fields

  • index (int, optional) – Index to use if name is empty or None

Returns:

A unique name with underscores converted to dashes

Return type:

str

eeco.costs.parametrize_charge_dict(start_dt, end_dt, rate_data, variants=None)[source]

Takes in an existing charge_dict and varies it parametrically to create alternative rate structures. Calls parametrize_rate_data to parametrize the billing csv file, then calls it on the dates specified.

Parameters:
  • start_dt (datetime.datetime) – first timestep to be included in the cost analysis

  • end_dt (datetime.datetime) – last timestep to be included in the cost analysis

  • rate_data (pandas.DataFrame) – tariff data with required columns

  • variants (list[dict]) – List of dictionaries containing variation parameters with keys: - scale_ratios: dict for charge scaling (see parametrize_rate_data for options) - shift_peak_hours_before: float to shift peak start, in hours - shift_peak_hours_after: float to shift peak end, in hours - variant_name: str (optional) variant name

Returns:

dictionary of charge_dicts with different variations

Return type:

dict

Raises:

UserWarning – If global scaling overrides individual ratios in any variant (inherited from parametrize_rate_data)

eeco.costs.parametrize_rate_data(rate_data, scale_ratios={}, shift_peak_hours_before=0, shift_peak_hours_after=0, variant_name=None)[source]

Parametrize rate data by charge periods (peak, half-peak, off-peak, super-off-peak) or exact charge keys. Applies scaling and window shifting to create alternative rate structures.

Parameters:
  • rate_data (pandas.DataFrame) – Tariff data with required columns

  • scale_ratios (dict, optional) – Dictionary for charge scaling. Can be one of three formats:

    Format 1 - Nested dictionary with structure for charge scaling:

    {

    ‘demand’: {

    ‘peak’: float, ‘half_peak’: float, ‘off_peak’: float, ‘super_off_peak’: float

    },

    ‘energy’: {

    ‘peak’: float, ‘half_peak’: float, ‘off_peak’: float, ‘super_off_peak’: float

    }

    }

    Format 2 - Dictionary with exact charge key prefixes based on csv:

    {

    ‘electric_demand_peak-summer’: float, ‘electric_energy_0’: float, ‘electric_demand_all-day’: float, …

    }

    Format 3 - Global scaling for all charges of each type:

    {

    ‘demand’: float, # scales all demand charges ‘energy’: float, # scales all energy charges

    }

    If None, all ratios default to 1.0

  • shift_peak_hours_before (float, optional) – Hours to shift peak window start (negative=earlier, positive=later). Must be multiple of 0.25 hours. Default 0

  • shift_peak_hours_after (float, optional) – Hours to shift peak window end (negative=earlier, positive=later). Must be multiple of 0.25 hours. Default 0

  • variant_name (str, optional) – Name for this variant. Default None

Returns:

Updated rate_data dataframe with parametrized charges and windows

Return type:

pandas.DataFrame

Raises:
  • ValueError – If scale_ratios contains both period-based scaling and individual charge scaling for the same charge type

  • UserWarning – If scale_ratios contains exact charge keys that are not found in the data

eeco.emissions module

Functions to calculate emissions from electricity consumption data.

eeco.emissions.calculate_grid_emissions(carbon_intensity, consumption_data, emissions_units=<Unit('kilogram / megawatt_hour')>, consumption_units=<Unit('kilowatt')>, resolution='15m', model=None, varstr='')[source]

Calculates the emissions for the given consumption information as a cvxpy object carbon intensity of electricity generation structure as a DataFrame.

Parameters:
  • carbon_intensity (array) – numpy array with kg of CO2 per kWh

  • consumption_data (numpy.Array, cvxpy.Variable, or pyomo.environ.Var) – Baseline electrical or gas usage data as a Pyomo Var

  • emissions_units (pint.Unit) – Units for the emissions data. Default is kg / MWh

  • consumption_units (pint.Unit) – Units for the electricity consumption data. Default is kW

  • resolution (str) – granularity of each timestep in string form with default value of “15m”

  • model (pyomo.Model) – The model object associated with the problem. Only used in the case of Pyomo, so None by default.

  • varstr (str) – Name of the variable to be created if using a Pyomo model

Returns:

tuple of pyomo Var representing emissions in kg of CO2 for the given consumption_data and carbon_intensity and the accompanying model object. The model object is only used for Pyomo, so by default it is None

Return type:

(pint.Quantity, cvxpy.Expression, or pyomo.environ.Var), pyomo.Model

eeco.emissions.get_carbon_intensity(start_dt, end_dt, emissions_data, emissions_units=<Unit('kilogram / megawatt_hour')>, resolution='15m', ei_varname='co2_eq_kg_per_MWh')[source]

Computes the emissions (as kilograms of CO2) of a horizon of data

Parameters:
  • start_dt (datetime.datetime or numpy.datetime64) – Start datetime to gather rate information.

  • end_dt (datetime.datetime or numpy.datetime64) – End datetime to gather rate information. This end_dt is excluded to be consistent with Python syntax.

  • emissions_data (DataFrame) – Electric grid emissions information. Only one of datetime_local and month/day/hour are required.

    datetime_local

    local datetime to estimate the marginal emissions

    month

    month for which the emissions data was averaged

    day

    day for which the emissions data was averaged

    hour

    hour for which the emissions data was averaged

    co2_eq_kg_per_MWh

    emissions in kg of CO2 per MWh of grid electricity

  • emissions_units (pint.Unit) – Units for the emissions data. Default is kg / MWh

  • resolution (str) – a string of the form [int][str] giving the temporal resolution on which charges are assessed. The str portion corresponds to numpy timedelta64 types. For example ‘15m’ specifying demand charges that are applied to 15-minute intervals of electricity consumption

  • ei_varname (str) – column name for the Scope 2 emissions factor. Default is EI_VARNAME=”co2_eq_kg_per_MWh”

Returns:

emissions from start_dt to end_dt in kg CO2 / kWh

Return type:

pint.Quantity

eeco.metrics module

Functions to estimate flexibility metrics from power consumption trajectories.

eeco.metrics.energy_capacity(baseline_kW, flexible_kW, timestep=0.25, ec_type='discharging', relative=True)[source]

Calculate the energy capacity of a virtual battery system. This approach implicitly assumes the system has completed a round-trip.

Parameters:
  • baseline_kW (array-like) – The baseline power consumption of the facility in kW.

  • flexible_kW (array-like) – The flexible power consumption of the facility in kW.

  • timestep (float) – The time step of the data in hours. Default is 0.25 hours (15 minutes).

  • ec_type (str) – The type of energy capacity to calculate. Options are ‘average’, ‘charging’, ‘discharging’

  • relative (bool) – If True, return the fractional energy capacity. If False, return the absolute energy capacity.

Raises:

ValueError – If ec_type is not one of the expected values (‘average’, ‘charging’, ‘discharging’).

Returns:

The energy capacity of the virtual battery system in either relative or absolute terms.

Return type:

float

eeco.metrics.net_present_value(capital_cost=0, electricity_savings=0, maintenance_diff=0, ancillary_service_benefit=0, service_curtailment=0, service_price=1.0, timestep=0.25, simulation_years=1, upgrade_lifetime=30, interest_rate=0.03)[source]

Calculate the net present value of flexibility of a virtual battery system.

Parameters:
  • capital_cost (float) – The capital cost of the virtual battery system in $.

  • electricity_savings (float) – The electricity savings from the flexible operation in $.

  • maintenance_diff (float) – The difference in maintenance costs between the baseline and flexible operation in $.

  • ancillary_service_benefit (float) – The benefit from providing ancillary services in $.

  • service_curtailment (float) – The amount of service curtailment. If the virtual battery system produces a product, this may be in units of volume or mass (e.g., m^3 or kg).

  • service_price (float) – The marginal price of curtailed service $/amount. Amount here may refer to units of volume or mass (e.g., $/m^3 or $/kg).

  • timestep (float) – The time step of the data in hours. Default is 0.25 hours (15 minutes).

  • simulation_years (int) – The number of years in which the electricity savings or ancillary service benefits are calculated for. Default is 1 year.

  • upgrade_lifetime (int) – The number of years of operation left for the upgrade. Default is 30 years.

  • interest_rate (float) – The interest rate used to discount future cash flows. Default is 0.03.

Raises:
  • Warning – If the capital cost is less than 0

  • ValueError – If the upgrade lifetime is less than or equal to 0

  • ValueError – If the interest rate is less than 0.

  • ValueError – if the timestep is less than or equal to 0.

Returns:

The net present value benefit of the virtual battery system in $.

Return type:

float

eeco.metrics.power_capacity(baseline_kW, flexible_kW, timestep=0.25, pc_type='average', relative=True)[source]

Calculate the power capacity of a virtual battery system. This approach implicitly assumes the system has completed a round-trip.

Parameters:
  • baseline_kW (array-like) – The baseline power consumption of the facility in kW.

  • flexible_kW (array-like) – The flexible power consumption of the facility in kW.

  • timestep (float) – The time step of the data in hours. Default is 0.25 hours (15 minutes).

  • pc_type (str) – The type of power capacity to calculate. Options are ‘average’, ‘charging’, ‘discharging’, ‘maximum’

  • relative (bool) – If True, return the fractional power capacity. If False, return the absolute power capacity.

Raises:

ValueError – If pc_type is not one of the expected values (‘average’, ‘charging’, ‘discharging’, ‘maximum’).

Returns:

The power capacity of the virtual battery system in either relative or absolute terms.

Return type:

float

eeco.metrics.roundtrip_efficiency(baseline_kW, flexible_kW)[source]

Calculate the round-trip efficiency of a flexibly operating power trajectory relative to a baseline.

Parameters:
  • baseline_kW (list or np.ndarray) – power consumption data of the baseline system in units of kW

  • flexible_kW (list or np.ndarray) – power consumption data of the flexibly operating or cost-optimized system in units of kW.

Raises:
  • TypeError – When baseline_kW and flexible_kW are not an acceptable type (e.g., list vs. np.ndarray).

  • ValueError – When baseline_kW and flexible_kW are not of the same length

  • Warnings – When baseline_kW and flexible_kW contain negative values, which may indicate an error in the data.

  • ValueError – When baseline_kW and flexible_kW contain missing values.

  • Warnings – When rte is calculated to be greater than 1. This may indicate an error in the assumptions behind the data.

Returns:

The round-trip efficiency [0,1] of the flexible power trajectory relative to the baseline.

Return type:

float

eeco.units module

eeco.units.set_sig_figs(n=4)[source]

Set the default number of significant figures used to print Pint, Pandas and NumPy value quantities.

Parameters:

n (int) – number of significant figures to display. Defaults to 4.

eeco.utils module

eeco.utils.convert_utc_to_timezone(utc_hour, timezone_str)[source]

Convert UTC hour (0-23) to the corresponding hour in a specified timezone.

Parameters: utc_hour (int): Hour in UTC (0-23). timezone_str (str): Timezone string, e.g., ‘America/New_York’.

Returns: int: Corresponding hour in the specified timezone.

eeco.utils.get_freq_binsize_minutes(freq)[source]

Gets size of a given time frequency expressed in units of minutes

Parameters:

freq (str) – a string of the form [type][freq_binsize], where type corresponds to a numpy.timedelta64 encoding and freq binsize is an integer giving the number of increments of type of one binned increment of our time variable (for example ‘6h’ means the data are grouped into increments of 6 hours)

Raises:

ValueError – when resolution is not minute, hourly, or daily

Returns:

integer giving the number of minutes in the given time frequency unit

Return type:

int

eeco.utils.idxparam_value(idx_param)[source]

Returns the parameter value at the given index.

Parameters:

idx_param (pyomo.environ.Param or pyomo.environ.Var) – The Pyomo parameter or variable to be converted

Returns:

Indexed variable or parameter as a numpy array

Return type:

numpy.ndarray

eeco.utils.max(expression, model=None, varstr=None)[source]

Elementwise maximum of an expression or array

Parameters:
  • expression ([) – numpy.Array, cvxpy.Expression, pyomo.core.expr.numeric_expr.NumericExpression, pyomo.core.expr.numeric_expr.NumericNDArray, pyomo.environ.Param, pyomo.environ.Var

  • ] – The expression to find the maximum of

  • model (pyomo.environ.Model) – The model object associated with the problem. Only used in the case of Pyomo, so None by default.

  • varstr (str) – Name of the variable to be created if using a Pyomo model

Raises:

TypeError – When expression is not of type numpy.Array, cvxpy.Expression, pyomo.core.expr.numeric_expr.NumericExpression, pyomo.core.expr.numeric_expr.NumericNDArray, pyomo.environ.Param, or pyomo.environ.Var

Returns:

Expression representing max of expression

Return type:

([numpy.Array, cvxpy.Expression, pyomo.environ.Var], pyomo.environ.Model)

eeco.utils.max_pos(expression, model=None, varstr=None)[source]

Returns the maximum positive scalar value of an expression. I.e., max([x, 0]) where x is any element of the expression (if a matrix)

Parameters:
  • expression ([) – numpy.Array, cvxpy.Expression, pyomo.core.expr.numeric_expr.NumericExpression, pyomo.core.expr.numeric_expr.NumericNDArray, pyomo.environ.Param, pyomo.environ.Var

  • ] – Expression representing a matrix, vector, or scalar

  • model (pyomo.environ.Model) – The model object associated with the problem. Only used in the case of Pyomo, so None by default.

  • varstr (str) – Name of the variable to be created if using a Pyomo model

Raises:

TypeError – When expression is not of type numpy.Array, cvxpy.Expression, pyomo.core.expr.numeric_expr.NumericNDArray, pyomo.core.expr.numeric_expr.NumericExpression, pyomo.environ.Param, or pyomo.environ.Var

Returns:

  • ( – [numpy.float, numpy.int, numpy.Array, cvxpy.Expression, or pyomo.environ.Var], pyomo.environ.Model

  • ) – Expression representing maximum positive scalar value of expression

eeco.utils.multiply(expression1, expression2, model=None, varstr=None)[source]

Implements elementwise multiplication operation on two optimization expressions

Parameters:
  • expression1 ([) – numpy.Array, cvxpy.Expression, pyomo.core.expr.numeric_expr.NumericExpression, pyomo.core.expr.numeric_expr.NumericNDArray, pyomo.environ.Param, pyomo.environ.Var

  • ] – LHS of multiply operation

  • expression2 ([) – numpy.Array, cvxpy.Expression, pyomo.core.expr.numeric_expr.NumericExpression, pyomo.core.expr.numeric_expr.NumericNDArray, pyomo.environ.Param, pyomo.environ.Var

  • ] – RHS of multiply operation

  • model (pyomo.environ.Model) – The model object associated with the problem. Only used in the case of Pyomo, so None by default.

  • varstr (str) – Name of the variable to be created if using a Pyomo model

Raises:

TypeError – When expression is not of type numpy.Array, cvxpy.Expression, pyomo.core.expr.numeric_expr.NumericNDArray, pyomo.core.expr.numeric_expr.NumericExpression, pyomo.environ.Param, or pyomo.environ.Var

Returns:

  • [ – numpy.Array, cvxpy.Expression, pyomo.core.expr.numeric_expr.NumericNDArray, pyomo.environ.Expression

  • ] – result from elementwise multiplication of expression1 and expression2

eeco.utils.parse_freq(freq)[source]

Parses a time frequency code string, returning its type and its freq_binsize

Parameters:

freq (str) – a string of the form [type][freq_binsize], where type corresponds to a numpy.timedelta64 encoding and freq binsize is an integer giving the number of increments of type of one binned increment of our time variable (for example ‘6h’ means the data are grouped into increments of 6 hours)

Returns:

tuple of the form (int,`str`) giving the binsize and units (freq_type)

Return type:

tuple

eeco.utils.sanitize_varstr(varstr)[source]

Sanitizes a variable string by removing non-alphanumeric characters and replacing spaces with underscores.

Parameters:

varstr (str) – The variable string to sanitize.

Returns:

The sanitized variable string.

Return type:

str

eeco.utils.sum(expression, axis=0, model=None, varstr=None)[source]

Elementwise sum of values in an expression or array

Parameters:
  • expression ([) – numpy.Array, cvxpy.Expression, pyomo.core.expr.numeric_expr.NumericExpression, pyomo.core.expr.numeric_expr.NumericNDArray, pyomo.environ.Param, pyomo.environ.Var

  • ] – Expression representing a matrix to sum

  • axis (int) – Optional axis along which to compute sum. Default is 0

  • model (pyomo.environ.Model) – The model object associated with the problem. Only used in the case of Pyomo, so None by default.

  • varstr (str) – Name of the variable to be created if using a Pyomo model

Raises:

TypeError – When expression is not of type numpy.Array, cvxpy.Expression, pyomo.core.expr.numeric_expr.NumericExpression, pyomo.core.expr.numeric_expr.NumericNDArray pyomo.environ.Param, or pyomo.environ.Var

Returns:

Expression representing sum of expression along axis

Return type:

[numpy.Array, cvxpy.Expression, pyomo.environ.Expression]

Module contents

Main package for Electric Emissions & Cost Optimizer (EECO).

eeco.get_module_version()[source]