costs

This module consists of code that computes a user’s electricity bill given an electricity consumption profile.

Functions to calculate costs from electricity consumption data.

electric_emission_cost.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 / day (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 / day (gas demand), cubic meter (gas energy), or $ / month (customer)

electric_emission_cost.costs.calculate_cost(charge_dict, consumption_data_dict, 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 / day (gas demand), cubic meter (gas energy), or $ / month (customer)

  • consumption_data_dict (dict of numpy.ndarray or cvxpy.Expression) – Baseline electrical and gas usage data as an optimization variable object with keys “electric” and “gas”

  • 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.

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

  • desired_utility (str) – Name of desired utility for itemized costs. Either ‘electric’ or ‘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.

  • 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:

numpy array, cvxpy Expression representing cost in USD for the given consumption_data, charge_type, and utility

Return type:

numpy.Array, cvxpy.Expression, or pyomo.Model

electric_emission_cost.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=None)[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 or cvxpy.Expression) – 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) – 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.

  • 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:

float or cvxpy Expression representing cost in USD for the given charge_array and consumption_data

Return type:

cvxpy.Expression or float

electric_emission_cost.costs.calculate_energy_cost(charge_array, consumption_data, divisor, limit=0, next_limit=inf, prev_consumption=0, consumption_estimate=0, model=None, varstr=None)[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 or cvxpy.Expression) – Baseline electrical or gas usage data as an optimization variable object

  • divisor (int) – Divisor for the energy charges

  • 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

  • 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.

  • 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:

float or cvxpy Expression representing cost in USD for the given charge_array and consumption_data

Return type:

cvxpy.Expression, pyomo.Model, or float

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

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

Only flat rates for exports are supported (in $ / kWh).

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

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

  • divisor (int) – Divisor for the energy charges

  • 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:

float or cvxpy Expression representing revenue in USD for the given charge_array and export_data

Return type:

cvxpy.Expression or float

electric_emission_cost.costs.calculate_itemized_cost(charge_dict, consumption_data, resolution='15m', prev_demand_dict=None, consumption_estimate=0, model=None)[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 / day (gas demand), cubic meter (gas energy), or $ / month (customer)

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

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

    prev_demand_dictdict

    Dictionary previous maximmum demand charges with a key for each charge. Default is None, which results in an a prev_demand of zero for all charges.

  • consumption_estimate (float) – estimated total consumption up to this point in the bililng period to determine correct tier based on charge limits

  • 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

electric_emission_cost.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

electric_emission_cost.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

electric_emission_cost.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

electric_emission_cost.costs.get_charge_df(start_dt, end_dt, rate_data, resolution='15m', keep_fixed_charges=True)[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 be divided amongst all time steps and included. If False, fixed charges will be dropped from the output. Default is False.

Returns:

DataFrame of charge arrays

Return type:

pandas.DataFrame

electric_emission_cost.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

electric_emission_cost.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