diff --git a/docs/build/.buildinfo b/docs/build/.buildinfo new file mode 100644 index 000000000..db3b6264b --- /dev/null +++ b/docs/build/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 9a5ab9220eaba148dacb38eb81465b8e +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/build/.doctrees/README.doctree b/docs/build/.doctrees/README.doctree new file mode 100644 index 000000000..e371a805f Binary files /dev/null and b/docs/build/.doctrees/README.doctree differ diff --git a/docs/build/.doctrees/analysis.doctree b/docs/build/.doctrees/analysis.doctree new file mode 100644 index 000000000..d4bd93f4b Binary files /dev/null and b/docs/build/.doctrees/analysis.doctree differ diff --git a/docs/build/.doctrees/charging_sim.doctree b/docs/build/.doctrees/charging_sim.doctree new file mode 100644 index 000000000..4a3da2f74 Binary files /dev/null and b/docs/build/.doctrees/charging_sim.doctree differ diff --git a/docs/build/.doctrees/environment.pickle b/docs/build/.doctrees/environment.pickle new file mode 100644 index 000000000..55e4c5d66 Binary files /dev/null and b/docs/build/.doctrees/environment.pickle differ diff --git a/docs/build/.doctrees/feeder_population.doctree b/docs/build/.doctrees/feeder_population.doctree new file mode 100644 index 000000000..8af74bbbe Binary files /dev/null and b/docs/build/.doctrees/feeder_population.doctree differ diff --git a/docs/build/.doctrees/index.doctree b/docs/build/.doctrees/index.doctree new file mode 100644 index 000000000..0b20731a7 Binary files /dev/null and b/docs/build/.doctrees/index.doctree differ diff --git a/docs/build/.doctrees/modules.doctree b/docs/build/.doctrees/modules.doctree new file mode 100644 index 000000000..deba12fb2 Binary files /dev/null and b/docs/build/.doctrees/modules.doctree differ diff --git a/docs/build/.doctrees/test_cases.base_case.doctree b/docs/build/.doctrees/test_cases.base_case.doctree new file mode 100644 index 000000000..a0c9e3570 Binary files /dev/null and b/docs/build/.doctrees/test_cases.base_case.doctree differ diff --git a/docs/build/.doctrees/test_cases.battery.doctree b/docs/build/.doctrees/test_cases.battery.doctree new file mode 100644 index 000000000..2a79bae66 Binary files /dev/null and b/docs/build/.doctrees/test_cases.battery.doctree differ diff --git a/docs/build/.doctrees/test_cases.battery.feeder_population.doctree b/docs/build/.doctrees/test_cases.battery.feeder_population.doctree new file mode 100644 index 000000000..36b35382d Binary files /dev/null and b/docs/build/.doctrees/test_cases.battery.feeder_population.doctree differ diff --git a/docs/build/.doctrees/test_cases.doctree b/docs/build/.doctrees/test_cases.doctree new file mode 100644 index 000000000..85129a00e Binary files /dev/null and b/docs/build/.doctrees/test_cases.doctree differ diff --git a/docs/build/README.html b/docs/build/README.html new file mode 100644 index 000000000..12f36983d --- /dev/null +++ b/docs/build/README.html @@ -0,0 +1,109 @@ + + + + + + + Readme — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ +
+

Readme

+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/build/_images/sim_frame.png b/docs/build/_images/sim_frame.png new file mode 100644 index 000000000..97deaca2a Binary files /dev/null and b/docs/build/_images/sim_frame.png differ diff --git a/docs/build/_modules/analysis/cost_analysis.html b/docs/build/_modules/analysis/cost_analysis.html new file mode 100644 index 000000000..1beeeabdc --- /dev/null +++ b/docs/build/_modules/analysis/cost_analysis.html @@ -0,0 +1,450 @@ + + + + + + analysis.cost_analysis — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for analysis.cost_analysis

+"""
+This module contains the CostEstimator Class, which estimates the cost of the different grid and DER components
+from the simulation.
+"""
+
+import os
+import numpy as np
+import pandas as pd
+import json
+import matplotlib.pyplot as plt
+
+PLOT_FONT_SIZE = 16
+plt.rcParams.update({'font.size': PLOT_FONT_SIZE})
+
+
+
+[docs] +class CostEstimator: + """ + This class is used to calculate levelized cost of DER assets in EV-Ecosim. + + :param num_days: The number of days for which the calculation is run. + """ + def __init__(self, num_days): + """ + Constructor method. + + :param num_days: The number of days for which the calculation is run. + """ + self.solar_rating = None + self.trans_price_dict = {} + self.dcfc = False # boolean for determining if transformer is 480 or 240V + self.num_days = num_days + self.trans_Th = None # hot-spot temp + self.trans_To = None # top-oil temp + self.TOU_rates = None + self.battery_cost = None # to be calculated later + self.solar_price_per_m2 = 6 + self.battery_price_per_kWh = 345 # ($) source: https://www.nrel.gov/docs/fy21osti/79236.pdf + self.trans_cost_per_kVA = None # create a non-linear cost curve for these prices (I sense batteries are the same) + self.trans_normal_life = 180000 # hours + self.resolution = 15 + self.TOU_rates = np.loadtxt('../elec_rates/PGE_BEV2_S_annual_TOU_rate_15min.csv')[:96 * self.num_days] # change this to referenced property + # todo: cannot find good source for 2400/240V transformer prices + +
+[docs] + def calculate_battery_cost(self, result_dir): + """ + Calculates the battery costs and updates the different cost components, including LCOE. + + :param result_dir: Directory in which to save the results dictionary. + :return dict result_dict: Dictionary of results. + """ + current_dir = os.getcwd() + os.chdir(result_dir) + with open('scenario.json', "r") as f: + scenario = json.load(f) + result_dict = {} + capital_cost = self.battery_price_per_kWh / 1000 * scenario['pack_energy_cap'] + for root, dirs, files, in os.walk(".", topdown=True): + for file in files: + path_lst = file.split("_") + if 'battery' in path_lst and 'plot.png' not in path_lst: + battery_LOL = 1 - pd.read_csv(file)['SOH'].to_numpy()[-1] + avg_daily_energy_thruput = np.abs(pd.read_csv(file)['power_kW'].to_numpy()[1:]).sum() \ + * self.resolution / 60 * 1 / self.num_days + expected_life_days = 0.2 / (battery_LOL / self.num_days) + expected_energy_thruput_over_lifetime = avg_daily_energy_thruput * expected_life_days + capital_loss_to_aging = (battery_LOL / 0.2 * capital_cost) + self.battery_cost = capital_cost + capital_loss_to_aging + result_dict[f'battery_sim_{path_lst[2]}'] = {"capital_loss_aging": capital_loss_to_aging, + "capital_loss_aging_per_day": capital_loss_to_aging / expected_life_days, + "capital_cost": capital_cost, + "battery_LOL": battery_LOL, + "LOL_per_day": battery_LOL / self.num_days, + "battery_total_cost": self.battery_cost, + "total_cost_per_day": self.battery_cost / expected_life_days, + 'lcoe': self.battery_cost / expected_energy_thruput_over_lifetime, + 'lcoe_aging': capital_loss_to_aging /expected_energy_thruput_over_lifetime + } + with open("postopt_cost_batt.json", 'w') as config_file_path: + json.dump(result_dict, config_file_path, indent=1) # save to JSON + os.chdir(current_dir) # go back to initial dir + return result_dict
+ + +
+[docs] + def calculate_solar_cost(self): + """ + Values are pulled from the NREL solar cost calculator. + Ref: https://www.nrel.gov/solar/market-research-analysis/solar-levelized-cost.html + To be deprecated soon. + + :return: None + """ + return
+ + +
+[docs] + def calculate_electricity_cost_PGEBEV2s(self, result_dir, PGE_separate_file=True): + """ + Calculates the overall electricity PGEBEV2S cost for a given scenario. + + :param str result_dir: Directory in which the result is saved. + :param PGE_separate_file: + :return dict result_dict: A dictionary comprising all the cost components and their dollar amounts. + """ + current_dir = os.getcwd() + os.chdir(result_dir) + result_dict = {} + price_per_block = 95.56 # ($/Block) # need to make these agnostic for now just leave as is + overage_fee = 3.82 # ($/kW) + for root, dirs, files, in os.walk(".", topdown=True): + for file in files: + path_lst = file.split("_") + if 'station' in path_lst and 'block' not in path_lst and 'plot.png' not in path_lst: + net_grid_load = pd.read_csv(file)['station_net_grid_load_kW'].to_numpy()[1:] + total_grid_load = pd.read_csv(file)['station_total_load_kW'].to_numpy()[1:] + net_ev_grid_load_plusbatt = total_grid_load - pd.read_csv(file)['station_solar_load_ev'].to_numpy()[ + 1:] + pd.read_csv(file)['battery_power'].to_numpy()[ + 1:] + total_energy = total_grid_load.sum() * self.resolution/60 + max_load = total_grid_load.max() + average_load = total_grid_load.mean() + self.plot_loads(total_grid_load, net_ev_grid_load_plusbatt, prefix=f'{file.split(".")[0]}_', + labels=["Total demand", "Net demand with DER"]) + if PGE_separate_file: + block_subscription = int(np.loadtxt(f'PGE_block_{file}')[1]) + else: + block_subscription = int(pd.read_csv(file)['PGE_power_blocks'].to_numpy()[1]) + subscription_cost = block_subscription * price_per_block # This is in blocks of 50kW which makes it very convenient ($/day) + penalty_cost = max((np.max(net_grid_load) - 50 * block_subscription), 0) * overage_fee # ($) + TOU_cost = np.sum(self.TOU_rates[0:net_grid_load.shape[0]] * net_grid_load) * self.resolution / 60 # ($) + electricity_cost = TOU_cost + penalty_cost + subscription_cost + result_dict[f'charging_station_sim_{path_lst[3]}'] = {"TOU_cost": TOU_cost, + "subscription_cost": subscription_cost, + "penalty_cost": penalty_cost, + "total_elec_cost": electricity_cost, + "cost_per_day": electricity_cost / self.num_days, + "max_load": max_load, + "avg_load": average_load, + "cost_per_kWh": electricity_cost/total_energy} + elif 'battery' in path_lst and 'plot.png' not in path_lst: + power = pd.read_csv(file)['power_kW'].to_numpy()[1:] + power_pred = pd.read_csv(file)['pred_power_kW'].to_numpy()[1:] + soc = pd.read_csv(file)['SOC'].to_numpy()[1:] + soc_pred = pd.read_csv(file)['SOC_pred'].to_numpy()[1:] + self.plot_soc(soc, soc_pred, prefix=f'{file.split(".")[0]}_SOC', + labels=['true soc', 'pred soc', 'SoC']) + self.plot_power(power, power_pred, prefix=f'{file.split(".")[0]}_power', + labels=['true power', 'pred power', 'power (kW)']) + + with open("postopt_cost_charging.json", 'w') as config_file_path: + json.dump(result_dict, config_file_path, indent=1) # save to JSON + os.chdir(current_dir) # go back to initial dir + return result_dict
+ + +
+[docs] + def transformer_cost(self): + """Cannot find good resource data for this yet.""" + return NotImplementedError
+ + +
+[docs] + @staticmethod + def plot_loads(total_load, net_load, prefix=None, labels: list = None): + """ + Creates plots overlaying load and net loads for post-simulation visualization. + + :param total_load: Overall EV load demand at node, can include building load if controllable. + :param net_load: total_load minus DER buffer. + :param prefix: Plot file label prefix. + :param labels: Legend labels for each plotted curve. + :return: None. + """ + plt.close('all') + num_days = 1 + start_day = 0 + num_steps = num_days * 96 + fig, ax = plt.subplots() + x_vals = 15 / 60 * np.arange(0, num_steps) + total_load_plot = total_load[start_day * 96:start_day * 96 + num_steps] + net_load_plot = net_load[start_day * 96:start_day * 96 + num_steps] + + lb = np.zeros(num_steps) + alph = 0.3 + interp = True + total_load_color = 'blue' + net_load_color = 'orange' + ax.plot(x_vals, total_load_plot, color=f'tab:{total_load_color}') + ax.plot(x_vals, net_load_plot, color=f'tab:{net_load_color}') + ax.fill_between(x_vals, lb, total_load_plot, color=f'tab:{total_load_color}', + label=labels[0], interpolate=interp, alpha=alph) + ax.fill_between(x_vals, lb, net_load_plot, color=f'tab:{net_load_color}', label=labels[1], interpolate=interp, + alpha=alph) + ax.set_ylim(bottom=0) + ax.set_xlim(left=0, right=round(max(x_vals))) + plt.xlabel('Hour of day') + plt.ylabel('Power (kW)') + plt.legend() + fig.tight_layout() + if prefix: + plt.savefig(f'{prefix}_load_plot.png') + plt.close('all') + return + plt.savefig('loads.png')
+ + +
+[docs] + @staticmethod + def plot_soc(soc, soc_pred, prefix=None, labels: list = None): + """ + Plots the controller predicted and true state of charge of the battery system. + + :param soc: True state of charge. + :param soc_pred: Controller predicted state of charge. + :param prefix: Plot file label prefix. + :param labels: Legend labels for each plotted curve. + :return: None. + """ + error_abs_mean = np.mean(np.abs((soc - soc_pred) / (soc + 1e-6)) * 100) + MAPE = np.max(np.abs((soc - soc_pred) / (soc + 1e-6)) * 100) + np.savetxt('abs_percent_err_soc.csv', [error_abs_mean]) + np.savetxt('MAPE_soc.csv', [MAPE]) + plt.close('all') + num_days = 10 + start_day = 0 + num_steps = num_days * 96 + fig, ax = plt.subplots() + x_vals = 15 / 60 * np.arange(0, num_steps) + soc_plot = soc[start_day * 96:start_day * 96 + num_steps] + soc_pred_plot = soc_pred[start_day * 96:start_day * 96 + num_steps] + + ax.plot(x_vals, soc_plot, color='tab:blue', label=labels[0]) + ax.plot(x_vals, soc_pred_plot, '--', color='tab:red', label=labels[1]) + plt.xlabel('Hour of day') + plt.ylabel(labels[2]) + plt.legend() + fig.tight_layout() + if prefix: + plt.savefig(f'{prefix}_soc_plot.png') + return + plt.savefig('soc_plot.png')
+ + +
+[docs] + @staticmethod + def plot_power(power, power_pred, prefix=None, labels: list = None): + """ + Plots the controller predicted and true power of the battery system. + + :param power: True power. + :param power_pred: Controller predicted power. + :param prefix: Plot file label prefix. + :param labels: Legend labels for each plotted curve. + :return: None. + """ + error_abs_mean = np.mean(np.abs((power - power_pred) / (power + 1e-6)) * 100) + MAPE = np.max(np.abs((power - power_pred) / (power + 1e-6)) * 100) + np.savetxt('abs_percent_err_power.csv', [error_abs_mean]) + np.savetxt('MAPE_power.csv', [MAPE]) + plt.close('all') + num_days = 10 + start_day = 0 + num_steps = num_days * 96 + fig, ax = plt.subplots() + x_vals = 15 / 60 * np.arange(0, num_steps) + power_plot = power[start_day * 96:start_day * 96 + num_steps] + power_pred_plot = power_pred[start_day * 96:start_day * 96 + num_steps] + + ax.plot(x_vals, power_plot, color='tab:blue', label=labels[0]) + ax.plot(x_vals, power_pred_plot, '--', color='tab:red', label=labels[1]) + plt.xlabel('Hour of day') + plt.ylabel(labels[2]) + plt.legend() + fig.tight_layout() + if prefix: + plt.savefig(f'{prefix}_power_plot.png') + return + plt.savefig('power_plot.png')
+ + +
+[docs] + def solar_cost(self, result_dir): + """ + Calculates the overall capital cost of the solar system. + Not fully implemented. + + :param str result_dir: Location to save the result. + :return: Solar PV capital cost. + """ + return self.solar_rating * 1e6 / 150 * self.solar_price_per_m2 # approximate area using 150W/m2
+ + +
+[docs] + def calculate_trans_loss_of_life(self, result_dir): + """ + Estimates the expected transformer loss of life. + + Reference: + + * 5.11.3 of IEEE Std C57.12.00-2010 a minimum normal insulation life expectancy of 180 000 hours is expected. + + :param result_dir: Directory in which the loss results is saved. + :return: Dictionary of transformer losses. + """ + current_dir = os.getcwd() + os.chdir(result_dir) + with open('scenario.json', "r") as f: + scenario = json.load(f) + # save the charging buses + result_dict = {} + for root, dirs, files, in os.walk(".", topdown=True): + for file in files: + if 'trans_Th' in file: + trans_Th_data = pd.read_csv(file) + relevant_dcfc_trans = [trans for trans in trans_Th_data.columns if 'dcfc' in trans] + relevant_L2_trans = [f'trip_trans_{trans.split("_")[-1]}' for trans in scenario['L2_nodes']] + trans_str_list = relevant_L2_trans + relevant_dcfc_trans + relevant_Th_data = trans_Th_data[trans_str_list] + # ref for A and B https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=4073181 + A = -27.558 + B = 14573 + for trans in trans_str_list: + trans_Th = relevant_Th_data[trans] + F_EQA = np.mean(np.exp(15000 / 383 - 15000 / (trans_Th + 273))) # equivalent aging factor + print("F_EQA: ", F_EQA) + percent_LOL = F_EQA * (24 * self.num_days) * 100 / self.trans_normal_life + result_dict[trans] = percent_LOL + result_dict[f'{trans}_LOL_per_day'] = percent_LOL / self.num_days + result_dict["average_LOL"] = sum(result_dict.values()) / (len(trans_str_list)) + + with open("postopt_trans_lol.json", 'w') as config_file_path: + json.dump(result_dict, config_file_path, indent=1) # save to JSON + os.chdir(current_dir) # go back to initial dir + return result_dict
+
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/build/_modules/charging_sim/batteryAgingSim.html b/docs/build/_modules/charging_sim/batteryAgingSim.html new file mode 100644 index 000000000..6941d1f69 --- /dev/null +++ b/docs/build/_modules/charging_sim/batteryAgingSim.html @@ -0,0 +1,321 @@ + + + + + + charging_sim.batteryAgingSim — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for charging_sim.batteryAgingSim

+"""
+This module contains the BatteryAging class. The battery aging objects enact on the battery object and update the
+battery capacity and resistance at each simulation time-step.
+"""
+
+import numpy as np
+import math
+
+
+
+[docs] +class BatteryAging: + """ + Current aging model is for LiNiMnCoO2 (NMC) battery cells. More aging models will be added in the future. + + Link to Paper: https://www.sciencedirect.com/science/article/pii/S0378775314001876 + + Default Params from paper: + * beta_cap: capacity fade aging factor for cycle aging + * alpha_cap capacity fade aging factor for calendar aging + * beta_res: resistance growth aging factor for cycle aging + * alpha_res: resistance growth aging factor for calendar aging + + Assumptions: + * Homogenous battery with dynamics modelled. + * Uniform aging across all cells. + * Constant temperature profile in vicinity of battery. + + """ + def __init__(self, datetime, num_steps, res=15): + """ + Constructor for the BatteryAging class. + + :param datetime: Unused for now. + :param num_steps: Number of steps in the simulation. + :param res: Resolution of the simulation in minutes. + """ + self.num_steps = num_steps + self.time = 1 # because calendar aging is in days, so for each num time_steps for resolution + self.ambient_temp = 23 + 273 # absolute temp in K + self.aging_params = {} # to be updated later + self.num_daily_steps = 96 # to be configured later + self.res = res # minutes + self.cap = 4.85 # Ah + self.beta_caps = [] + +
+[docs] + def get_cyc_aging(self, battery): + """ + Calculates the resistance growth and capacity fade from cycle aging. + + :param battery: THe batt + :return: + """ + SOC_vector = np.array( + battery.SOC_list[-(self.num_steps + 1):]) # change this to the list? Done after one complete day + # print("SOC is: ", SOC_vector) + # TODO: changed del DOD to absolute value!! + # print('SOC: ', SOC_vector) + del_DOD = np.abs(np.round(SOC_vector[0:self.num_steps] - SOC_vector[1:], 5)) # just for numerical convenience. Have this list be updated, given the resolution we want to solve!!! + # print("del DOD: ", del_DOD) + # print("Current Voltage is ", battery.voltage) + # del_DOD[del_DOD < 0] = 0 # remove the charging parts in profile to get DOD + del_DOD = np.sum(del_DOD) / 2 # total cycle depth is half one depth - DOUBLE-CHECK IF THIS IS ACCURATE + # del_DOD = np.max(SOC_vector) - np.min(SOC_vector) # this is not entirely accurate + real_voltage = np.array(battery.voltages[-2:]) / battery.topology[0] # this should include the prior voltage no? + avg_voltage = np.sqrt(np.average(real_voltage ** 2)) # quadratic mean voltage for aging + # print("average voltage: ", avg_voltage, "regular avg: ", np.average(real_voltage)) + beta_cap = 7.348 * 10**-3 * (avg_voltage - 3.695)**2 + 7.6 * 10**-4 + 4.081 * 10**-3 * del_DOD + beta_cap /= 4880.285045 + # print('Beta Cap is, ', beta_cap) + beta_res = 2.153 * 10**-4 * (avg_voltage - 3.725)**2 - 1.521 * 10**-5 + 2.798 * 10**-4 * del_DOD + beta_minimum = 1.5 * 10**-5 + if beta_res < beta_minimum: + beta_res = beta_minimum # there is a minimum aging factor that needs to be fixed + Q = np.abs(battery.current / battery.topology[1] * self.res / 60) # in Ah + + capacity_fade = beta_cap * Q ** 0.5 # time is one day for both + # capacity_fade = beta_cap * Qmax**0.5 * 2.15 / battery.cell_nominal_cap # time is one day for both + battery.cycle_aging.append(capacity_fade) + # print('Q: {}, del DOD: {}, cap fade: {}'.format(Q, del_DOD, capacity_fade)) + resistance_growth = beta_res * Q + # resistance_growth = beta_res * Q * 2.15 / battery.cell_nominal_cap + battery.true_capacity_loss = capacity_fade + self.beta_caps.append(beta_cap) + # print("Aging factor beta,", beta_cap) + # change return function to np.sum later after debugging + return capacity_fade, np.sum(resistance_growth)
+ + +
+[docs] + def update_capacity(self, battery): + """ + Updates the capacity of the battery based on the aging model adopted from Schmalsteig Et. Al. + + :param battery: Battery object. + :return: None. Updates the battery object capacity. + """ + cap_fade = self.get_aging_value(battery)[0] + battery.SOH -= cap_fade # change this to nom rating + battery.SOH_track += battery.SOH, + battery.cap = battery.SOH * battery.cell_nominal_cap + battery.Qmax = battery.max_SOC * battery.cap + battery.true_capacity_loss += cap_fade + battery.true_aging.append(cap_fade)
+ + +
+[docs] + def update_resistance(self, battery): + """ + Updates the resistance of the battery based on the aging model adopted from Schmalsteig Et. Al. + + :param battery: Battery object. + :return: None. Updates the battery object resistance. + """ + res_growth = self.get_aging_value(battery)[1] + battery.R_cell += res_growth + battery.resistance_growth += res_growth
+ + +
+[docs] + def get_calendar_aging(self, battery): + """ + Returns the calendar aging of the battery object. + + :param battery: The battery object. + :return: A tuple of capacity fade and resistance growth due to calendar aging. + """ + voltages = np.array(battery.voltages[-2:]) / battery.topology[0] # this should include the prior voltage no? + avg_voltage = np.average(voltages) # mean voltage for aging + # THIS MUST BE ESTIMATED IN DAYS + alpha_cap = (7.543 * avg_voltage - 23.75) * 10**6 * math.exp(-6976 / self.ambient_temp) # aging factors + alpha_res = (5.270 * avg_voltage - 16.32) * 10**5 * math.exp(-5986 / self.ambient_temp) # temp in K + alpha_cap /= 4880.285045 # scaling factor to match our data + capacity_fade = alpha_cap * (self.time / self.num_daily_steps)**0.75 + # for each time-step (this is scaled up for current cell) + resistance_growth = alpha_res * (self.time / self.num_daily_steps) ** 0.75 + # for each time-step (this is scaled up for current cell) + # battery.true_capacity_loss = capacity_fade # this is wrong + if isinstance(capacity_fade, float): + battery.calendar_aging.append(capacity_fade) + return capacity_fade, resistance_growth # due to interval which degradation is implemented + return sum(capacity_fade), sum(resistance_growth)
+ + +
+[docs] + def get_total_aging(self, battery: object): + """ + Returns the total capacity fade of the battery object. This includes both cycle and calendar aging. + + :param object battery: The battery (pack) object. + :return: Total calendar + cycle aging of the battery. + """ + return self.get_cyc_aging(battery) + self.get_calendar_aging(battery)
+ + +
+[docs] + def get_aging_value(self, battery): + """ + Returns the total capacity fade and resistance growth of the battery object. + + :param battery: The battery (pack) object. + :return: List of total capacity fade and resistance growth of the battery. + """ + cap_fade_cycle, res_growth_cycle = self.get_cyc_aging(battery) # this infers first + cap_fade_calendar, res_growth_cal = self.get_calendar_aging(battery) + # print("Cycle aging: {}, Calendar aging: {}".format(cap_fade_cycle, cap_fade_calendar)) + capacity_fade = cap_fade_cycle + cap_fade_calendar + res_growth = res_growth_cal + res_growth_cycle + return [capacity_fade, res_growth]
+ + +
+[docs] + def run(self, battery): + """ + Runs the aging model for the battery object. + + :param battery: The battery (pack) object. + :return: None. Updates the battery object. + """ + self.update_capacity(battery)
+ + # print("Battery Aging and Response Estimated") + +
+[docs] + @staticmethod + def NMC_cal_aging(): + pass
+ + +
+[docs] + @staticmethod + def NMC_cyc_aging(): + pass
+ + +
+[docs] + @staticmethod + def LFP_cal_aging(): + pass
+ + +
+[docs] + @staticmethod + def LFP_cyc_aging(): + pass
+
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/build/_modules/charging_sim/capacitor.html b/docs/build/_modules/charging_sim/capacitor.html new file mode 100644 index 000000000..3e02fabe2 --- /dev/null +++ b/docs/build/_modules/charging_sim/capacitor.html @@ -0,0 +1,111 @@ + + + + + + charging_sim.capacitor — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for charging_sim.capacitor

+"""This file hosts the class for capacitors. Future work"""
+#TODO: develop new class for super-caps for future study: Modelling, constraints, and features
+
+
+[docs] +class Capacitor: + def __init__(self, name): + self.name = name
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/build/_modules/charging_sim/electricityPrices.html b/docs/build/_modules/charging_sim/electricityPrices.html new file mode 100644 index 000000000..d816620ce --- /dev/null +++ b/docs/build/_modules/charging_sim/electricityPrices.html @@ -0,0 +1,230 @@ + + + + + + charging_sim.electricityPrices — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for charging_sim.electricityPrices

+"""
+This module contains the class that loads the electricity price data and structure used for sampling prices during
+simulation.
+
+Based on the prices.json config file, this module will load the desired price TOU rate file that will be used in
+optimization problem. The default is the PGE_BEV2_S rate file, which is valid for California, however users can load
+their own TOU rate file. The prices are loaded into a numpy array and can be sampled from during simulation.
+The prices are sampled based on the month of the year and the hour of the day.
+"""
+
+import numpy as np
+import pandas as pd
+
+# Old (legacy) reference below:
+# https://www.pge.com/tariffs/assets/pdf/tariffbook/ELEC_SCHEDS_EV.pdf
+# load_profile is a 24x1 array with kWh consumed in each our of the day, starting at 0:00
+# Rates in $/kWh based on "Residential TOU Service for Plug-In EV2"
+# Rates in $/kWh based on "Commercial TOU Service for Plug-In EV2"
+# Peak (weekday) = 4 to 9 PM 
+# Partial-peak (weekday) = 3 to 4 PM, 9 to 12 AM
+# Off-peak: all other times
+
+
+
+[docs] +class PriceLoader: + """This class pre-loads prices and is used to sample prices that are used for optimization of EVSE profits/costs + during charging simulation. + + :type config: dict + :param config: Configuration dictionary for the price loader. + :param path_prefix: This string path prefix is obtained first based on your repository location to set the + correct path for obtaining the data. + """ + + def __init__(self, config, path_prefix=None): + """ + Initializes the PriceLoader class. + + :type config: dict + :param config: Configuration dictionary for the price loader. + :param path_prefix: This string path prefix is obtained first based on your repository location to set the + correct path for obtaining the data. + """ + self.path_prefix = path_prefix + self.config = config + self.data = pd.read_csv(path_prefix + self.config["data_path"]) + self.data_np = self.data.to_numpy() + self.month_start_idx = {1: 0, 2: 31, 3: 59, 4: 90, 5: 120, 6: 151, 7: 181, 8: 243, 9: 273, 10: 304, 11: 334, + 12: 365} + self.month = -100 # Default value. + +
+[docs] + def get_prices(self, start_idx, num_steps, month=7): + """ + Returns time-of-use (TOU) rate prices from data. This assumes TOU rates do not change day-to-day. + + :param int start_idx: Starting index from which to price vector will start. + :param int num_steps: Cardinality of the price vector being returned. + :param int month: Month for which the price vector will be obtained (for example, 1 - Jan, 12 - December). + :return ndarray price_vector: The TOU price vector, which is a numpy array. + """ + price_vector = self.data_np[start_idx:start_idx + num_steps] + price_vector = price_vector.reshape(-1, 1) + return price_vector
+ + +
+[docs] + def set_month_data(self, month): + """ + Sets the month for which the prices will be obtained. + + :param month: Month to set the data to. + :return: None. + """ + if self.month != month: + self.data_np = self.data.to_numpy()[self.month_start_idx[month] * 96:self.month_start_idx[month + 1] * 96]
+ + +
+[docs] + def downscale(self, input_res, output_res): + """ + Downscales the price data into a finer resolution, similar to the downscaling method in Pandas. + Typically only used once. + + :param input_res: Resolution of the input data. + :param output_res: Resolution of the output data. + :return: None. Saves output data to a csv file. + """ + input_data_shape = len(self.data_np[:, 0]) + num_repetitions = int(input_res / output_res) + assert num_repetitions == 4 # JUST AN INITIAL CHECK, REMOVE LATER + temp_data = np.zeros(input_data_shape * num_repetitions) + start_idx = 0 + for datapoint in self.data_np: + # print(datapoint) + temp_data[start_idx:start_idx + num_repetitions] = datapoint + start_idx += 4 + self.data = pd.DataFrame(data=temp_data) + self.data_np = temp_data + # IMPORTANT: Change the paths below to save new data. + np.savetxt(self.path_prefix + "/elec_rates/PGE_BEV2_S_annual_TOU_rate_{}min.csv".format(output_res), temp_data)
+
+ + + +
+[docs] +def main(): + """This is only run to generate new downscaled data or for testing.""" + import os + import json + path_prefix = os.getcwd() + path_prefix = path_prefix[0:path_prefix.index('EV50_cosimulation')] + 'EV50_cosimulation' + path_prefix = path_prefix.replace('\\', '/') + with open(path_prefix + '/charging_sim/configs/prices.json', "r") as f: + config = json.load(f) + loader = PriceLoader(config, path_prefix=path_prefix) + desired_res = 15 # units are in minutes + loader.downscale(config['resolution'], desired_res)
+ + + +if __name__ == "__main__": + main() +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/build/_modules/charging_sim/optimization.html b/docs/build/_modules/charging_sim/optimization.html new file mode 100644 index 000000000..ded41d94b --- /dev/null +++ b/docs/build/_modules/charging_sim/optimization.html @@ -0,0 +1,259 @@ + + + + + + charging_sim.optimization — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for charging_sim.optimization

+"""Contains the Optimization class, which is used by controller to solve the optimization problem."""
+
+import cvxpy as cp
+
+
+
+[docs] +class Optimization: + """ + Constructor for the overall optimization problem solved by the optimization-based controller. + + * Designed to include future cost functions such as transformer degradation and battery aging. + * Limited to convex and Mixed Integer programs, depending on the selected solver. + * Note, each desired solver must be installed separately on user's PC for a successful run. + + :param objective_type: Type of objective problem being optimized. + :param objective: CVXPY objective function object. + :param controller: Controller object. + :param power_demand: Power demand at the Charging Station. + :param time_res: Time resolution of problem data. + :param transformer: Transformer object (optional, not implemented yet). + :param battery: Battery object. + :param time: Time Counter. + :param name: Optimization identifier. + :param solar: Solar Object. + :param str solver: Available backend solver to invoke (ECOS, MOSEK, GUROBI, etc.). + + """ + + # TODO: change all refs to battery_constraints to call controller + def __init__(self, objective_type, objective, controller, power_demand, time_res, transformer, battery, time=0, + name=None, solar=None, solver='GUROBI'): + + self._objective_type = objective_type + self._objective = objective + self._name = name + self._time = time + self._constraints = [] + self.test_demand = power_demand + self.time_res = time_res + self.charge = 0 + self.discharge = 0 + self.transformer = transformer + self.battery = battery + self.solar = solar + self.controller = controller # update this somewhere else in simulation + self.problem = None + self.market_constraints = None + self.battery_constraints = controller.get_battery_constraints(power_demand) + self.cost_per_opt = [] + self.solver = getattr(cp, solver) + if solar: + setattr(self, 'solar', solar) + +
+[docs] + def build_emissions_cost(self): + """ + Builds emission cost to be included in the objective function (future work). + + :return: + """ + pass
+ + +
+[docs] + def build_battery_cost(self): + """ + Build battery cost (to be implemented in future version). + + :return: + """ + pass
+ + +
+[docs] + def build_transformer_cost(self): + """ + Build Transformer cost (to be implemented in future version). + + :return: + """ + pass
+ + +
+[docs] + def add_demand_charge(self, charge): + """ + Including demand charge in the objective function (Deprecated). + + :param charge: Demand charge ($/kW). + :return: + """ + load = 0 # placeholder + cost = charge * load + (self.controller.battery_power_charge + + self.controller.battery_power_discharge - + self.solar.battery_power - self.solar.ev_power)
+ + +
+[docs] + def get_battery_constraint(self): + """ + Returns the list of battery constraints within the controller. + + :return: Battery constraints. + """ + return self.battery_constraints
+ + +
+[docs] + def aggregate_constraints(self): + """ + Aggregates all the constraints into one constraint list within the object. + + :return: None. + """ + if self.battery_constraints: # fix this later to call battery directly + self._constraints.extend(self.battery_constraints) + if self.market_constraints: + self._constraints.extend(self.market_constraints) + if self.solar: + self._constraints.extend(self.solar.get_constraints())
+ + +
+[docs] + def get_constraints(self): + """ + Returns the constraints list. + + :return: List of all constraints within the problem. + """ + return self._constraints
+ + +
+[docs] + def run(self): + """ + Runs an instance of the optimization problem. + + :return float: Optimal objective value. + """ + self.aggregate_constraints() # aggregate constraints + problem = cp.Problem(cp.Minimize(self._objective), self._constraints) + self.problem = problem + result = problem.solve(solver=self.solver, verbose=False) + self.cost_per_opt.append(result) + # print(problem.status) ACTIVATE LATER + return result
+
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/build/_modules/charging_sim/solar.html b/docs/build/_modules/charging_sim/solar.html new file mode 100644 index 000000000..93317b7c5 --- /dev/null +++ b/docs/build/_modules/charging_sim/solar.html @@ -0,0 +1,260 @@ + + + + + + charging_sim.solar — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for charging_sim.solar

+"""
+This module contains the Solar class. The solar class is used to simulate the solar power generation at a given site
+by sampling Global Horizontal Irradiance (GHI) data from the dataset of the desired location.
+"""
+
+import numpy as np
+import pandas as pd
+import cvxpy as cp
+
+
+
+[docs] +class Solar: + """ + This class is used to simulate the solar power generation at a given site by sampling Global Horizontal Irradiance + and estimating the solar generation, given the solar nameplate capacity that can be modified it its configuration + file `solar.json`. It also contains the optimization variables for the solar system. + + The solar power generation is estimated using the following equation: + + .. math:: + P_{solar} = \min(P_{rated}, \eta * A * GHI). + + Where :math:`P_{solar}` is the solar power generation, :math:`\eta` is the efficiency of the solar system, + :math:`P_{rated}` is the solar nameplate capacity, :math:`A` is the area of the solar panels, and :math:`GHI` is + the Global Horizontal Irradiance. + + :param config: Solar configuration dictionary. + :param path_prefix: This string path prefix is obtained first based on your repository location to set the right path. + :param controller: Controller object for making decisions on flow of power from energy devices. + :param num_steps: Number of steps in the simulation. + + """ + + def __init__(self, config, path_prefix=None, controller=None, num_steps=None): + """ + + :param config: + :param path_prefix: + :param controller: + :param num_steps: + """ + self.path_prefix = path_prefix + '/' + self.config = config + cols = ['Month', 'Day', 'Hour', 'GHI', 'Temperature'] + self.cols = cols + self.controller = controller + if num_steps: + self.num_steps = num_steps + else: + self.num_steps = self.config["num steps"] + self.solar_df = pd.read_csv(self.path_prefix+self.config["data_path"])[cols] + self.solar_vec = self.solar_df.to_numpy() + self.location = self.config["location"] + self.start_year = self.config["start_year"] + self.start_month = self.config["start_month"] + self.start_day = self.config["start_day"] + self.efficiency = self.config["efficiency"] + self.resolution = self.config["resolution"] + self.input_data_res = self.config["input_res"] + self.sample_start_idx = self.config["sample_start_idx"] + self.sample_end_idx = self.config["sample_end_idx"] + self.rating = self.config['rating'] * 1000 # convert from MW to kW + self.area = self.rating * 1000 / 150 # approximate area using 150W/m2 + self.data = None + # self.data_np = None + self.data_np = self.solar_df[self.solar_df["Month"] == self.start_month]['GHI'].to_numpy() + self.battery_power = cp.Variable((self.num_steps, 1), nonneg=True) # solar power to battery + self.ev_power = cp.Variable((self.num_steps, 1), nonneg=True) # solar power to ev + self.grid_power = cp.Variable((self.num_steps, 1), nonneg=True) # TODO: consider including this in future work + self.power = None + self.constraints = [] + self.month = self.start_month # initializing for the start of the simulation + self.id = None + self.node = None + +
+[docs] + def get_power(self, start_idx, num_steps, desired_shape=(96, 1), month=None): + if month is not None and self.month != month: + # GHI = Global Horizontal Irradiance + print("setting month for solar power...") + self.data_np = self.solar_df[self.solar_df["Month"] == month]['GHI'].to_numpy() # for one month + self.month = month # set month to current desired month + self.power = self.data_np[start_idx:start_idx+num_steps] / 1000 # convert to kW + self.power = np.minimum(self.rating, np.reshape(self.power, desired_shape) * self.efficiency * self.area) + # this ignores area for now. Can look at potential land-use/space use in future work + return self.power
+ + +
+[docs] + def modify_res(self, new_res): + pass
+ + +
+[docs] + def downscale(self, input_res, output_res): + """This is used only to initially downscale data to desired resolution""" + num_repetitions = int(input_res / output_res) + assert num_repetitions == 2 # JUST AN INITIAL CHECK, REMOVE LATER + temp_data = np.zeros((self.solar_vec.shape[0]*num_repetitions, self.solar_vec.shape[1])) + start_idx = 0 + for datapoint in self.solar_vec: + # print(datapoint) + temp_data[start_idx:start_idx + num_repetitions] = datapoint + start_idx += num_repetitions + self.data = pd.DataFrame(data=temp_data, columns=self.cols) + self.data_np = temp_data + path_suffix = self.config['data_path'].split('-')[0] + self.data.to_csv(self.path_prefix+path_suffix + f"-{output_res}min.csv")
+ + +
+[docs] + def get_solar_output(self): + return self.data_np * self.efficiency * self.area / 1000 # this is in kW
+ + +
+[docs] + def get_constraints(self): + self.constraints = [self.battery_power + self.ev_power + self.grid_power == self.power] + return self.constraints
+ + +
+[docs] + def update_history(self): + # CODE IS NOT UPDATING ALL THE ACTIONS SO THERE IS A BUG THERE + #TODO: add solar history update + return NotImplementedError
+
+ + + +
+[docs] +def main(): + """THis is mainly to testing or generating new data purposes""" + import os + import json + # load input data + path_prefix = os.getcwd() + path_prefix = path_prefix[:path_prefix.index('EV50_cosimulation')] + 'EV50_cosimulation' + path_prefix = path_prefix.replace('\\', '/') + with open(path_prefix+'/charging_sim/configs/solar.json', "r") as f: + config = json.load(f) + solar = Solar(config, path_prefix=path_prefix) + desired_res = 15 + # input res, desired res + solar.downscale(30, desired_res)
+ + + +if __name__ == "__main__": + main() +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/build/_modules/charging_sim/utils.html b/docs/build/_modules/charging_sim/utils.html new file mode 100644 index 000000000..953ba7a39 --- /dev/null +++ b/docs/build/_modules/charging_sim/utils.html @@ -0,0 +1,251 @@ + + + + + + charging_sim.utils — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for charging_sim.utils

+"""Maybe stores general configurations and general functions"""
+import cvxpy as cp
+import numpy as np
+import matplotlib.pyplot as plt
+
+day_hours = 24
+day_minutes = day_hours * 60
+resolution = 15  # minutes
+num_homes = 1
+num_steps = int(day_minutes / resolution)  # number of time intervals in a day = 96
+month_days = {"January": 31, "February": 28, "March": 31, "April": 30, "May": 31, "June": 30, "July": 31,
+              "August": 31, "September": 30, "October": 30, "November": 30, "December": 31}
+
+objectives = {'Transformer Aging': [0, 0, 1],
+              "Electricity Cost": [1, 0, 0],
+              "Battery Degradation": [1, 200, 0],
+              'Air Pollution': [],
+              "Mixed": [0.1, 1, 0],
+              "All": [1, 100, 1]}  # modifies weight placed on multi-obj based on priority/case study
+
+
+
+[docs] +def PGE_BEV2_S(): + """Price schedule/TOU rate for PGE EVSE doc can be found here:""" + peak = 0.39601 # $/kWh + off_peak = 0.18278 # $/kWh + super_off_peak = 0.15951 # $/kWh + peak_times = ["4PM-9PM"] + off_peak_times = ["12AM-9AM", "2PM-4PM", "9PM-12AM"] + super_off_peak_times = ["9AM-2PM"] + hourly_prices = np.zeros((24,)) + hourly_prices = load_prices(peak_times, peak, hourly_prices) + hourly_prices = load_prices(off_peak_times, off_peak, hourly_prices) + hourly_prices = load_prices(super_off_peak_times, super_off_peak, hourly_prices) + times = [f'{int(i)}:00' for i in range(24)] + plt.figure(figsize=(10, 8)) + plt.rcParams.update({'font.size': 16}) + plt.xticks(rotation=60, ha="right") + plt.plot(times, hourly_prices) + plt.xlabel("Hour of day") + plt.ylabel("TOU rate ($/kWh)") + plt.tight_layout() + plt.show() + # np.save + return hourly_prices
+ + + +
+[docs] +def load_prices(time_intervals, price, price_vector): + for interval in time_intervals: + interval_list = interval.split('-') + for i in range(len(interval_list)): + if interval_list[i] == '12AM' and i == 0: + interval_list[i] = 0 + elif interval_list[i] == '12AM': + interval_list[i] = 24 + else: + interval_list[i] = int(interval_list[i][:-2]) if interval_list[i][-2] == 'A' else int( + interval_list[i][:-2]) + 12 + price_vector[interval_list[0]:interval_list[1]] = price + return price_vector
+ + + +
+[docs] +def build_electricity_cost(controller, load, energy_prices_TOU, demand_charge=False): + """Need to update from home load right now; maybe this can be useful in future opt.""" + cost_electricity = cp.sum((cp.multiply(energy_prices_TOU, (load + controller.battery_power - + controller.solar.battery_power - + controller.solar.ev_power)))) + if demand_charge: + demand_charge_cost = cp.max(cp.pos(load + (controller.battery_power_charge + + controller.battery_power_discharge - + controller.solar.battery_power - + controller.solar.ev_power))) + cost_electricity += demand_charge_cost + return cost_electricity
+ + + +
+[docs] +def build_cost_PGE_BEV2S(controller, load, energy_prices_TOU, penalize_max_power=True, max_power_pen=1000): + """This will need to use a heuristic and take the average conservative estimate for gamma""" + net_grid_load = load + controller.battery_power - controller.solar.battery_power - controller.solar.ev_power + TOU_cost = cp.sum(cp.multiply(energy_prices_TOU, net_grid_load)) * controller.resolution/60 # ($) + smoothness_pen = np.mean(cp.abs(controller.battery_power[:-1] - controller.battery_power[1:])) + smoothness_alpha = 0 + price_per_block = 95.56 # ($/Block) + overage_fee = 3.82 # ($/kW) + charging_block = controller.pge_gamma * 50 # gamma is an integer variable that's at least 1 + subscription_cost = controller.pge_gamma * price_per_block # This is in blocks of 50kW which makes it very convenient ($/day) + penalty_cost = cp.max(cp.neg(charging_block - net_grid_load) * overage_fee) # ($) + if penalize_max_power: + return subscription_cost + penalty_cost + TOU_cost + max_power_pen * cp.max(cp.abs(net_grid_load)) + # return subscription_cost + penalty_cost + TOU_cost + max_power_pen*cp.max(net_grid_load) + return subscription_cost + penalty_cost + TOU_cost + smoothness_pen * smoothness_alpha
+ + + +
+[docs] +def build_objective(mode, electricity_cost, battery_degradation_cost, transformer_cost=0): + """Builds the objective function that we will minimize.""" + lambdas = objectives[mode] + return cp.sum( + electricity_cost * lambdas[0] + + battery_degradation_cost * lambdas[1] + + transformer_cost * lambdas[2] + )
+ + + +
+[docs] +def add_power_profile_to_object(battery, index, battery_power_profile): + if 1 <= index <= 31: + battery.power_profile['Jan'].append(battery_power_profile) + if 32 <= index <= 59: + battery.power_profile['Feb'].append(battery_power_profile) + if 60 <= index <= 90: + battery.power_profile['Mar'].append(battery_power_profile) + if 91 <= index <= 120: + battery.power_profile['Apr'].append(battery_power_profile) + if 121 <= index <= 151: + battery.power_profile['May'].append(battery_power_profile) + if 152 <= index <= 181: + battery.power_profile['Jun'].append(battery_power_profile) + if 182 <= index <= 212: + battery.power_profile['Jul'].append(battery_power_profile) + if 213 <= index <= 233: + battery.power_profile['Aug'].append(battery_power_profile) + if 234 <= index <= 263: + battery.power_profile['Sep'].append(battery_power_profile) + if 264 <= index <= 294: + battery.power_profile['Oct'].append(battery_power_profile) + if 295 <= index <= 334: + battery.power_profile['Nov'].append(battery_power_profile) + if 335 <= index <= 365: + battery.power_profile['Dec'].append(battery_power_profile)
+ + + +if __name__ == '__main__': + PGE_BEV2_S() +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/build/_modules/feeder_population/glm_mod_functions.html b/docs/build/_modules/feeder_population/glm_mod_functions.html new file mode 100644 index 000000000..517f47beb --- /dev/null +++ b/docs/build/_modules/feeder_population/glm_mod_functions.html @@ -0,0 +1,432 @@ + + + + + + feeder_population.glm_mod_functions — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for feeder_population.glm_mod_functions

+"""
+Functions for modifying GridLAB-D power system simulation models
+"""
+import os
+
+
+
+[docs] +def load_base_glm(base_file_dir, base_glm_file): + """ + Loads the glm as list and populates it into dict and returns the output + + :param base_file_dir: + :param base_glm_file: + :return: + """ + os.chdir(base_file_dir) + f = open(base_glm_file, 'r') + glm=f.readlines() + + glm_dict={} + obj_type={} + glm_list=list() + globals_list=list() + include_list=list() + sync_list=list() + + #edit out all comments + for l in glm: + line_temp=l.lstrip().rstrip().rstrip('\n').split('//')[0] # is the // encoding something + #Comment somewhere in line + if len(line_temp)>1: + #There is some content in line, extract content + if l.split('//')[0]!='': + glm_list.append(line_temp.rstrip()) # this adds to glm list lines that are not comments + #No comment in line + else: + #Line is not a space + if line_temp!='': + glm_list.append(line_temp) + + obj_num=0 + obj_flag=0 + #put info into dict structure + for l in glm_list: + #Setting global variable + if l[0:4]=='#set': + globals_list.append(l) + elif l[0:8]=='#include': + include_list.append(l) + elif 'object' in l: + obj_flag=1 + line_temp=l.rstrip('{').rstrip().split(' ') + obj_type[obj_num]={'object':line_temp[1]} + prop_num=0 + elif ('class' in l) and obj_flag==0: + obj_flag=1 + line_temp=l.rstrip('{').rstrip().split(' ') + obj_type[obj_num]={'class':line_temp[1]} + prop_num=0 + elif 'module' in l: + obj_flag=1 + line_temp=l.rstrip('{').rstrip().split(' ') + #if no properties in object + if ';' in line_temp[1]: + obj_type[obj_num]={'module':line_temp[1].rstrip(';')} + obj_flag=0 + glm_dict[obj_num]={} + obj_num=obj_num+1 + #if properties in object + else: + obj_type[obj_num]={'module':line_temp[1]} + obj_flag=1 + prop_num=0 + elif 'clock' in l: + obj_flag=1 + obj_type[obj_num]={'clock':'clock'} + prop_num=0 + elif 'script' in l: + sync_list.append(l) + + + elif l=='}' or l=='};': + obj_num=obj_num+1 + obj_flag=0 + else: + if obj_flag==1: + line_temp=l.split(' ',maxsplit=1) + if prop_num==0: + glm_dict[obj_num]={line_temp[0]:line_temp[1].rstrip(';')} + prop_num=prop_num+1 + else: + glm_dict[obj_num][line_temp[0]]=line_temp[1].rstrip(';') + else: + print('error') + print(l) + return glm_dict,obj_type,globals_list,include_list,sync_list
+ + + +
+[docs] +def write_base_glm(glm_dict,obj_type,globals_list,include_list,out_dir,file_name,sync_list): + """ + Writes the glm file from the dict structure. + + :param glm_dict: + :param obj_type: + :param globals_list: + :param include_list: + :param out_dir: + :param file_name: + :param sync_list: + :return: + """ + os.chdir(out_dir) + glm_out = open(file_name,"w+") + + + for i in range(len(globals_list)): + glm_out.write(globals_list[i]+'\n\n') + + for i in glm_dict.keys(): + #for i in range(len(glm_dict)): + if 'clock' in obj_type[i].keys(): + write_clock_dict(glm_out,glm_dict[i]) + + for i in glm_dict.keys(): + #for i in range(len(glm_dict)): + if 'module' in obj_type[i].keys(): + write_mod_dict(glm_out,glm_dict[i],obj_type[i]['module']) + + for i in range(len(include_list)): + glm_out.write(include_list[i]+'\n\n') + + for i in glm_dict.keys(): + if 'filter' in obj_type[i].keys(): + write_filter_dict(glm_out,glm_dict[i],obj_type[i]['filter']) + + for i in glm_dict.keys(): + if 'class' in obj_type[i].keys(): + write_class_dict(glm_out,glm_dict[i],obj_type[i]['class']) + + for i in glm_dict.keys(): + #for i in range(len(glm_dict)): + if 'object' in obj_type[i].keys(): + if 'player' in obj_type[i]['object']: + write_obj_dict(glm_out,glm_dict,i,obj_type[i]['object']) + + for i in glm_dict.keys(): + #for i in range(len(glm_dict)): + if 'object' in obj_type[i].keys(): + if ('player' in obj_type[i]['object'])==False: + write_obj_dict(glm_out,glm_dict,i,obj_type[i]['object']) + + for i in range(len(sync_list)): + glm_out.write(sync_list[i]+'\n\n') + + glm_out.close()
+ + + +
+[docs] +def write_obj_dict(file,gld_dict,dict_key,obj_type): + """ + Write dictionary corresponding to GLD objects to .glm file. + + :param file: + :param gld_dict: + :param dict_key: + :param obj_type: + :return: + """ + if dict_key==-1: + file.write('object '+obj_type+' {\n') + for i,j in gld_dict.items(): + file.write('\t'+str(i)+' '+str(j)+';\n') + file.write('}\n\n') + else: + file.write('object '+obj_type+' {\n') + for i,j in gld_dict[dict_key].items(): + file.write('\t'+str(i)+' '+str(j)+';\n') + file.write('}\n\n')
+ + + +
+[docs] +def write_mod_dict(file,gld_dict,mod_name): + """ + Write dictionary corresponding to GLD module to .glm file. + + :param file: + :param gld_dict: + :param mod_name: + :return: + """ + if len(gld_dict)==0: + file.write('module '+mod_name+';\n\n') + else: + file.write('module '+mod_name+' {\n') + for i,j in gld_dict.items(): + file.write('\t'+str(i)+' '+str(j)+';\n') + file.write('}\n\n')
+ + + +
+[docs] +def write_class_dict(file,gld_dict,class_name): + """ + Write dictionary corresponding to GLD class to .glm file. + + :param file: + :param gld_dict: + :param class_name: + :return: + """ + if len(gld_dict)==0: + file.write('class '+class_name+';\n\n') + else: + file.write('class '+class_name+' {\n') + for i,j in gld_dict.items(): + file.write('\t'+str(i)+' '+str(j)+';\n') + file.write('}\n\n')
+ + + +
+[docs] +def write_filter_dict(file,gld_dict,class_name): + """ + Write dictionary corresponding to GLD filter to .glm file. + + :param file: + :param gld_dict: + :param class_name: + :return: + """ + if len(gld_dict)==0: + file.write('filter '+class_name+';\n\n') + else: + file.write('filter '+class_name+' {\n') + for i,j in gld_dict.items(): + file.write('\t'+str(i)+' '+str(j)+';\n') + file.write('}\n\n')
+ + + +
+[docs] +def write_clock_dict(file,gld_dict): + """ + Write dictionary corresponding to GLD clock to .glm file. + + :param file: + :param gld_dict: + :return: + """ + file.write('clock {\n') + for i,j in gld_dict.items(): + file.write('\t'+str(i)+' '+str(j)+';\n') + file.write('}\n\n')
+ + + +
+[docs] +def replace_load_w_meter_old(glm_dict,match_str,rep_str,obj_type): + """ + Replace all instances of load in glm_dict with meter. + + :param glm_dict: + :param match_str: + :param rep_str: + :param obj_type: + :return: + """ + replace_prop_list=list() + for i in glm_dict.keys(): + if match_str in glm_dict[i].values(): + replace_prop_list.append(i) + for i in replace_prop_list: + for prop in glm_dict[i].keys(): + if glm_dict[i][prop]==match_str: + glm_dict[i][prop]=rep_str + if obj_type[i]['object']=='load' and prop[0:8]=='constant': + delete_index=i + delete_prop=prop + + if obj_type[i]['object']=='load': + obj_type[i]['object']='meter' + del glm_dict[delete_index][delete_prop] + return glm_dict
+ + + +
+[docs] +def replace_load_w_meter(glm_dict,match_str,rep_str,obj_type): + """ + Replace all instances of load in glm_dict with meter. + + :param glm_dict: + :param match_str: + :param rep_str: + :param obj_type: + :return: + """ + replace_prop_list=list() + for i in glm_dict.keys(): + if match_str in glm_dict[i].values(): + replace_prop_list.append(i) + delete_index_list=[] + delete_prop_list=[] + for i in replace_prop_list: + for prop in glm_dict[i].keys(): + if glm_dict[i][prop]==match_str: + glm_dict[i][prop]=rep_str + if obj_type[i]['object']=='load' and prop[0:8]=='constant': + delete_index_list.append(i) + delete_prop_list.append(prop) + + if obj_type[i]['object']=='load': + obj_type[i]['object']='meter' + for i in range(len(delete_index_list)): + del glm_dict[delete_index_list[i]][delete_prop_list[i]] + return glm_dict
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/build/_modules/index.html b/docs/build/_modules/index.html new file mode 100644 index 000000000..4003d1bec --- /dev/null +++ b/docs/build/_modules/index.html @@ -0,0 +1,110 @@ + + + + + + Overview: module code — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+ + +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/build/_modules/test_cases/battery/feeder_population/glm_mod_functions.html b/docs/build/_modules/test_cases/battery/feeder_population/glm_mod_functions.html new file mode 100644 index 000000000..226f2663d --- /dev/null +++ b/docs/build/_modules/test_cases/battery/feeder_population/glm_mod_functions.html @@ -0,0 +1,432 @@ + + + + + + test_cases.battery.feeder_population.glm_mod_functions — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for test_cases.battery.feeder_population.glm_mod_functions

+"""
+Module contains functions for modifying GridLAB-D power system simulation models
+"""
+import os
+
+
+
+[docs] +def load_base_glm(base_file_dir,base_glm_file): + """ + Loads base glm file into a dictionary structure. + + :param base_file_dir: + :param base_glm_file: + :return: + """ + + os.chdir(base_file_dir) + f = open(base_glm_file, 'r') + glm=f.readlines() + + glm_dict={} + obj_type={} + glm_list=list() + globals_list=list() + include_list=list() + sync_list=list() + + #edit out all comments + for l in glm: + line_temp=l.lstrip().rstrip().rstrip('\n').split('//')[0] + #Comment somewhere in line + if len(line_temp)>1: + #There is some content in line, extract content + if l.split('//')[0]!='': + glm_list.append(line_temp.rstrip()) + #No comment in line + else: + #Line is not a space + if line_temp!='': + glm_list.append(line_temp) + + obj_num=0 + obj_flag=0 + #put info into dict structure + for l in glm_list: + #Setting global variable + if l[0:4]=='#set': + globals_list.append(l) + elif l[0:8]=='#include': + include_list.append(l) + elif 'object' in l: + obj_flag=1 + line_temp=l.rstrip('{').rstrip().split(' ') + obj_type[obj_num]={'object':line_temp[1]} + prop_num=0 + elif ('class' in l) and obj_flag==0: + obj_flag=1 + line_temp=l.rstrip('{').rstrip().split(' ') + obj_type[obj_num]={'class':line_temp[1]} + prop_num=0 + elif 'module' in l: + obj_flag=1 + line_temp=l.rstrip('{').rstrip().split(' ') + #if no properties in object + if ';' in line_temp[1]: + obj_type[obj_num]={'module':line_temp[1].rstrip(';')} + obj_flag=0 + glm_dict[obj_num]={} + obj_num=obj_num+1 + #if properties in object + else: + obj_type[obj_num]={'module':line_temp[1]} + obj_flag=1 + prop_num=0 + elif 'clock' in l: + obj_flag=1 + obj_type[obj_num]={'clock':'clock'} + prop_num=0 + elif 'script' in l: + sync_list.append(l) + + + elif l=='}' or l=='};': + obj_num=obj_num+1 + obj_flag=0 + else: + if obj_flag==1: + line_temp=l.split(' ',maxsplit=1) + if prop_num==0: + glm_dict[obj_num]={line_temp[0]:line_temp[1].rstrip(';')} + prop_num=prop_num+1 + else: + glm_dict[obj_num][line_temp[0]]=line_temp[1].rstrip(';') + else: + print('error') + print(l) + return glm_dict,obj_type,globals_list,include_list,sync_list
+ + + +
+[docs] +def write_base_glm(glm_dict,obj_type,globals_list,include_list,out_dir,file_name,sync_list): + """ + + :param glm_dict: + :param obj_type: + :param globals_list: + :param include_list: + :param out_dir: + :param file_name: + :param sync_list: + :return: + """ + os.chdir(out_dir) + glm_out = open(file_name,"w+") + + + for i in range(len(globals_list)): + glm_out.write(globals_list[i]+'\n\n') + + for i in glm_dict.keys(): + #for i in range(len(glm_dict)): + if 'clock' in obj_type[i].keys(): + write_clock_dict(glm_out,glm_dict[i]) + + for i in glm_dict.keys(): + #for i in range(len(glm_dict)): + if 'module' in obj_type[i].keys(): + write_mod_dict(glm_out,glm_dict[i],obj_type[i]['module']) + + for i in range(len(include_list)): + glm_out.write(include_list[i]+'\n\n') + + for i in glm_dict.keys(): + if 'filter' in obj_type[i].keys(): + write_filter_dict(glm_out,glm_dict[i],obj_type[i]['filter']) + + for i in glm_dict.keys(): + if 'class' in obj_type[i].keys(): + write_class_dict(glm_out,glm_dict[i],obj_type[i]['class']) + + for i in glm_dict.keys(): + #for i in range(len(glm_dict)): + if 'object' in obj_type[i].keys(): + if 'player' in obj_type[i]['object']: + write_obj_dict(glm_out,glm_dict,i,obj_type[i]['object']) + + for i in glm_dict.keys(): + #for i in range(len(glm_dict)): + if 'object' in obj_type[i].keys(): + if ('player' in obj_type[i]['object'])==False: + write_obj_dict(glm_out,glm_dict,i,obj_type[i]['object']) + + for i in range(len(sync_list)): + glm_out.write(sync_list[i]+'\n\n') + + glm_out.close()
+ + + +
+[docs] +def write_obj_dict(file,gld_dict,dict_key,obj_type): + """ + Write dictionary corresponding to GLD objects to .glm file + + :param file: + :param gld_dict: + :param dict_key: + :param obj_type: + :return: + """ + if dict_key==-1: + file.write('object '+obj_type+' {\n') + for i,j in gld_dict.items(): + file.write('\t'+str(i)+' '+str(j)+';\n') + file.write('}\n\n') + else: + file.write('object '+obj_type+' {\n') + for i,j in gld_dict[dict_key].items(): + file.write('\t'+str(i)+' '+str(j)+';\n') + file.write('}\n\n')
+ + + +
+[docs] +def write_mod_dict(file,gld_dict,mod_name): + """ + Write dictionary corresponding to GLD module to .glm file' + + :param file: + :param gld_dict: + :param mod_name: + :return: + """ + if len(gld_dict)==0: + file.write('module '+mod_name+';\n\n') + else: + file.write('module '+mod_name+' {\n') + for i,j in gld_dict.items(): + file.write('\t'+str(i)+' '+str(j)+';\n') + file.write('}\n\n')
+ + + +
+[docs] +def write_class_dict(file,gld_dict,class_name): + """ + Write dictionary corresponding to GLD class to .glm file. + + :param file: + :param gld_dict: + :param class_name: + :return: + """ + if len(gld_dict)==0: + file.write('class '+class_name+';\n\n') + else: + file.write('class '+class_name+' {\n') + for i,j in gld_dict.items(): + file.write('\t'+str(i)+' '+str(j)+';\n') + file.write('}\n\n')
+ + + +
+[docs] +def write_filter_dict(file,gld_dict,class_name): + """ + Write dictionary corresponding to GLD filter to .glm file. + + :param file: + :param gld_dict: + :param class_name: + :return: + """ + if len(gld_dict)==0: + file.write('filter '+class_name+';\n\n') + else: + file.write('filter '+class_name+' {\n') + for i,j in gld_dict.items(): + file.write('\t'+str(i)+' '+str(j)+';\n') + file.write('}\n\n')
+ + + +
+[docs] +def write_clock_dict(file,gld_dict): + """ + Write dictionary corresponding to GLD clock to .glm file. + + :param file: + :param gld_dict: + :return: + """ + file.write('clock {\n') + for i,j in gld_dict.items(): + file.write('\t'+str(i)+' '+str(j)+';\n') + file.write('}\n\n')
+ + + +
+[docs] +def replace_load_w_meter_old(glm_dict,match_str,rep_str,obj_type): + """ + Replace load with meter in GLM dictionary. + + :param glm_dict: + :param match_str: + :param rep_str: + :param obj_type: + :return: + """ + replace_prop_list=list() + for i in glm_dict.keys(): + if match_str in glm_dict[i].values(): + replace_prop_list.append(i) + for i in replace_prop_list: + for prop in glm_dict[i].keys(): + if glm_dict[i][prop]==match_str: + glm_dict[i][prop]=rep_str + if obj_type[i]['object']=='load' and prop[0:8]=='constant': + delete_index=i + delete_prop=prop + + if obj_type[i]['object']=='load': + obj_type[i]['object']='meter' + del glm_dict[delete_index][delete_prop] + return glm_dict
+ + + +
+[docs] +def replace_load_w_meter(glm_dict,match_str,rep_str,obj_type): + """ + Replace load with meter in GLM dictionary. + + :param glm_dict: + :param match_str: + :param rep_str: + :param obj_type: + :return: + """ + replace_prop_list=list() + for i in glm_dict.keys(): + if match_str in glm_dict[i].values(): + replace_prop_list.append(i) + delete_index_list=[] + delete_prop_list=[] + for i in replace_prop_list: + for prop in glm_dict[i].keys(): + if glm_dict[i][prop]==match_str: + glm_dict[i][prop]=rep_str + if obj_type[i]['object']=='load' and prop[0:8]=='constant': + delete_index_list.append(i) + delete_prop_list.append(prop) + + if obj_type[i]['object']=='load': + obj_type[i]['object']='meter' + for i in range(len(delete_index_list)): + del glm_dict[delete_index_list[i]][delete_prop_list[i]] + return glm_dict
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/build/_sources/README.md.txt b/docs/build/_sources/README.md.txt new file mode 100644 index 000000000..426c10499 --- /dev/null +++ b/docs/build/_sources/README.md.txt @@ -0,0 +1,170 @@ +# EV-Ecosim platform + +A grid-aware co-simulation platform for the design and optimization of electric vehicle charging stations. +Paper: https://doi.org/10.36227/techrxiv.23596725.v2 + +[//]: # () + +![sim_frame.png](doc_images%2Fsim_frame.png) + +[//]: # (EV-Ecosim Framework Description) + +## Authors +Emmanuel Balogun: ebalogun@stanford.edu, Lily Buechler: ebuech@stanford.edu + + +## Requirements + +GiSMo SLAC GridLAB-D installation (master branch): https://github.com/arras-energy/gridlabd. +This GridLAB-D version is required for the python co-simulation functionality. Recommended use with AWS EC2 SLAC +GiSMo HiPAS GridLAB-D AMI (beauharnois-X). + +## Folder descriptions + +### ambient_data + +Hosts ambient temperature data for capturing the effects of environmental conditions on subsystems, such as battery, +transformers, charging stations. + + +### base_load_data + +Includes existing base case building/home load (usually uncontrollable) within the distribution grid. This work uses +proprietary Pecan Street Data. Below is an exmaple data prototype for the base load data. Note that column fields are +case-sensitive. The data used in the original paper has a minute resolution, as is the power system simulation. `` + +Base load data prototype. + +[//]: # (![baseload_data_proto.png](doc_images%2Fbaseload_data_proto.png)) + + +### batt_sys_identification +Battery system identification module. Hosts the class for generating battery system identification parameters +from experimental data. This module leverages a genetic algorithm to optimize the battery model parameters. +The battery model is a 2nd order RC Equivalent circuit model (ECM). One can this module to generate custom NMC +battery parameters by uploading experimental data to the `batt_sys_identification/data` folder and running the module. +The module will generate a `.csv` file with the battery parameters in the `batt_sys_identification/params` folder. +The data prototype is shown below. Note that column fields are case-sensitive. + +![batt_sys_data_proto.png](doc_images%2Fbatt_sys_data_proto.png) + +The module will save a new `.csv` file with an additional field for the corrected open circuit voltage (OCV) values; +this field (column) will be labelled `ocv_corr` within the new battery data csv, including the existing columns as shown +in the data prototype above. + +Once the battery parameters are generated, they can be used in the `battery_data` folder and `configs/battery.json` can +be modified so the model runs using the new custom parameters. + +### charging_sim + +This contains the `configs` folder which includes the configuration files for all the relevant modules.Hosts the implementation of the physical modules, including: +##### `battery.py` - Battery cell module. +##### `batterypack.py` - Battery pack module. +##### `batteryAgingSim.py` - Battery aging module. +##### `controller.py` - Controller module. +##### `chargingStation.py` - Charging station module. +##### `electricityPrices.py` - Electricity prices module. +##### `optimization.py` - Optimization module. +##### `orchestrator.py` - Simulation orchestrator module. +##### `solar.py` - Solar PV module. +##### `utils.py` - Hosts utility functions used by some modules. +##### `simulate.py` - Offline DER control optimization for cost minimization (this is run for offline mode (no state feedback)). + + +### DLMODELS + +This includes legacy load forecasts models developed (not needed). + + +### elec_rates + +Includes .csv files for electricity Time-of-use (TOU) rates. The input data prototype for electricity rates +is shown below. User must upload a normal full-year sized data (for 365 days) to avoid +any errors. + + + +The data required must be in the format shown above. The `electricityPrices.py` module will read the data and sample +prices during optimization and simulation. The data should be one full year of TOU rate prices at 15 minute resolution. +The `electricityPrices.py` module can also help with downscaling the data to 15 minute resolution if the data is at a +much coarser resolution. The module will save the downscaled data in the `elec_rates` folder. + +### feeders +Library of IEEE test feeders and PNNL taxonomy feeders for distribution systems in the GridLAB-D `.glm` format. +IEEE feeders have spot loads specified at primary distribution level. PNNL taxonomy feeders have spot loads specified at +primary or secondary distribution level. + + +### feeder_population +Scripts for populating base feeder models with time-varying loads and resources using the load data in base_load_data. +`feeder_population.py` generates the necessary files for a co-simulation run based on the parameters specified in +`feeder_population/config.txt`. This module uses the +Requires residential load data not included in repo (limited access). + + + +### solar_data +Includes solar irradiance data for capturing the effects of environmental conditions on overall system cost. Default +data for solar irradiance is from the National Solar Radiation Database (NSRDB) for the San Francisco Bay Area. +The data prototype is from the National Renewable Energy Laboratory (NREL) and is shown below. Note that column fields +are case-sensitive. + +![solar_data_proto.png](doc_images%2Fsolar_data_proto.png) + +Month labels are indexed from 1 to 12, inclusive; 1 - January, 12 - December. The original data is in hourly resolution. +The *EV-Ecosim* data prototype is in 15 minute intervals by default, with irradiance oversampled 4 times from hourly +dataset. The GHI represents the "Global Horizontal Irradiance" in W/m^2, which is the total amount of shortwave radiation +received from above by a surface horizontal to the ground. + +### test_cases + +#### Co-simulation cases. + `base_case`- Reads voltage from GridLAB-D and writes power injections at each timestep (no EV charging or DER). + +`rlsf` - base_case plus implements a recursive least squares filter to estimate network model online (not used) + +`battery` - base_case plus transformer thermal model plus DER integration (included battery and solar). + +`transformer` - base_case plus simulation of transformer thermal model for each transformer in GridLAB-D model (not used). + + + +### analysis + +Scripts for plotting and analysis of co-simulation results. Includes post optimization and simulation cost +calculation modules and voltage impacts on the distribution grid. + +`plot_results.py` - This module is used post-simulation to parse the voltages from the power-simulation to calculate the percentage +voltage violations per ANSI C84.1. The file also generates voltage distribution plots. A user can modify the +SIMULATION_FOLDER variable which is the string of the path where the powerflow simulation output voltages at each node +exist. + +`load_post_opt_costs.py` - This module is calculates the levelized cost of energy and populates into tables/cost matrices, which are saved in the +respective files and folders. The module also generates plots for the cost analysis. + +`cost_analysis.py` - This module contains the `CostEstimator` class, which estimates the cost of the different grid and DER components +from the simulation. + + +## How to run +Create a new environment using `conda env create --name -f environment.yml`OR +install packages listed in the environment manually (RECOMMENDED) +Ensure gridlabd is installed by following recommended installation method. + +For battery test case: +* Navigate to `test_cases/battery/feeder_population` and run `feeder_population.py`. This uses the + `test_cases/battery/feeder_population/config.txt` settings to prepare the power system and populate the secondary + distribution network with time-varying base loads, EV charging stations, with the required transformers. +* Once confirmed that `feeder_population.py` has run successfully and generates the required `IEEE123_secondary.glm` and + `IEEE123_populated.glm` files, you are done with the initial pre-simulation run prep. +* Now navigate one level of out `/feeder_population` and run scenarios.py using `python3 scenarios.py` + +For base case: +* Navigate to `EV50_cosimulation/feeder_population` and run `feeder_population.py`. This uses the + `./feeder_population/config.txt` settings to prepare the power system and populate the secondary distribution network \ + with time-varying base loads +* Navigate to `test_cases/base_case` and run master_sim.py using `python3 master_sim.py` + +## Post-simulation analysis + * This is done with the modules in the `analysis` folder. Please see the `analysis` folder section for more details. + diff --git a/docs/build/_sources/analysis.rst.txt b/docs/build/_sources/analysis.rst.txt new file mode 100644 index 000000000..63546e198 --- /dev/null +++ b/docs/build/_sources/analysis.rst.txt @@ -0,0 +1,37 @@ +Post-simulation analysis +================ + +Submodules +---------- + +cost\_analysis module +------------------------------ + +.. automodule:: analysis.cost_analysis + :members: + :undoc-members: + :show-inheritance: + +load\_post\_opt\_costs module +-------------------------------------- + +.. automodule:: analysis.load_post_opt_costs + :members: + :undoc-members: + :show-inheritance: + +plot\_results module +----------------------------- + +.. automodule:: analysis.plot_results + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: analysis + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/build/_sources/charging_sim.rst.txt b/docs/build/_sources/charging_sim.rst.txt new file mode 100644 index 000000000..835283f7a --- /dev/null +++ b/docs/build/_sources/charging_sim.rst.txt @@ -0,0 +1,117 @@ +Charging simulator +===================== + +Submodules +---------- + +charging\_sim.battery module +---------------------------- + +.. automodule:: charging_sim.battery + :members: + :undoc-members: + :show-inheritance: + +charging\_sim.batteryAgingSim module +------------------------------------ + +.. automodule:: charging_sim.batteryAgingSim + :members: + :undoc-members: + :show-inheritance: + +charging\_sim.batterypack module +-------------------------------- + +.. automodule:: charging_sim.batterypack + :members: + :undoc-members: + :show-inheritance: + +charging\_sim.batterytest module +-------------------------------- + +.. automodule:: charging_sim.batterytest + :members: + :undoc-members: + :show-inheritance: + +charging\_sim.capacitor module +------------------------------ + +.. automodule:: charging_sim.capacitor + :members: + :undoc-members: + :show-inheritance: + +charging\_sim.chargingStation module +------------------------------------ + +.. automodule:: charging_sim.chargingStation + :members: + :undoc-members: + :show-inheritance: + +charging\_sim.controller module +------------------------------- + +.. automodule:: charging_sim.controller + :members: + :undoc-members: + :show-inheritance: + +charging\_sim.electricityPrices module +-------------------------------------- + +.. automodule:: charging_sim.electricityPrices + :members: + :undoc-members: + :show-inheritance: + +charging\_sim.optimization module +--------------------------------- + +.. automodule:: charging_sim.optimization + :members: + :undoc-members: + :show-inheritance: + +charging\_sim.orchestrator module +--------------------------------- + +.. automodule:: charging_sim.orchestrator + :members: + :undoc-members: + :show-inheritance: + +charging\_sim.simulate module +----------------------------- + +.. automodule:: charging_sim.simulate + :members: + :undoc-members: + :show-inheritance: + +charging\_sim.solar module +-------------------------- + +.. automodule:: charging_sim.solar + :members: + :undoc-members: + :show-inheritance: + +charging\_sim.utils module +-------------------------- + +.. automodule:: charging_sim.utils + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: charging_sim + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/build/_sources/feeder_population.rst.txt b/docs/build/_sources/feeder_population.rst.txt new file mode 100644 index 000000000..64aa90e82 --- /dev/null +++ b/docs/build/_sources/feeder_population.rst.txt @@ -0,0 +1,29 @@ +Feeder population +========================== + +Submodules +---------- + +feeder\_population.feeder\_population module +-------------------------------------------- + +.. automodule:: feeder_population.feeder_population + :members: + :undoc-members: + :show-inheritance: + +feeder\_population.glm\_mod\_functions module +--------------------------------------------- + +.. automodule:: feeder_population.glm_mod_functions + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: feeder_population + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/build/_sources/index.rst.txt b/docs/build/_sources/index.rst.txt new file mode 100644 index 000000000..aa8975082 --- /dev/null +++ b/docs/build/_sources/index.rst.txt @@ -0,0 +1,39 @@ +.. EV-Ecosim documentation master file, created by + sphinx-quickstart on Wed Aug 9 14:16:15 2023. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to EV-Ecosim 1.0.0 +===================================== +EV-Ecosim is a grid-aware python-based co-simulation platform for modeling and simulation of EV charging +stations integrated with Solar and Battery systems. This is a python based platform that interfaces with GridLAB-D, +a 3-phase unbalanced power flow solver, to estimate the impacts of EV (Fast) Charging Stations on power distribution +networks. + +.. image:: ../../doc_images/sim_frame.png + :width: 100% + :align: center + :alt: EV-Ecosim Simulation Framework + +We have made a web-tool version available for public use. It runs most of the code shown in this documentation. + +The project is accessible via Github and still under active development and improvements. + +TODO - Link to tutorial. +TODO - Include information on the container. + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + readme + modules + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/build/_sources/modules.rst.txt b/docs/build/_sources/modules.rst.txt new file mode 100644 index 000000000..a328dd802 --- /dev/null +++ b/docs/build/_sources/modules.rst.txt @@ -0,0 +1,11 @@ +Packages +================= +.. toctree:: + :maxdepth: 4 + + analysis + charging_sim + feeder_population + test_cases + + diff --git a/docs/build/_sources/readme.rst.txt b/docs/build/_sources/readme.rst.txt new file mode 100644 index 000000000..1efd2d475 --- /dev/null +++ b/docs/build/_sources/readme.rst.txt @@ -0,0 +1,3 @@ +Readme +================= +.. mdinclude:: ../../README.md \ No newline at end of file diff --git a/docs/build/_sources/test_cases.base_case.rst.txt b/docs/build/_sources/test_cases.base_case.rst.txt new file mode 100644 index 000000000..1cf8c0ac8 --- /dev/null +++ b/docs/build/_sources/test_cases.base_case.rst.txt @@ -0,0 +1,61 @@ +test\_cases.base\_case package +============================== + +Submodules +---------- + +test\_cases.base\_case.event\_handlers module +--------------------------------------------- + +.. automodule:: test_cases.base_case.event_handlers + :members: + :undoc-members: + :show-inheritance: + +test\_cases.base\_case.gblvar module +------------------------------------ + +.. automodule:: test_cases.base_case.gblvar + :members: + :undoc-members: + :show-inheritance: + +test\_cases.base\_case.glmptime module +-------------------------------------- + +.. automodule:: test_cases.base_case.glmptime + :members: + :undoc-members: + :show-inheritance: + +test\_cases.base\_case.master\_sim module +----------------------------------------- + +.. automodule:: test_cases.base_case.master_sim + :members: + :undoc-members: + :show-inheritance: + +test\_cases.base\_case.sim module +--------------------------------- + +.. automodule:: test_cases.base_case.sim + :members: + :undoc-members: + :show-inheritance: + +test\_cases.base\_case.voltdump2 module +--------------------------------------- + +.. automodule:: test_cases.base_case.voltdump2 + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: test_cases.base_case + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/build/_sources/test_cases.battery.feeder_population.rst.txt b/docs/build/_sources/test_cases.battery.feeder_population.rst.txt new file mode 100644 index 000000000..a78f70b4a --- /dev/null +++ b/docs/build/_sources/test_cases.battery.feeder_population.rst.txt @@ -0,0 +1,37 @@ +test\_cases.battery.feeder\_population package +============================================== + +Submodules +---------- + +test\_cases.battery.feeder\_population.feeder\_population module +---------------------------------------------------------------- + +.. automodule:: test_cases.battery.feeder_population.feeder_population + :members: + :undoc-members: + :show-inheritance: + +test\_cases.battery.feeder\_population.feeder\_population\_old module +--------------------------------------------------------------------- + +.. automodule:: test_cases.battery.feeder_population.feeder_population_old + :members: + :undoc-members: + :show-inheritance: + +test\_cases.battery.feeder\_population.glm\_mod\_functions module +----------------------------------------------------------------- + +.. automodule:: test_cases.battery.feeder_population.glm_mod_functions + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: test_cases.battery.feeder_population + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/build/_sources/test_cases.battery.rst.txt b/docs/build/_sources/test_cases.battery.rst.txt new file mode 100644 index 000000000..332aee2f3 --- /dev/null +++ b/docs/build/_sources/test_cases.battery.rst.txt @@ -0,0 +1,101 @@ +test\_cases.battery package +=========================== + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + test_cases.battery.feeder_population + +Submodules +---------- + +test\_cases.battery.data\_analysis module +----------------------------------------- + +.. automodule:: test_cases.battery.data_analysis + :members: + :undoc-members: + :show-inheritance: + +test\_cases.battery.event\_handlers module +------------------------------------------ + +.. automodule:: test_cases.battery.event_handlers + :members: + :undoc-members: + :show-inheritance: + +test\_cases.battery.event\_handlers\_oneshot module +--------------------------------------------------- + +.. automodule:: test_cases.battery.event_handlers_oneshot + :members: + :undoc-members: + :show-inheritance: + +test\_cases.battery.gblvar module +--------------------------------- + +.. automodule:: test_cases.battery.gblvar + :members: + :undoc-members: + :show-inheritance: + +test\_cases.battery.glmptime module +----------------------------------- + +.. automodule:: test_cases.battery.glmptime + :members: + :undoc-members: + :show-inheritance: + +test\_cases.battery.master\_sim module +-------------------------------------- + +.. automodule:: test_cases.battery.master_sim + :members: + :undoc-members: + :show-inheritance: + +test\_cases.battery.parse\_voltages module +------------------------------------------ + +.. automodule:: test_cases.battery.parse_voltages + :members: + :undoc-members: + :show-inheritance: + +test\_cases.battery.scenarios module +------------------------------------ + +.. automodule:: test_cases.battery.scenarios + :members: + :undoc-members: + :show-inheritance: + +test\_cases.battery.sim module +------------------------------ + +.. automodule:: test_cases.battery.sim + :members: + :undoc-members: + :show-inheritance: + +test\_cases.battery.voltdump2 module +------------------------------------ + +.. automodule:: test_cases.battery.voltdump2 + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: test_cases.battery + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/build/_sources/test_cases.rst.txt b/docs/build/_sources/test_cases.rst.txt new file mode 100644 index 000000000..f5dd0d32f --- /dev/null +++ b/docs/build/_sources/test_cases.rst.txt @@ -0,0 +1,19 @@ +Test cases +=================== + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + test_cases.base_case + test_cases.battery + +Module contents +--------------- + +.. automodule:: test_cases + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/build/_static/_sphinx_javascript_frameworks_compat.js b/docs/build/_static/_sphinx_javascript_frameworks_compat.js new file mode 100644 index 000000000..81415803e --- /dev/null +++ b/docs/build/_static/_sphinx_javascript_frameworks_compat.js @@ -0,0 +1,123 @@ +/* Compatability shim for jQuery and underscores.js. + * + * Copyright Sphinx contributors + * Released under the two clause BSD licence + */ + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} diff --git a/docs/build/_static/basic.css b/docs/build/_static/basic.css new file mode 100644 index 000000000..30fee9d0f --- /dev/null +++ b/docs/build/_static/basic.css @@ -0,0 +1,925 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a:visited { + color: #551A8B; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +nav.contents, +aside.topic, +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +nav.contents, +aside.topic, +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +nav.contents::after, +aside.topic::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +.sig dd { + margin-top: 0px; + margin-bottom: 0px; +} + +.sig dl { + margin-top: 0px; + margin-bottom: 0px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +.translated { + background-color: rgba(207, 255, 207, 0.2) +} + +.untranslated { + background-color: rgba(255, 207, 207, 0.2) +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/docs/build/_static/css/badge_only.css b/docs/build/_static/css/badge_only.css new file mode 100644 index 000000000..c718cee44 --- /dev/null +++ b/docs/build/_static/css/badge_only.css @@ -0,0 +1 @@ +.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#FontAwesome) format("svg")}.fa:before{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1}.fa:before,a .fa{text-decoration:inherit}.fa:before,a .fa,li .fa{display:inline-block}li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-caret-down:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before,.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before,.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before,.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60}.rst-versions .rst-current-version:after{clear:both;content:"";display:block}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}} \ No newline at end of file diff --git a/docs/build/_static/css/fonts/Roboto-Slab-Bold.woff b/docs/build/_static/css/fonts/Roboto-Slab-Bold.woff new file mode 100644 index 000000000..6cb600001 Binary files /dev/null and b/docs/build/_static/css/fonts/Roboto-Slab-Bold.woff differ diff --git a/docs/build/_static/css/fonts/Roboto-Slab-Bold.woff2 b/docs/build/_static/css/fonts/Roboto-Slab-Bold.woff2 new file mode 100644 index 000000000..7059e2314 Binary files /dev/null and b/docs/build/_static/css/fonts/Roboto-Slab-Bold.woff2 differ diff --git a/docs/build/_static/css/fonts/Roboto-Slab-Regular.woff b/docs/build/_static/css/fonts/Roboto-Slab-Regular.woff new file mode 100644 index 000000000..f815f63f9 Binary files /dev/null and b/docs/build/_static/css/fonts/Roboto-Slab-Regular.woff differ diff --git a/docs/build/_static/css/fonts/Roboto-Slab-Regular.woff2 b/docs/build/_static/css/fonts/Roboto-Slab-Regular.woff2 new file mode 100644 index 000000000..f2c76e5bd Binary files /dev/null and b/docs/build/_static/css/fonts/Roboto-Slab-Regular.woff2 differ diff --git a/docs/build/_static/css/fonts/fontawesome-webfont.eot b/docs/build/_static/css/fonts/fontawesome-webfont.eot new file mode 100644 index 000000000..e9f60ca95 Binary files /dev/null and b/docs/build/_static/css/fonts/fontawesome-webfont.eot differ diff --git a/docs/build/_static/css/fonts/fontawesome-webfont.svg b/docs/build/_static/css/fonts/fontawesome-webfont.svg new file mode 100644 index 000000000..855c845e5 --- /dev/null +++ b/docs/build/_static/css/fonts/fontawesome-webfont.svg @@ -0,0 +1,2671 @@ + + + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/build/_static/css/fonts/fontawesome-webfont.ttf b/docs/build/_static/css/fonts/fontawesome-webfont.ttf new file mode 100644 index 000000000..35acda2fa Binary files /dev/null and b/docs/build/_static/css/fonts/fontawesome-webfont.ttf differ diff --git a/docs/build/_static/css/fonts/fontawesome-webfont.woff b/docs/build/_static/css/fonts/fontawesome-webfont.woff new file mode 100644 index 000000000..400014a4b Binary files /dev/null and b/docs/build/_static/css/fonts/fontawesome-webfont.woff differ diff --git a/docs/build/_static/css/fonts/fontawesome-webfont.woff2 b/docs/build/_static/css/fonts/fontawesome-webfont.woff2 new file mode 100644 index 000000000..4d13fc604 Binary files /dev/null and b/docs/build/_static/css/fonts/fontawesome-webfont.woff2 differ diff --git a/docs/build/_static/css/fonts/lato-bold-italic.woff b/docs/build/_static/css/fonts/lato-bold-italic.woff new file mode 100644 index 000000000..88ad05b9f Binary files /dev/null and b/docs/build/_static/css/fonts/lato-bold-italic.woff differ diff --git a/docs/build/_static/css/fonts/lato-bold-italic.woff2 b/docs/build/_static/css/fonts/lato-bold-italic.woff2 new file mode 100644 index 000000000..c4e3d804b Binary files /dev/null and b/docs/build/_static/css/fonts/lato-bold-italic.woff2 differ diff --git a/docs/build/_static/css/fonts/lato-bold.woff b/docs/build/_static/css/fonts/lato-bold.woff new file mode 100644 index 000000000..c6dff51f0 Binary files /dev/null and b/docs/build/_static/css/fonts/lato-bold.woff differ diff --git a/docs/build/_static/css/fonts/lato-bold.woff2 b/docs/build/_static/css/fonts/lato-bold.woff2 new file mode 100644 index 000000000..bb195043c Binary files /dev/null and b/docs/build/_static/css/fonts/lato-bold.woff2 differ diff --git a/docs/build/_static/css/fonts/lato-normal-italic.woff b/docs/build/_static/css/fonts/lato-normal-italic.woff new file mode 100644 index 000000000..76114bc03 Binary files /dev/null and b/docs/build/_static/css/fonts/lato-normal-italic.woff differ diff --git a/docs/build/_static/css/fonts/lato-normal-italic.woff2 b/docs/build/_static/css/fonts/lato-normal-italic.woff2 new file mode 100644 index 000000000..3404f37e2 Binary files /dev/null and b/docs/build/_static/css/fonts/lato-normal-italic.woff2 differ diff --git a/docs/build/_static/css/fonts/lato-normal.woff b/docs/build/_static/css/fonts/lato-normal.woff new file mode 100644 index 000000000..ae1307ff5 Binary files /dev/null and b/docs/build/_static/css/fonts/lato-normal.woff differ diff --git a/docs/build/_static/css/fonts/lato-normal.woff2 b/docs/build/_static/css/fonts/lato-normal.woff2 new file mode 100644 index 000000000..3bf984332 Binary files /dev/null and b/docs/build/_static/css/fonts/lato-normal.woff2 differ diff --git a/docs/build/_static/css/theme.css b/docs/build/_static/css/theme.css new file mode 100644 index 000000000..19a446a0e --- /dev/null +++ b/docs/build/_static/css/theme.css @@ -0,0 +1,4 @@ +html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden],audio:not([controls]){display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;text-decoration:none}ins,mark{color:#000}mark{background:#ff0;font-style:italic;font-weight:700}.rst-content code,.rst-content tt,code,kbd,pre,samp{font-family:monospace,serif;_font-family:courier new,monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:after,q:before{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,ol,ul{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure,form{margin:0}label{cursor:pointer}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}textarea{resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{body,html,section{background:none!important}*{box-shadow:none!important;text-shadow:none!important;filter:none!important;-ms-filter:none!important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}.rst-content .toctree-wrapper>p.caption,h2,h3,p{orphans:3;widows:3}.rst-content .toctree-wrapper>p.caption,h2,h3{page-break-after:avoid}}.btn,.fa:before,.icon:before,.rst-content .admonition,.rst-content .admonition-title:before,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .code-block-caption .headerlink:before,.rst-content .danger,.rst-content .eqno .headerlink:before,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-alert,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before,input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:FontAwesome;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713);src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix&v=4.7.0) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa-pull-left.icon,.fa.fa-pull-left,.rst-content .code-block-caption .fa-pull-left.headerlink,.rst-content .eqno .fa-pull-left.headerlink,.rst-content .fa-pull-left.admonition-title,.rst-content code.download span.fa-pull-left:first-child,.rst-content dl dt .fa-pull-left.headerlink,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content p .fa-pull-left.headerlink,.rst-content table>caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.wy-menu-vertical li.current>a button.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-left.toctree-expand,.wy-menu-vertical li button.fa-pull-left.toctree-expand{margin-right:.3em}.fa-pull-right.icon,.fa.fa-pull-right,.rst-content .code-block-caption .fa-pull-right.headerlink,.rst-content .eqno .fa-pull-right.headerlink,.rst-content .fa-pull-right.admonition-title,.rst-content code.download span.fa-pull-right:first-child,.rst-content dl dt .fa-pull-right.headerlink,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content p .fa-pull-right.headerlink,.rst-content table>caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.wy-menu-vertical li.current>a button.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-right.toctree-expand,.wy-menu-vertical li button.fa-pull-right.toctree-expand{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.pull-left.icon,.rst-content .code-block-caption .pull-left.headerlink,.rst-content .eqno .pull-left.headerlink,.rst-content .pull-left.admonition-title,.rst-content code.download span.pull-left:first-child,.rst-content dl dt .pull-left.headerlink,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content p .pull-left.headerlink,.rst-content table>caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.wy-menu-vertical li.current>a button.pull-left.toctree-expand,.wy-menu-vertical li.on a button.pull-left.toctree-expand,.wy-menu-vertical li button.pull-left.toctree-expand{margin-right:.3em}.fa.pull-right,.pull-right.icon,.rst-content .code-block-caption .pull-right.headerlink,.rst-content .eqno .pull-right.headerlink,.rst-content .pull-right.admonition-title,.rst-content code.download span.pull-right:first-child,.rst-content dl dt .pull-right.headerlink,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content p .pull-right.headerlink,.rst-content table>caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.wy-menu-vertical li.current>a button.pull-right.toctree-expand,.wy-menu-vertical li.on a button.pull-right.toctree-expand,.wy-menu-vertical li button.pull-right.toctree-expand{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-close:before,.fa-remove:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-cog:before,.fa-gear:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-repeat:before,.fa-rotate-right:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.rst-content .admonition-title:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-exclamation-triangle:before,.fa-warning:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-cogs:before,.fa-gears:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-floppy-o:before,.fa-save:before{content:""}.fa-square:before{content:""}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.icon-caret-down:before,.wy-dropdown .caret:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-sort:before,.fa-unsorted:before{content:""}.fa-sort-desc:before,.fa-sort-down:before{content:""}.fa-sort-asc:before,.fa-sort-up:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-gavel:before,.fa-legal:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-bolt:before,.fa-flash:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-clipboard:before,.fa-paste:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-chain-broken:before,.fa-unlink:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:""}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:""}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:""}.fa-eur:before,.fa-euro:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-inr:before,.fa-rupee:before{content:""}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:""}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:""}.fa-krw:before,.fa-won:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-try:before,.fa-turkish-lira:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li button.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-bank:before,.fa-institution:before,.fa-university:before{content:""}.fa-graduation-cap:before,.fa-mortar-board:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:""}.fa-file-archive-o:before,.fa-file-zip-o:before{content:""}.fa-file-audio-o:before,.fa-file-sound-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:""}.fa-empire:before,.fa-ge:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-paper-plane:before,.fa-send:before{content:""}.fa-paper-plane-o:before,.fa-send-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-bed:before,.fa-hotel:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-y-combinator:before,.fa-yc:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-television:before,.fa-tv:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:""}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-sign-language:before,.fa-signing:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-address-card:before,.fa-vcard:before{content:""}.fa-address-card-o:before,.fa-vcard-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{font-family:inherit}.fa:before,.icon:before,.rst-content .admonition-title:before,.rst-content .code-block-caption .headerlink:before,.rst-content .eqno .headerlink:before,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before{font-family:FontAwesome;display:inline-block;font-style:normal;font-weight:400;line-height:1;text-decoration:inherit}.rst-content .code-block-caption a .headerlink,.rst-content .eqno a .headerlink,.rst-content a .admonition-title,.rst-content code.download a span:first-child,.rst-content dl dt a .headerlink,.rst-content h1 a .headerlink,.rst-content h2 a .headerlink,.rst-content h3 a .headerlink,.rst-content h4 a .headerlink,.rst-content h5 a .headerlink,.rst-content h6 a .headerlink,.rst-content p.caption a .headerlink,.rst-content p a .headerlink,.rst-content table>caption a .headerlink,.rst-content tt.download a span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li a button.toctree-expand,a .fa,a .icon,a .rst-content .admonition-title,a .rst-content .code-block-caption .headerlink,a .rst-content .eqno .headerlink,a .rst-content code.download span:first-child,a .rst-content dl dt .headerlink,a .rst-content h1 .headerlink,a .rst-content h2 .headerlink,a .rst-content h3 .headerlink,a .rst-content h4 .headerlink,a .rst-content h5 .headerlink,a .rst-content h6 .headerlink,a .rst-content p.caption .headerlink,a .rst-content p .headerlink,a .rst-content table>caption .headerlink,a .rst-content tt.download span:first-child,a .wy-menu-vertical li button.toctree-expand{display:inline-block;text-decoration:inherit}.btn .fa,.btn .icon,.btn .rst-content .admonition-title,.btn .rst-content .code-block-caption .headerlink,.btn .rst-content .eqno .headerlink,.btn .rst-content code.download span:first-child,.btn .rst-content dl dt .headerlink,.btn .rst-content h1 .headerlink,.btn .rst-content h2 .headerlink,.btn .rst-content h3 .headerlink,.btn .rst-content h4 .headerlink,.btn .rst-content h5 .headerlink,.btn .rst-content h6 .headerlink,.btn .rst-content p .headerlink,.btn .rst-content table>caption .headerlink,.btn .rst-content tt.download span:first-child,.btn .wy-menu-vertical li.current>a button.toctree-expand,.btn .wy-menu-vertical li.on a button.toctree-expand,.btn .wy-menu-vertical li button.toctree-expand,.nav .fa,.nav .icon,.nav .rst-content .admonition-title,.nav .rst-content .code-block-caption .headerlink,.nav .rst-content .eqno .headerlink,.nav .rst-content code.download span:first-child,.nav .rst-content dl dt .headerlink,.nav .rst-content h1 .headerlink,.nav .rst-content h2 .headerlink,.nav .rst-content h3 .headerlink,.nav .rst-content h4 .headerlink,.nav .rst-content h5 .headerlink,.nav .rst-content h6 .headerlink,.nav .rst-content p .headerlink,.nav .rst-content table>caption .headerlink,.nav .rst-content tt.download span:first-child,.nav .wy-menu-vertical li.current>a button.toctree-expand,.nav .wy-menu-vertical li.on a button.toctree-expand,.nav .wy-menu-vertical li button.toctree-expand,.rst-content .btn .admonition-title,.rst-content .code-block-caption .btn .headerlink,.rst-content .code-block-caption .nav .headerlink,.rst-content .eqno .btn .headerlink,.rst-content .eqno .nav .headerlink,.rst-content .nav .admonition-title,.rst-content code.download .btn span:first-child,.rst-content code.download .nav span:first-child,.rst-content dl dt .btn .headerlink,.rst-content dl dt .nav .headerlink,.rst-content h1 .btn .headerlink,.rst-content h1 .nav .headerlink,.rst-content h2 .btn .headerlink,.rst-content h2 .nav .headerlink,.rst-content h3 .btn .headerlink,.rst-content h3 .nav .headerlink,.rst-content h4 .btn .headerlink,.rst-content h4 .nav .headerlink,.rst-content h5 .btn .headerlink,.rst-content h5 .nav .headerlink,.rst-content h6 .btn .headerlink,.rst-content h6 .nav .headerlink,.rst-content p .btn .headerlink,.rst-content p .nav .headerlink,.rst-content table>caption .btn .headerlink,.rst-content table>caption .nav .headerlink,.rst-content tt.download .btn span:first-child,.rst-content tt.download .nav span:first-child,.wy-menu-vertical li .btn button.toctree-expand,.wy-menu-vertical li.current>a .btn button.toctree-expand,.wy-menu-vertical li.current>a .nav button.toctree-expand,.wy-menu-vertical li .nav button.toctree-expand,.wy-menu-vertical li.on a .btn button.toctree-expand,.wy-menu-vertical li.on a .nav button.toctree-expand{display:inline}.btn .fa-large.icon,.btn .fa.fa-large,.btn .rst-content .code-block-caption .fa-large.headerlink,.btn .rst-content .eqno .fa-large.headerlink,.btn .rst-content .fa-large.admonition-title,.btn .rst-content code.download span.fa-large:first-child,.btn .rst-content dl dt .fa-large.headerlink,.btn .rst-content h1 .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.btn .rst-content p .fa-large.headerlink,.btn .rst-content table>caption .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.btn .wy-menu-vertical li button.fa-large.toctree-expand,.nav .fa-large.icon,.nav .fa.fa-large,.nav .rst-content .code-block-caption .fa-large.headerlink,.nav .rst-content .eqno .fa-large.headerlink,.nav .rst-content .fa-large.admonition-title,.nav .rst-content code.download span.fa-large:first-child,.nav .rst-content dl dt .fa-large.headerlink,.nav .rst-content h1 .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.nav .rst-content p .fa-large.headerlink,.nav .rst-content table>caption .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.nav .wy-menu-vertical li button.fa-large.toctree-expand,.rst-content .btn .fa-large.admonition-title,.rst-content .code-block-caption .btn .fa-large.headerlink,.rst-content .code-block-caption .nav .fa-large.headerlink,.rst-content .eqno .btn .fa-large.headerlink,.rst-content .eqno .nav .fa-large.headerlink,.rst-content .nav .fa-large.admonition-title,.rst-content code.download .btn span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.rst-content dl dt .btn .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.rst-content p .btn .fa-large.headerlink,.rst-content p .nav .fa-large.headerlink,.rst-content table>caption .btn .fa-large.headerlink,.rst-content table>caption .nav .fa-large.headerlink,.rst-content tt.download .btn span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.wy-menu-vertical li .btn button.fa-large.toctree-expand,.wy-menu-vertical li .nav button.fa-large.toctree-expand{line-height:.9em}.btn .fa-spin.icon,.btn .fa.fa-spin,.btn .rst-content .code-block-caption .fa-spin.headerlink,.btn .rst-content .eqno .fa-spin.headerlink,.btn .rst-content .fa-spin.admonition-title,.btn .rst-content code.download span.fa-spin:first-child,.btn .rst-content dl dt .fa-spin.headerlink,.btn .rst-content h1 .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.btn .rst-content p .fa-spin.headerlink,.btn .rst-content table>caption .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.btn .wy-menu-vertical li button.fa-spin.toctree-expand,.nav .fa-spin.icon,.nav .fa.fa-spin,.nav .rst-content .code-block-caption .fa-spin.headerlink,.nav .rst-content .eqno .fa-spin.headerlink,.nav .rst-content .fa-spin.admonition-title,.nav .rst-content code.download span.fa-spin:first-child,.nav .rst-content dl dt .fa-spin.headerlink,.nav .rst-content h1 .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.nav .rst-content p .fa-spin.headerlink,.nav .rst-content table>caption .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.nav .wy-menu-vertical li button.fa-spin.toctree-expand,.rst-content .btn .fa-spin.admonition-title,.rst-content .code-block-caption .btn .fa-spin.headerlink,.rst-content .code-block-caption .nav .fa-spin.headerlink,.rst-content .eqno .btn .fa-spin.headerlink,.rst-content .eqno .nav .fa-spin.headerlink,.rst-content .nav .fa-spin.admonition-title,.rst-content code.download .btn span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.rst-content dl dt .btn .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.rst-content p .btn .fa-spin.headerlink,.rst-content p .nav .fa-spin.headerlink,.rst-content table>caption .btn .fa-spin.headerlink,.rst-content table>caption .nav .fa-spin.headerlink,.rst-content tt.download .btn span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.wy-menu-vertical li .btn button.fa-spin.toctree-expand,.wy-menu-vertical li .nav button.fa-spin.toctree-expand{display:inline-block}.btn.fa:before,.btn.icon:before,.rst-content .btn.admonition-title:before,.rst-content .code-block-caption .btn.headerlink:before,.rst-content .eqno .btn.headerlink:before,.rst-content code.download span.btn:first-child:before,.rst-content dl dt .btn.headerlink:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content p .btn.headerlink:before,.rst-content table>caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.wy-menu-vertical li button.btn.toctree-expand:before{opacity:.5;-webkit-transition:opacity .05s ease-in;-moz-transition:opacity .05s ease-in;transition:opacity .05s ease-in}.btn.fa:hover:before,.btn.icon:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content .code-block-caption .btn.headerlink:hover:before,.rst-content .eqno .btn.headerlink:hover:before,.rst-content code.download span.btn:first-child:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content p .btn.headerlink:hover:before,.rst-content table>caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.wy-menu-vertical li button.btn.toctree-expand:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .icon:before,.btn-mini .rst-content .admonition-title:before,.btn-mini .rst-content .code-block-caption .headerlink:before,.btn-mini .rst-content .eqno .headerlink:before,.btn-mini .rst-content code.download span:first-child:before,.btn-mini .rst-content dl dt .headerlink:before,.btn-mini .rst-content h1 .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.btn-mini .rst-content p .headerlink:before,.btn-mini .rst-content table>caption .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.btn-mini .wy-menu-vertical li button.toctree-expand:before,.rst-content .btn-mini .admonition-title:before,.rst-content .code-block-caption .btn-mini .headerlink:before,.rst-content .eqno .btn-mini .headerlink:before,.rst-content code.download .btn-mini span:first-child:before,.rst-content dl dt .btn-mini .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.rst-content p .btn-mini .headerlink:before,.rst-content table>caption .btn-mini .headerlink:before,.rst-content tt.download .btn-mini span:first-child:before,.wy-menu-vertical li .btn-mini button.toctree-expand:before{font-size:14px;vertical-align:-15%}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.wy-alert{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.rst-content .admonition-title,.wy-alert-title{font-weight:700;display:block;color:#fff;background:#6ab0de;padding:6px 12px;margin:-12px -12px 12px}.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.admonition,.rst-content .wy-alert-danger.admonition-todo,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.wy-alert.wy-alert-danger{background:#fdf3f2}.rst-content .danger .admonition-title,.rst-content .danger .wy-alert-title,.rst-content .error .admonition-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.rst-content .wy-alert-danger.admonition .admonition-title,.rst-content .wy-alert-danger.admonition .wy-alert-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.wy-alert.wy-alert-danger .wy-alert-title{background:#f29f97}.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .warning,.rst-content .wy-alert-warning.admonition,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.note,.rst-content .wy-alert-warning.seealso,.rst-content .wy-alert-warning.tip,.wy-alert.wy-alert-warning{background:#ffedcc}.rst-content .admonition-todo .admonition-title,.rst-content .admonition-todo .wy-alert-title,.rst-content .attention .admonition-title,.rst-content .attention .wy-alert-title,.rst-content .caution .admonition-title,.rst-content .caution .wy-alert-title,.rst-content .warning .admonition-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.admonition .admonition-title,.rst-content .wy-alert-warning.admonition .wy-alert-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.wy-alert.wy-alert-warning .wy-alert-title{background:#f0b37e}.rst-content .note,.rst-content .seealso,.rst-content .wy-alert-info.admonition,.rst-content .wy-alert-info.admonition-todo,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.wy-alert.wy-alert-info{background:#e7f2fa}.rst-content .note .admonition-title,.rst-content .note .wy-alert-title,.rst-content .seealso .admonition-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .admonition-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.wy-alert.wy-alert-info .wy-alert-title{background:#6ab0de}.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.admonition,.rst-content .wy-alert-success.admonition-todo,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.warning,.wy-alert.wy-alert-success{background:#dbfaf4}.rst-content .hint .admonition-title,.rst-content .hint .wy-alert-title,.rst-content .important .admonition-title,.rst-content .important .wy-alert-title,.rst-content .tip .admonition-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .admonition-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.rst-content .wy-alert-success.admonition .admonition-title,.rst-content .wy-alert-success.admonition .wy-alert-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.wy-alert.wy-alert-success .wy-alert-title{background:#1abc9c}.rst-content .wy-alert-neutral.admonition,.rst-content .wy-alert-neutral.admonition-todo,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.wy-alert.wy-alert-neutral{background:#f3f6f6}.rst-content .wy-alert-neutral.admonition-todo .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.rst-content .wy-alert-neutral.admonition .admonition-title,.rst-content .wy-alert-neutral.admonition .wy-alert-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.wy-alert.wy-alert-neutral .wy-alert-title{color:#404040;background:#e1e4e5}.rst-content .wy-alert-neutral.admonition-todo a,.rst-content .wy-alert-neutral.admonition a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.wy-alert.wy-alert-neutral a{color:#2980b9}.rst-content .admonition-todo p:last-child,.rst-content .admonition p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .note p:last-child,.rst-content .seealso p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.wy-alert p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;transition:all .3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27ae60}.wy-tray-container li.wy-tray-item-info{background:#2980b9}.wy-tray-container li.wy-tray-item-warning{background:#e67e22}.wy-tray-container li.wy-tray-item-danger{background:#e74c3c}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width:768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px;color:#fff;border:1px solid rgba(0,0,0,.1);background-color:#27ae60;text-decoration:none;font-weight:400;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 2px -1px hsla(0,0%,100%,.5),inset 0 -2px 0 0 rgba(0,0,0,.1);outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .1s linear;-moz-transition:all .1s linear;transition:all .1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:inset 0 -1px 0 0 rgba(0,0,0,.05),inset 0 2px 0 0 rgba(0,0,0,.1);padding:8px 12px 6px}.btn:visited{color:#fff}.btn-disabled,.btn-disabled:active,.btn-disabled:focus,.btn-disabled:hover,.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980b9!important}.btn-info:hover{background-color:#2e8ece!important}.btn-neutral{background-color:#f3f6f6!important;color:#404040!important}.btn-neutral:hover{background-color:#e5ebeb!important;color:#404040}.btn-neutral:visited{color:#404040!important}.btn-success{background-color:#27ae60!important}.btn-success:hover{background-color:#295!important}.btn-danger{background-color:#e74c3c!important}.btn-danger:hover{background-color:#ea6153!important}.btn-warning{background-color:#e67e22!important}.btn-warning:hover{background-color:#e98b39!important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f!important}.btn-link{background-color:transparent!important;color:#2980b9;box-shadow:none;border-color:transparent!important}.btn-link:active,.btn-link:hover{background-color:transparent!important;color:#409ad5!important;box-shadow:none}.btn-link:visited{color:#9b59b6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:after,.wy-btn-group:before{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:1px solid #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980b9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:1px solid #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type=search]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980b9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned .wy-help-inline,.wy-form-aligned input,.wy-form-aligned label,.wy-form-aligned select,.wy-form-aligned textarea{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{margin:0}fieldset,legend{border:0;padding:0}legend{width:100%;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label,legend{display:block}label{margin:0 0 .3125em;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;max-width:1200px;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:after,.wy-control-group:before{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#e74c3c}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full input[type=color],.wy-control-group .wy-form-full input[type=date],.wy-control-group .wy-form-full input[type=datetime-local],.wy-control-group .wy-form-full input[type=datetime],.wy-control-group .wy-form-full input[type=email],.wy-control-group .wy-form-full input[type=month],.wy-control-group .wy-form-full input[type=number],.wy-control-group .wy-form-full input[type=password],.wy-control-group .wy-form-full input[type=search],.wy-control-group .wy-form-full input[type=tel],.wy-control-group .wy-form-full input[type=text],.wy-control-group .wy-form-full input[type=time],.wy-control-group .wy-form-full input[type=url],.wy-control-group .wy-form-full input[type=week],.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves input[type=color],.wy-control-group .wy-form-halves input[type=date],.wy-control-group .wy-form-halves input[type=datetime-local],.wy-control-group .wy-form-halves input[type=datetime],.wy-control-group .wy-form-halves input[type=email],.wy-control-group .wy-form-halves input[type=month],.wy-control-group .wy-form-halves input[type=number],.wy-control-group .wy-form-halves input[type=password],.wy-control-group .wy-form-halves input[type=search],.wy-control-group .wy-form-halves input[type=tel],.wy-control-group .wy-form-halves input[type=text],.wy-control-group .wy-form-halves input[type=time],.wy-control-group .wy-form-halves input[type=url],.wy-control-group .wy-form-halves input[type=week],.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds input[type=color],.wy-control-group .wy-form-thirds input[type=date],.wy-control-group .wy-form-thirds input[type=datetime-local],.wy-control-group .wy-form-thirds input[type=datetime],.wy-control-group .wy-form-thirds input[type=email],.wy-control-group .wy-form-thirds input[type=month],.wy-control-group .wy-form-thirds input[type=number],.wy-control-group .wy-form-thirds input[type=password],.wy-control-group .wy-form-thirds input[type=search],.wy-control-group .wy-form-thirds input[type=tel],.wy-control-group .wy-form-thirds input[type=text],.wy-control-group .wy-form-thirds input[type=time],.wy-control-group .wy-form-thirds input[type=url],.wy-control-group .wy-form-thirds input[type=week],.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full{float:left;display:block;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child,.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(odd){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child,.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control,.wy-control-no-input{margin:6px 0 0;font-size:90%}.wy-control-no-input{display:inline-block}.wy-control-group.fluid-input input[type=color],.wy-control-group.fluid-input input[type=date],.wy-control-group.fluid-input input[type=datetime-local],.wy-control-group.fluid-input input[type=datetime],.wy-control-group.fluid-input input[type=email],.wy-control-group.fluid-input input[type=month],.wy-control-group.fluid-input input[type=number],.wy-control-group.fluid-input input[type=password],.wy-control-group.fluid-input input[type=search],.wy-control-group.fluid-input input[type=tel],.wy-control-group.fluid-input input[type=text],.wy-control-group.fluid-input input[type=time],.wy-control-group.fluid-input input[type=url],.wy-control-group.fluid-input input[type=week]{width:100%}.wy-form-message-inline{padding-left:.3em;color:#666;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;*overflow:visible}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}input[type=datetime-local]{padding:.34375em .625em}input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type=checkbox],input[type=radio],input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus{outline:0;outline:thin dotted\9;border-color:#333}input.no-focus:focus{border-color:#ccc!important}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted #333;outline:1px auto #129fea}input[type=color][disabled],input[type=date][disabled],input[type=datetime-local][disabled],input[type=datetime][disabled],input[type=email][disabled],input[type=month][disabled],input[type=number][disabled],input[type=password][disabled],input[type=search][disabled],input[type=tel][disabled],input[type=text][disabled],input[type=time][disabled],input[type=url][disabled],input[type=week][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,select:focus:invalid,textarea:focus:invalid{color:#e74c3c;border:1px solid #e74c3c}input:focus:invalid:focus,select:focus:invalid:focus,textarea:focus:invalid:focus{border-color:#e74c3c}input[type=checkbox]:focus:invalid:focus,input[type=file]:focus:invalid:focus,input[type=radio]:focus:invalid:focus{outline-color:#e74c3c}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}input[readonly],select[disabled],select[readonly],textarea[disabled],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type=checkbox][disabled],input[type=radio][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:1px solid #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{position:relative;display:block;height:24px;margin-top:12px;cursor:pointer}.wy-switch:before{left:0;top:0;width:36px;height:12px;background:#ccc}.wy-switch:after,.wy-switch:before{position:absolute;content:"";display:block;border-radius:4px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch:after{width:18px;height:18px;background:#999;left:-3px;top:-3px}.wy-switch span{position:absolute;left:48px;display:block;font-size:12px;color:#ccc;line-height:1}.wy-switch.active:before{background:#1e8449}.wy-switch.active:after{left:24px;background:#27ae60}.wy-switch.disabled{cursor:not-allowed;opacity:.8}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#e74c3c}.wy-control-group.wy-control-group-error input[type=color],.wy-control-group.wy-control-group-error input[type=date],.wy-control-group.wy-control-group-error input[type=datetime-local],.wy-control-group.wy-control-group-error input[type=datetime],.wy-control-group.wy-control-group-error input[type=email],.wy-control-group.wy-control-group-error input[type=month],.wy-control-group.wy-control-group-error input[type=number],.wy-control-group.wy-control-group-error input[type=password],.wy-control-group.wy-control-group-error input[type=search],.wy-control-group.wy-control-group-error input[type=tel],.wy-control-group.wy-control-group-error input[type=text],.wy-control-group.wy-control-group-error input[type=time],.wy-control-group.wy-control-group-error input[type=url],.wy-control-group.wy-control-group-error input[type=week],.wy-control-group.wy-control-group-error textarea{border:1px solid #e74c3c}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27ae60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#e74c3c}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#e67e22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980b9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width:480px){.wy-form button[type=submit]{margin:.7em 0 0}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=text],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week],.wy-form label{margin-bottom:.3em;display:block}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0}.wy-form-message,.wy-form-message-inline,.wy-form .wy-help-inline{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width:768px){.tablet-hide{display:none}}@media screen and (max-width:480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.rst-content table.docutils,.rst-content table.field-list,.wy-table{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.rst-content table.docutils caption,.rst-content table.field-list caption,.wy-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.rst-content table.docutils td,.rst-content table.docutils th,.rst-content table.field-list td,.rst-content table.field-list th,.wy-table td,.wy-table th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.rst-content table.docutils td:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list td:first-child,.rst-content table.field-list th:first-child,.wy-table td:first-child,.wy-table th:first-child{border-left-width:0}.rst-content table.docutils thead,.rst-content table.field-list thead,.wy-table thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.rst-content table.docutils thead th,.rst-content table.field-list thead th,.wy-table thead th{font-weight:700;border-bottom:2px solid #e1e4e5}.rst-content table.docutils td,.rst-content table.field-list td,.wy-table td{background-color:transparent;vertical-align:middle}.rst-content table.docutils td p,.rst-content table.field-list td p,.wy-table td p{line-height:18px}.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child,.wy-table td p:last-child{margin-bottom:0}.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min,.wy-table .wy-table-cell-min{width:1%;padding-right:0}.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:grey;font-size:90%}.wy-table-tertiary{color:grey;font-size:80%}.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,.wy-table-backed,.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td{background-color:#f3f6f6}.rst-content table.docutils,.wy-table-bordered-all{border:1px solid #e1e4e5}.rst-content table.docutils td,.wy-table-bordered-all td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.rst-content table.docutils tbody>tr:last-child td,.wy-table-bordered-all tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0!important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980b9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9b59b6}html{height:100%}body,html{overflow-x:hidden}body{font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-weight:400;color:#404040;min-height:100%;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22!important}a.wy-text-warning:hover{color:#eb9950!important}.wy-text-info{color:#2980b9!important}a.wy-text-info:hover{color:#409ad5!important}.wy-text-success{color:#27ae60!important}a.wy-text-success:hover{color:#36d278!important}.wy-text-danger{color:#e74c3c!important}a.wy-text-danger:hover{color:#ed7669!important}.wy-text-neutral{color:#404040!important}a.wy-text-neutral:hover{color:#595959!important}.rst-content .toctree-wrapper>p.caption,h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif}p{line-height:24px;font-size:16px;margin:0 0 24px}h1{font-size:175%}.rst-content .toctree-wrapper>p.caption,h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}.rst-content code,.rst-content tt,code{white-space:nowrap;max-width:100%;background:#fff;border:1px solid #e1e4e5;font-size:75%;padding:0 5px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#e74c3c;overflow-x:auto}.rst-content tt.code-large,code.code-large{font-size:90%}.rst-content .section ul,.rst-content .toctree-wrapper ul,.rst-content section ul,.wy-plain-list-disc,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.rst-content .section ul li,.rst-content .toctree-wrapper ul li,.rst-content section ul li,.wy-plain-list-disc li,article ul li{list-style:disc;margin-left:24px}.rst-content .section ul li p:last-child,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li p:last-child,.rst-content .toctree-wrapper ul li ul,.rst-content section ul li p:last-child,.rst-content section ul li ul,.wy-plain-list-disc li p:last-child,.wy-plain-list-disc li ul,article ul li p:last-child,article ul li ul{margin-bottom:0}.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,.rst-content section ul li li,.wy-plain-list-disc li li,article ul li li{list-style:circle}.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,.rst-content section ul li li li,.wy-plain-list-disc li li li,article ul li li li{list-style:square}.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,.rst-content section ul li ol li,.wy-plain-list-disc li ol li,article ul li ol li{list-style:decimal}.rst-content .section ol,.rst-content .section ol.arabic,.rst-content .toctree-wrapper ol,.rst-content .toctree-wrapper ol.arabic,.rst-content section ol,.rst-content section ol.arabic,.wy-plain-list-decimal,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.rst-content .section ol.arabic li,.rst-content .section ol li,.rst-content .toctree-wrapper ol.arabic li,.rst-content .toctree-wrapper ol li,.rst-content section ol.arabic li,.rst-content section ol li,.wy-plain-list-decimal li,article ol li{list-style:decimal;margin-left:24px}.rst-content .section ol.arabic li ul,.rst-content .section ol li p:last-child,.rst-content .section ol li ul,.rst-content .toctree-wrapper ol.arabic li ul,.rst-content .toctree-wrapper ol li p:last-child,.rst-content .toctree-wrapper ol li ul,.rst-content section ol.arabic li ul,.rst-content section ol li p:last-child,.rst-content section ol li ul,.wy-plain-list-decimal li p:last-child,.wy-plain-list-decimal li ul,article ol li p:last-child,article ol li ul{margin-bottom:0}.rst-content .section ol.arabic li ul li,.rst-content .section ol li ul li,.rst-content .toctree-wrapper ol.arabic li ul li,.rst-content .toctree-wrapper ol li ul li,.rst-content section ol.arabic li ul li,.rst-content section ol li ul li,.wy-plain-list-decimal li ul li,article ol li ul li{list-style:disc}.wy-breadcrumbs{*zoom:1}.wy-breadcrumbs:after,.wy-breadcrumbs:before{display:table;content:""}.wy-breadcrumbs:after{clear:both}.wy-breadcrumbs>li{display:inline-block;padding-top:5px}.wy-breadcrumbs>li.wy-breadcrumbs-aside{float:right}.rst-content .wy-breadcrumbs>li code,.rst-content .wy-breadcrumbs>li tt,.wy-breadcrumbs>li .rst-content tt,.wy-breadcrumbs>li code{all:inherit;color:inherit}.breadcrumb-item:before{content:"/";color:#bbb;font-size:13px;padding:0 6px 0 3px}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width:480px){.wy-breadcrumbs-extra,.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}html{font-size:16px}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:after,.wy-menu-horiz:before{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz li,.wy-menu-horiz ul{display:inline-block}.wy-menu-horiz li:hover{background:hsla(0,0%,100%,.1)}.wy-menu-horiz li.divide-left{border-left:1px solid #404040}.wy-menu-horiz li.divide-right{border-right:1px solid #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{color:#55a5d9;height:32px;line-height:32px;padding:0 1.618em;margin:12px 0 0;display:block;font-weight:700;text-transform:uppercase;font-size:85%;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:1px solid #404040}.wy-menu-vertical li.divide-bottom{border-bottom:1px solid #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:grey;border-right:1px solid #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.rst-content .wy-menu-vertical li tt,.wy-menu-vertical li .rst-content tt,.wy-menu-vertical li code{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li button.toctree-expand{display:block;float:left;margin-left:-1.2em;line-height:18px;color:#4d4d4d;border:none;background:none;padding:0}.wy-menu-vertical li.current>a,.wy-menu-vertical li.on a{color:#404040;font-weight:700;position:relative;background:#fcfcfc;border:none;padding:.4045em 1.618em}.wy-menu-vertical li.current>a:hover,.wy-menu-vertical li.on a:hover{background:#fcfcfc}.wy-menu-vertical li.current>a:hover button.toctree-expand,.wy-menu-vertical li.on a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand{display:block;line-height:18px;color:#333}.wy-menu-vertical li.toctree-l1.current>a{border-bottom:1px solid #c9c9c9;border-top:1px solid #c9c9c9}.wy-menu-vertical .toctree-l1.current .toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .toctree-l11>ul{display:none}.wy-menu-vertical .toctree-l1.current .current.toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .current.toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .current.toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .current.toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .current.toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .current.toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .current.toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .current.toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .current.toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .current.toctree-l11>ul{display:block}.wy-menu-vertical li.toctree-l3,.wy-menu-vertical li.toctree-l4{font-size:.9em}.wy-menu-vertical li.toctree-l2 a,.wy-menu-vertical li.toctree-l3 a,.wy-menu-vertical li.toctree-l4 a,.wy-menu-vertical li.toctree-l5 a,.wy-menu-vertical li.toctree-l6 a,.wy-menu-vertical li.toctree-l7 a,.wy-menu-vertical li.toctree-l8 a,.wy-menu-vertical li.toctree-l9 a,.wy-menu-vertical li.toctree-l10 a{color:#404040}.wy-menu-vertical li.toctree-l2 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l3 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l4 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l5 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l6 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l7 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l8 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l9 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l10 a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a,.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a,.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a,.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a,.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a,.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a,.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a,.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{display:block}.wy-menu-vertical li.toctree-l2.current>a{padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{padding:.4045em 1.618em .4045em 4.045em}.wy-menu-vertical li.toctree-l3.current>a{padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{padding:.4045em 1.618em .4045em 5.663em}.wy-menu-vertical li.toctree-l4.current>a{padding:.4045em 5.663em}.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a{padding:.4045em 1.618em .4045em 7.281em}.wy-menu-vertical li.toctree-l5.current>a{padding:.4045em 7.281em}.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a{padding:.4045em 1.618em .4045em 8.899em}.wy-menu-vertical li.toctree-l6.current>a{padding:.4045em 8.899em}.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a{padding:.4045em 1.618em .4045em 10.517em}.wy-menu-vertical li.toctree-l7.current>a{padding:.4045em 10.517em}.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a{padding:.4045em 1.618em .4045em 12.135em}.wy-menu-vertical li.toctree-l8.current>a{padding:.4045em 12.135em}.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a{padding:.4045em 1.618em .4045em 13.753em}.wy-menu-vertical li.toctree-l9.current>a{padding:.4045em 13.753em}.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a{padding:.4045em 1.618em .4045em 15.371em}.wy-menu-vertical li.toctree-l10.current>a{padding:.4045em 15.371em}.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{padding:.4045em 1.618em .4045em 16.989em}.wy-menu-vertical li.toctree-l2.current>a,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{background:#c9c9c9}.wy-menu-vertical li.toctree-l2 button.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3.current>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{background:#bdbdbd}.wy-menu-vertical li.toctree-l3 button.toctree-expand{color:#969696}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical li ul li a{margin-bottom:0;color:#d9d9d9;font-weight:400}.wy-menu-vertical a{line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#d9d9d9}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover button.toctree-expand{color:#d9d9d9}.wy-menu-vertical a:active{background-color:#2980b9;cursor:pointer;color:#fff}.wy-menu-vertical a:active button.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:.809em;margin-bottom:.809em;z-index:200;background-color:#2980b9;text-align:center;color:#fcfcfc}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a{color:#fcfcfc;font-size:100%;font-weight:700;display:inline-block;padding:4px 6px;margin-bottom:.809em;max-width:100%}.wy-side-nav-search .wy-dropdown>a:hover,.wy-side-nav-search>a:hover{background:hsla(0,0%,100%,.1)}.wy-side-nav-search .wy-dropdown>a img.logo,.wy-side-nav-search>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search .wy-dropdown>a.icon img.logo,.wy-side-nav-search>a.icon img.logo{margin-top:.85em}.wy-side-nav-search>div.version{margin-top:-.4045em;margin-bottom:.809em;font-weight:400;color:hsla(0,0%,100%,.3)}.wy-nav .wy-menu-vertical header{color:#2980b9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980b9;color:#fff}[data-menu-wrap]{-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;transition:all .2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:#fcfcfc}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;color:#9b9b9b;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980b9;color:#fff;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:after,.wy-nav-top:before{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:700}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:grey}footer p{margin-bottom:12px}.rst-content footer span.commit tt,footer span.commit .rst-content tt,footer span.commit code{padding:0;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:1em;background:none;border:none;color:grey}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:after,.rst-footer-buttons:before{width:100%;display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:after,.rst-breadcrumbs-buttons:before{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:1px solid #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:1px solid #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:grey;font-size:90%}.genindextable li>ul{margin-left:24px}@media screen and (max-width:768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-menu.wy-menu-vertical,.wy-side-nav-search,.wy-side-scroll{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width:1100px){.wy-nav-content-wrap{background:rgba(0,0,0,.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,.wy-nav-side,footer{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:after,.rst-versions .rst-current-version:before{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-content .code-block-caption .rst-versions .rst-current-version .headerlink,.rst-content .eqno .rst-versions .rst-current-version .headerlink,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-content p .rst-versions .rst-current-version .headerlink,.rst-content table>caption .rst-versions .rst-current-version .headerlink,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .icon,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-versions .rst-current-version .rst-content .code-block-caption .headerlink,.rst-versions .rst-current-version .rst-content .eqno .headerlink,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-versions .rst-current-version .rst-content p .headerlink,.rst-versions .rst-current-version .rst-content table>caption .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-versions .rst-current-version .wy-menu-vertical li button.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version button.toctree-expand{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}.rst-content .toctree-wrapper>p.caption,.rst-content h1,.rst-content h2,.rst-content h3,.rst-content h4,.rst-content h5,.rst-content h6{margin-bottom:24px}.rst-content img{max-width:100%;height:auto}.rst-content div.figure,.rst-content figure{margin-bottom:24px}.rst-content div.figure .caption-text,.rst-content figure .caption-text{font-style:italic}.rst-content div.figure p:last-child.caption,.rst-content figure p:last-child.caption{margin-bottom:0}.rst-content div.figure.align-center,.rst-content figure.align-center{text-align:center}.rst-content .section>a>img,.rst-content .section>img,.rst-content section>a>img,.rst-content section>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content.style-external-links a.reference.external:after{font-family:FontAwesome;content:"\f08e";color:#b3b3b3;vertical-align:super;font-size:60%;margin:0 .2em}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre.literal-block{white-space:pre;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;display:block;overflow:auto}.rst-content div[class^=highlight],.rst-content pre.literal-block{border:1px solid #e1e4e5;overflow-x:auto;margin:1px 0 24px}.rst-content div[class^=highlight] div[class^=highlight],.rst-content pre.literal-block div[class^=highlight]{padding:0;border:none;margin:0}.rst-content div[class^=highlight] td.code{width:100%}.rst-content .linenodiv pre{border-right:1px solid #e6e9ea;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;user-select:none;pointer-events:none}.rst-content div[class^=highlight] pre{white-space:pre;margin:0;padding:12px;display:block;overflow:auto}.rst-content div[class^=highlight] pre .hll{display:block;margin:0 -12px;padding:0 12px}.rst-content .linenodiv pre,.rst-content div[class^=highlight] pre,.rst-content pre.literal-block{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:12px;line-height:1.4}.rst-content div.highlight .gp,.rst-content div.highlight span.linenos{user-select:none;pointer-events:none}.rst-content div.highlight span.linenos{display:inline-block;padding-left:0;padding-right:12px;margin-right:12px;border-right:1px solid #e6e9ea}.rst-content .code-block-caption{font-style:italic;font-size:85%;line-height:1;padding:1em 0;text-align:center}@media print{.rst-content .codeblock,.rst-content div[class^=highlight],.rst-content div[class^=highlight] pre{white-space:pre-wrap}}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning{clear:both}.rst-content .admonition-todo .last,.rst-content .admonition-todo>:last-child,.rst-content .admonition .last,.rst-content .admonition>:last-child,.rst-content .attention .last,.rst-content .attention>:last-child,.rst-content .caution .last,.rst-content .caution>:last-child,.rst-content .danger .last,.rst-content .danger>:last-child,.rst-content .error .last,.rst-content .error>:last-child,.rst-content .hint .last,.rst-content .hint>:last-child,.rst-content .important .last,.rst-content .important>:last-child,.rst-content .note .last,.rst-content .note>:last-child,.rst-content .seealso .last,.rst-content .seealso>:last-child,.rst-content .tip .last,.rst-content .tip>:last-child,.rst-content .warning .last,.rst-content .warning>:last-child{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent!important;border-color:rgba(0,0,0,.1)!important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha>li,.rst-content .toctree-wrapper ol.loweralpha,.rst-content .toctree-wrapper ol.loweralpha>li,.rst-content section ol.loweralpha,.rst-content section ol.loweralpha>li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha>li,.rst-content .toctree-wrapper ol.upperalpha,.rst-content .toctree-wrapper ol.upperalpha>li,.rst-content section ol.upperalpha,.rst-content section ol.upperalpha>li{list-style:upper-alpha}.rst-content .section ol li>*,.rst-content .section ul li>*,.rst-content .toctree-wrapper ol li>*,.rst-content .toctree-wrapper ul li>*,.rst-content section ol li>*,.rst-content section ul li>*{margin-top:12px;margin-bottom:12px}.rst-content .section ol li>:first-child,.rst-content .section ul li>:first-child,.rst-content .toctree-wrapper ol li>:first-child,.rst-content .toctree-wrapper ul li>:first-child,.rst-content section ol li>:first-child,.rst-content section ul li>:first-child{margin-top:0}.rst-content .section ol li>p,.rst-content .section ol li>p:last-child,.rst-content .section ul li>p,.rst-content .section ul li>p:last-child,.rst-content .toctree-wrapper ol li>p,.rst-content .toctree-wrapper ol li>p:last-child,.rst-content .toctree-wrapper ul li>p,.rst-content .toctree-wrapper ul li>p:last-child,.rst-content section ol li>p,.rst-content section ol li>p:last-child,.rst-content section ul li>p,.rst-content section ul li>p:last-child{margin-bottom:12px}.rst-content .section ol li>p:only-child,.rst-content .section ol li>p:only-child:last-child,.rst-content .section ul li>p:only-child,.rst-content .section ul li>p:only-child:last-child,.rst-content .toctree-wrapper ol li>p:only-child,.rst-content .toctree-wrapper ol li>p:only-child:last-child,.rst-content .toctree-wrapper ul li>p:only-child,.rst-content .toctree-wrapper ul li>p:only-child:last-child,.rst-content section ol li>p:only-child,.rst-content section ol li>p:only-child:last-child,.rst-content section ul li>p:only-child,.rst-content section ul li>p:only-child:last-child{margin-bottom:0}.rst-content .section ol li>ol,.rst-content .section ol li>ul,.rst-content .section ul li>ol,.rst-content .section ul li>ul,.rst-content .toctree-wrapper ol li>ol,.rst-content .toctree-wrapper ol li>ul,.rst-content .toctree-wrapper ul li>ol,.rst-content .toctree-wrapper ul li>ul,.rst-content section ol li>ol,.rst-content section ol li>ul,.rst-content section ul li>ol,.rst-content section ul li>ul{margin-bottom:12px}.rst-content .section ol.simple li>*,.rst-content .section ol.simple li ol,.rst-content .section ol.simple li ul,.rst-content .section ul.simple li>*,.rst-content .section ul.simple li ol,.rst-content .section ul.simple li ul,.rst-content .toctree-wrapper ol.simple li>*,.rst-content .toctree-wrapper ol.simple li ol,.rst-content .toctree-wrapper ol.simple li ul,.rst-content .toctree-wrapper ul.simple li>*,.rst-content .toctree-wrapper ul.simple li ol,.rst-content .toctree-wrapper ul.simple li ul,.rst-content section ol.simple li>*,.rst-content section ol.simple li ol,.rst-content section ol.simple li ul,.rst-content section ul.simple li>*,.rst-content section ul.simple li ol,.rst-content section ul.simple li ul{margin-top:0;margin-bottom:0}.rst-content .line-block{margin-left:0;margin-bottom:24px;line-height:24px}.rst-content .line-block .line-block{margin-left:24px;margin-bottom:0}.rst-content .topic-title{font-weight:700;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0 0 24px 24px}.rst-content .align-left{float:left;margin:0 24px 24px 0}.rst-content .align-center{margin:auto}.rst-content .align-center:not(table){display:block}.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink{opacity:0;font-size:14px;font-family:FontAwesome;margin-left:.5em}.rst-content .code-block-caption .headerlink:focus,.rst-content .code-block-caption:hover .headerlink,.rst-content .eqno .headerlink:focus,.rst-content .eqno:hover .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink:focus,.rst-content .toctree-wrapper>p.caption:hover .headerlink,.rst-content dl dt .headerlink:focus,.rst-content dl dt:hover .headerlink,.rst-content h1 .headerlink:focus,.rst-content h1:hover .headerlink,.rst-content h2 .headerlink:focus,.rst-content h2:hover .headerlink,.rst-content h3 .headerlink:focus,.rst-content h3:hover .headerlink,.rst-content h4 .headerlink:focus,.rst-content h4:hover .headerlink,.rst-content h5 .headerlink:focus,.rst-content h5:hover .headerlink,.rst-content h6 .headerlink:focus,.rst-content h6:hover .headerlink,.rst-content p.caption .headerlink:focus,.rst-content p.caption:hover .headerlink,.rst-content p .headerlink:focus,.rst-content p:hover .headerlink,.rst-content table>caption .headerlink:focus,.rst-content table>caption:hover .headerlink{opacity:1}.rst-content p a{overflow-wrap:anywhere}.rst-content .wy-table td p,.rst-content .wy-table td ul,.rst-content .wy-table th p,.rst-content .wy-table th ul,.rst-content table.docutils td p,.rst-content table.docutils td ul,.rst-content table.docutils th p,.rst-content table.docutils th ul,.rst-content table.field-list td p,.rst-content table.field-list td ul,.rst-content table.field-list th p,.rst-content table.field-list th ul{font-size:inherit}.rst-content .btn:focus{outline:2px solid}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .centered{text-align:center}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:1px solid #e1e4e5}.rst-content .sidebar dl,.rst-content .sidebar p,.rst-content .sidebar ul{font-size:90%}.rst-content .sidebar .last,.rst-content .sidebar>:last-child{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif;font-weight:700;background:#e1e4e5;padding:6px 12px;margin:-24px -24px 24px;font-size:100%}.rst-content .highlighted{background:#f1c40f;box-shadow:0 0 0 2px #f1c40f;display:inline;font-weight:700}.rst-content .citation-reference,.rst-content .footnote-reference{vertical-align:baseline;position:relative;top:-.4em;line-height:0;font-size:90%}.rst-content .citation-reference>span.fn-bracket,.rst-content .footnote-reference>span.fn-bracket{display:none}.rst-content .hlist{width:100%}.rst-content dl dt span.classifier:before{content:" : "}.rst-content dl dt span.classifier-delimiter{display:none!important}html.writer-html4 .rst-content table.docutils.citation,html.writer-html4 .rst-content table.docutils.footnote{background:none;border:none}html.writer-html4 .rst-content table.docutils.citation td,html.writer-html4 .rst-content table.docutils.citation tr,html.writer-html4 .rst-content table.docutils.footnote td,html.writer-html4 .rst-content table.docutils.footnote tr{border:none;background-color:transparent!important;white-space:normal}html.writer-html4 .rst-content table.docutils.citation td.label,html.writer-html4 .rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{display:grid;grid-template-columns:auto minmax(80%,95%)}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{display:inline-grid;grid-template-columns:max-content auto}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{display:grid;grid-template-columns:auto auto minmax(.65rem,auto) minmax(40%,95%)}html.writer-html5 .rst-content aside.citation>span.label,html.writer-html5 .rst-content aside.footnote>span.label,html.writer-html5 .rst-content div.citation>span.label{grid-column-start:1;grid-column-end:2}html.writer-html5 .rst-content aside.citation>span.backrefs,html.writer-html5 .rst-content aside.footnote>span.backrefs,html.writer-html5 .rst-content div.citation>span.backrefs{grid-column-start:2;grid-column-end:3;grid-row-start:1;grid-row-end:3}html.writer-html5 .rst-content aside.citation>p,html.writer-html5 .rst-content aside.footnote>p,html.writer-html5 .rst-content div.citation>p{grid-column-start:4;grid-column-end:5}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{margin-bottom:24px}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{padding-left:1rem}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dd,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dd,html.writer-html5 .rst-content dl.footnote>dt{margin-bottom:0}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{font-size:.9rem}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.footnote>dt{margin:0 .5rem .5rem 0;line-height:1.2rem;word-break:break-all;font-weight:400}html.writer-html5 .rst-content dl.citation>dt>span.brackets:before,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:before{content:"["}html.writer-html5 .rst-content dl.citation>dt>span.brackets:after,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:after{content:"]"}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a{word-break:keep-all}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a:not(:first-child):before,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.footnote>dd{margin:0 0 .5rem;line-height:1.2rem}html.writer-html5 .rst-content dl.citation>dd p,html.writer-html5 .rst-content dl.footnote>dd p{font-size:.9rem}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{padding-left:1rem;padding-right:1rem;font-size:.9rem;line-height:1.2rem}html.writer-html5 .rst-content aside.citation p,html.writer-html5 .rst-content aside.footnote p,html.writer-html5 .rst-content div.citation p{font-size:.9rem;line-height:1.2rem;margin-bottom:12px}html.writer-html5 .rst-content aside.citation span.backrefs,html.writer-html5 .rst-content aside.footnote span.backrefs,html.writer-html5 .rst-content div.citation span.backrefs{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content aside.citation span.backrefs>a,html.writer-html5 .rst-content aside.footnote span.backrefs>a,html.writer-html5 .rst-content div.citation span.backrefs>a{word-break:keep-all}html.writer-html5 .rst-content aside.citation span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content aside.footnote span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content div.citation span.backrefs>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content aside.citation span.label,html.writer-html5 .rst-content aside.footnote span.label,html.writer-html5 .rst-content div.citation span.label{line-height:1.2rem}html.writer-html5 .rst-content aside.citation-list,html.writer-html5 .rst-content aside.footnote-list,html.writer-html5 .rst-content div.citation-list{margin-bottom:24px}html.writer-html5 .rst-content dl.option-list kbd{font-size:.9rem}.rst-content table.docutils.footnote,html.writer-html4 .rst-content table.docutils.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content aside.footnote-list aside.footnote,html.writer-html5 .rst-content div.citation-list>div.citation,html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{color:grey}.rst-content table.docutils.footnote code,.rst-content table.docutils.footnote tt,html.writer-html4 .rst-content table.docutils.citation code,html.writer-html4 .rst-content table.docutils.citation tt,html.writer-html5 .rst-content aside.footnote-list aside.footnote code,html.writer-html5 .rst-content aside.footnote-list aside.footnote tt,html.writer-html5 .rst-content aside.footnote code,html.writer-html5 .rst-content aside.footnote tt,html.writer-html5 .rst-content div.citation-list>div.citation code,html.writer-html5 .rst-content div.citation-list>div.citation tt,html.writer-html5 .rst-content dl.citation code,html.writer-html5 .rst-content dl.citation tt,html.writer-html5 .rst-content dl.footnote code,html.writer-html5 .rst-content dl.footnote tt{color:#555}.rst-content .wy-table-responsive.citation,.rst-content .wy-table-responsive.footnote{margin-bottom:0}.rst-content .wy-table-responsive.citation+:not(.citation),.rst-content .wy-table-responsive.footnote+:not(.footnote){margin-top:24px}.rst-content .wy-table-responsive.citation:last-child,.rst-content .wy-table-responsive.footnote:last-child{margin-bottom:24px}.rst-content table.docutils th{border-color:#e1e4e5}html.writer-html5 .rst-content table.docutils th{border:1px solid #e1e4e5}html.writer-html5 .rst-content table.docutils td>p,html.writer-html5 .rst-content table.docutils th>p{line-height:1rem;margin-bottom:0;font-size:.9rem}.rst-content table.docutils td .last,.rst-content table.docutils td .last>:last-child{margin-bottom:0}.rst-content table.field-list,.rst-content table.field-list td{border:none}.rst-content table.field-list td p{line-height:inherit}.rst-content table.field-list td>strong{display:inline-block}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left}.rst-content code,.rst-content tt{color:#000;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;padding:2px 5px}.rst-content code big,.rst-content code em,.rst-content tt big,.rst-content tt em{font-size:100%!important;line-height:normal}.rst-content code.literal,.rst-content tt.literal{color:#e74c3c;white-space:normal}.rst-content code.xref,.rst-content tt.xref,a .rst-content code,a .rst-content tt{font-weight:700;color:#404040;overflow-wrap:normal}.rst-content kbd,.rst-content pre,.rst-content samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace}.rst-content a code,.rst-content a tt{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:700;margin-bottom:12px}.rst-content dl ol,.rst-content dl p,.rst-content dl table,.rst-content dl ul{margin-bottom:12px}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}.rst-content dl dd>ol:last-child,.rst-content dl dd>p:last-child,.rst-content dl dd>table:last-child,.rst-content dl dd>ul:last-child{margin-bottom:0}html.writer-html4 .rst-content dl:not(.docutils),html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple){margin-bottom:24px}html.writer-html4 .rst-content dl:not(.docutils)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{display:table;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980b9;border-top:3px solid #6ab0de;padding:6px;position:relative}html.writer-html4 .rst-content dl:not(.docutils)>dt:before,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:before{color:#6ab0de}html.writer-html4 .rst-content dl:not(.docutils)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{margin-bottom:6px;border:none;border-left:3px solid #ccc;background:#f0f0f0;color:#555}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils)>dt:first-child,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:first-child{margin-top:0}html.writer-html4 .rst-content dl:not(.docutils) code.descclassname,html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descclassname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{background-color:transparent;border:none;padding:0;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .optional,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .property,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .property{display:inline-block;padding-right:8px;max-width:100%}html.writer-html4 .rst-content dl:not(.docutils) .k,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .k{font-style:italic}html.writer-html4 .rst-content dl:not(.docutils) .descclassname,html.writer-html4 .rst-content dl:not(.docutils) .descname,html.writer-html4 .rst-content dl:not(.docutils) .sig-name,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .sig-name{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#000}.rst-content .viewcode-back,.rst-content .viewcode-link{display:inline-block;color:#27ae60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:700}.rst-content code.download,.rst-content tt.download{background:inherit;padding:inherit;font-weight:400;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content code.download span:first-child,.rst-content tt.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{margin-right:4px}.rst-content .guilabel,.rst-content .menuselection{font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}.rst-content .guilabel,.rst-content .menuselection{border:1px solid #7fbbe3;background:#e7f2fa}.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>.kbd,.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>kbd{color:inherit;font-size:80%;background-color:#fff;border:1px solid #a6a6a6;border-radius:4px;box-shadow:0 2px grey;padding:2.4px 6px;margin:auto 0}.rst-content .versionmodified{font-style:italic}@media screen and (max-width:480px){.rst-content .sidebar{width:100%}}span[id*=MathJax-Span]{color:#404040}.math{text-align:center}@font-face{font-family:Lato;src:url(fonts/lato-normal.woff2?bd03a2cc277bbbc338d464e679fe9942) format("woff2"),url(fonts/lato-normal.woff?27bd77b9162d388cb8d4c4217c7c5e2a) format("woff");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold.woff2?cccb897485813c7c256901dbca54ecf2) format("woff2"),url(fonts/lato-bold.woff?d878b6c29b10beca227e9eef4246111b) format("woff");font-weight:700;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold-italic.woff2?0b6bb6725576b072c5d0b02ecdd1900d) format("woff2"),url(fonts/lato-bold-italic.woff?9c7e4e9eb485b4a121c760e61bc3707c) format("woff");font-weight:700;font-style:italic;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-normal-italic.woff2?4eb103b4d12be57cb1d040ed5e162e9d) format("woff2"),url(fonts/lato-normal-italic.woff?f28f2d6482446544ef1ea1ccc6dd5892) format("woff");font-weight:400;font-style:italic;font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:400;src:url(fonts/Roboto-Slab-Regular.woff2?7abf5b8d04d26a2cafea937019bca958) format("woff2"),url(fonts/Roboto-Slab-Regular.woff?c1be9284088d487c5e3ff0a10a92e58c) format("woff");font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:700;src:url(fonts/Roboto-Slab-Bold.woff2?9984f4a9bda09be08e83f2506954adbe) format("woff2"),url(fonts/Roboto-Slab-Bold.woff?bed5564a116b05148e3b3bea6fb1162a) format("woff");font-display:block} \ No newline at end of file diff --git a/docs/build/_static/doctools.js b/docs/build/_static/doctools.js new file mode 100644 index 000000000..d06a71d75 --- /dev/null +++ b/docs/build/_static/doctools.js @@ -0,0 +1,156 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Base JavaScript utilities for all Sphinx HTML documentation. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/docs/build/_static/documentation_options.js b/docs/build/_static/documentation_options.js new file mode 100644 index 000000000..89435bb41 --- /dev/null +++ b/docs/build/_static/documentation_options.js @@ -0,0 +1,13 @@ +const DOCUMENTATION_OPTIONS = { + VERSION: '1.0.0', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/docs/build/_static/file.png b/docs/build/_static/file.png new file mode 100644 index 000000000..a858a410e Binary files /dev/null and b/docs/build/_static/file.png differ diff --git a/docs/build/_static/jquery.js b/docs/build/_static/jquery.js new file mode 100644 index 000000000..c4c6022f2 --- /dev/null +++ b/docs/build/_static/jquery.js @@ -0,0 +1,2 @@ +/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=y.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=y.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),y.elements=c+" "+a,j(b)}function f(a){var b=x[a[v]];return b||(b={},w++,a[v]=w,x[w]=b),b}function g(a,c,d){if(c||(c=b),q)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():u.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||t.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),q)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return y.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(y,b.frag)}function j(a){a||(a=b);var d=f(a);return!y.shivCSS||p||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),q||i(a,d),a}function k(a){for(var b,c=a.getElementsByTagName("*"),e=c.length,f=RegExp("^(?:"+d().join("|")+")$","i"),g=[];e--;)b=c[e],f.test(b.nodeName)&&g.push(b.applyElement(l(b)));return g}function l(a){for(var b,c=a.attributes,d=c.length,e=a.ownerDocument.createElement(A+":"+a.nodeName);d--;)b=c[d],b.specified&&e.setAttribute(b.nodeName,b.nodeValue);return e.style.cssText=a.style.cssText,e}function m(a){for(var b,c=a.split("{"),e=c.length,f=RegExp("(^|[\\s,>+~])("+d().join("|")+")(?=[[\\s,>+~#.:]|$)","gi"),g="$1"+A+"\\:$2";e--;)b=c[e]=c[e].split("}"),b[b.length-1]=b[b.length-1].replace(f,g),c[e]=b.join("}");return c.join("{")}function n(a){for(var b=a.length;b--;)a[b].removeNode()}function o(a){function b(){clearTimeout(g._removeSheetTimer),d&&d.removeNode(!0),d=null}var d,e,g=f(a),h=a.namespaces,i=a.parentWindow;return!B||a.printShived?a:("undefined"==typeof h[A]&&h.add(A),i.attachEvent("onbeforeprint",function(){b();for(var f,g,h,i=a.styleSheets,j=[],l=i.length,n=Array(l);l--;)n[l]=i[l];for(;h=n.pop();)if(!h.disabled&&z.test(h.media)){try{f=h.imports,g=f.length}catch(o){g=0}for(l=0;g>l;l++)n.push(f[l]);try{j.push(h.cssText)}catch(o){}}j=m(j.reverse().join("")),e=k(a),d=c(a,j)}),i.attachEvent("onafterprint",function(){n(e),clearTimeout(g._removeSheetTimer),g._removeSheetTimer=setTimeout(b,500)}),a.printShived=!0,a)}var p,q,r="3.7.3",s=a.html5||{},t=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,u=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,v="_html5shiv",w=0,x={};!function(){try{var a=b.createElement("a");a.innerHTML="",p="hidden"in a,q=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){p=!0,q=!0}}();var y={elements:s.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:r,shivCSS:s.shivCSS!==!1,supportsUnknownElements:q,shivMethods:s.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=y,j(b);var z=/^$|\b(?:all|print)\b/,A="html5shiv",B=!q&&function(){var c=b.documentElement;return!("undefined"==typeof b.namespaces||"undefined"==typeof b.parentWindow||"undefined"==typeof c.applyElement||"undefined"==typeof c.removeNode||"undefined"==typeof a.attachEvent)}();y.type+=" print",y.shivPrint=o,o(b),"object"==typeof module&&module.exports&&(module.exports=y)}("undefined"!=typeof window?window:this,document); \ No newline at end of file diff --git a/docs/build/_static/js/html5shiv.min.js b/docs/build/_static/js/html5shiv.min.js new file mode 100644 index 000000000..cd1c674f5 --- /dev/null +++ b/docs/build/_static/js/html5shiv.min.js @@ -0,0 +1,4 @@ +/** +* @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed +*/ +!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3-pre",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document); \ No newline at end of file diff --git a/docs/build/_static/js/theme.js b/docs/build/_static/js/theme.js new file mode 100644 index 000000000..1fddb6ee4 --- /dev/null +++ b/docs/build/_static/js/theme.js @@ -0,0 +1 @@ +!function(n){var e={};function t(i){if(e[i])return e[i].exports;var o=e[i]={i:i,l:!1,exports:{}};return n[i].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=n,t.c=e,t.d=function(n,e,i){t.o(n,e)||Object.defineProperty(n,e,{enumerable:!0,get:i})},t.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},t.t=function(n,e){if(1&e&&(n=t(n)),8&e)return n;if(4&e&&"object"==typeof n&&n&&n.__esModule)return n;var i=Object.create(null);if(t.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:n}),2&e&&"string"!=typeof n)for(var o in n)t.d(i,o,function(e){return n[e]}.bind(null,o));return i},t.n=function(n){var e=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(e,"a",e),e},t.o=function(n,e){return Object.prototype.hasOwnProperty.call(n,e)},t.p="",t(t.s=0)}([function(n,e,t){t(1),n.exports=t(3)},function(n,e,t){(function(){var e="undefined"!=typeof window?window.jQuery:t(2);n.exports.ThemeNav={navBar:null,win:null,winScroll:!1,winResize:!1,linkScroll:!1,winPosition:0,winHeight:null,docHeight:null,isRunning:!1,enable:function(n){var t=this;void 0===n&&(n=!0),t.isRunning||(t.isRunning=!0,e((function(e){t.init(e),t.reset(),t.win.on("hashchange",t.reset),n&&t.win.on("scroll",(function(){t.linkScroll||t.winScroll||(t.winScroll=!0,requestAnimationFrame((function(){t.onScroll()})))})),t.win.on("resize",(function(){t.winResize||(t.winResize=!0,requestAnimationFrame((function(){t.onResize()})))})),t.onResize()})))},enableSticky:function(){this.enable(!0)},init:function(n){n(document);var e=this;this.navBar=n("div.wy-side-scroll:first"),this.win=n(window),n(document).on("click","[data-toggle='wy-nav-top']",(function(){n("[data-toggle='wy-nav-shift']").toggleClass("shift"),n("[data-toggle='rst-versions']").toggleClass("shift")})).on("click",".wy-menu-vertical .current ul li a",(function(){var t=n(this);n("[data-toggle='wy-nav-shift']").removeClass("shift"),n("[data-toggle='rst-versions']").toggleClass("shift"),e.toggleCurrent(t),e.hashChange()})).on("click","[data-toggle='rst-current-version']",(function(){n("[data-toggle='rst-versions']").toggleClass("shift-up")})),n("table.docutils:not(.field-list,.footnote,.citation)").wrap("
"),n("table.docutils.footnote").wrap("
"),n("table.docutils.citation").wrap("
"),n(".wy-menu-vertical ul").not(".simple").siblings("a").each((function(){var t=n(this);expand=n(''),expand.on("click",(function(n){return e.toggleCurrent(t),n.stopPropagation(),!1})),t.prepend(expand)}))},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),t=e.find('[href="'+n+'"]');if(0===t.length){var i=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(t=e.find('[href="#'+i.attr("id")+'"]')).length&&(t=e.find('[href="#"]'))}if(t.length>0){$(".wy-menu-vertical .current").removeClass("current").attr("aria-expanded","false"),t.addClass("current").attr("aria-expanded","true"),t.closest("li.toctree-l1").parent().addClass("current").attr("aria-expanded","true");for(let n=1;n<=10;n++)t.closest("li.toctree-l"+n).addClass("current").attr("aria-expanded","true");t[0].scrollIntoView()}}catch(n){console.log("Error expanding nav for anchor",n)}},onScroll:function(){this.winScroll=!1;var n=this.win.scrollTop(),e=n+this.winHeight,t=this.navBar.scrollTop()+(n-this.winPosition);n<0||e>this.docHeight||(this.navBar.scrollTop(t),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",(function(){this.linkScroll=!1}))},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current").attr("aria-expanded","false"),e.siblings().find("li.current").removeClass("current").attr("aria-expanded","false");var t=e.find("> ul li");t.length&&(t.removeClass("current").attr("aria-expanded","false"),e.toggleClass("current").attr("aria-expanded",(function(n,e){return"true"==e?"false":"true"})))}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:n.exports.ThemeNav,StickyNav:n.exports.ThemeNav}),function(){for(var n=0,e=["ms","moz","webkit","o"],t=0;t0 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) + return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0,1); + if (firstch == "y") + w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) + w = w.replace(re,"$1$2"); + else if (re2.test(w)) + w = w.replace(re2,"$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re,""); + } + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) + w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + else if (re4.test(w)) + w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) + w = stem + "i"; + } + + // Step 2 + re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) + w = stem; + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) + w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) + w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + + // and turn initial Y back to y + if (firstch == "y") + w = firstch.toLowerCase() + w.substr(1); + return w; + } +} + diff --git a/docs/build/_static/minus.png b/docs/build/_static/minus.png new file mode 100644 index 000000000..d96755fda Binary files /dev/null and b/docs/build/_static/minus.png differ diff --git a/docs/build/_static/plus.png b/docs/build/_static/plus.png new file mode 100644 index 000000000..7107cec93 Binary files /dev/null and b/docs/build/_static/plus.png differ diff --git a/docs/build/_static/pygments.css b/docs/build/_static/pygments.css new file mode 100644 index 000000000..84ab3030a --- /dev/null +++ b/docs/build/_static/pygments.css @@ -0,0 +1,75 @@ +pre { line-height: 125%; } +td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +.highlight .hll { background-color: #ffffcc } +.highlight { background: #f8f8f8; } +.highlight .c { color: #3D7B7B; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid #FF0000 } /* Error */ +.highlight .k { color: #008000; font-weight: bold } /* Keyword */ +.highlight .o { color: #666666 } /* Operator */ +.highlight .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */ +.highlight .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #9C6500 } /* Comment.Preproc */ +.highlight .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */ +.highlight .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ +.highlight .gr { color: #E40000 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #008400 } /* Generic.Inserted */ +.highlight .go { color: #717171 } /* Generic.Output */ +.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #0044DD } /* Generic.Traceback */ +.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #008000 } /* Keyword.Pseudo */ +.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #B00040 } /* Keyword.Type */ +.highlight .m { color: #666666 } /* Literal.Number */ +.highlight .s { color: #BA2121 } /* Literal.String */ +.highlight .na { color: #687822 } /* Name.Attribute */ +.highlight .nb { color: #008000 } /* Name.Builtin */ +.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */ +.highlight .no { color: #880000 } /* Name.Constant */ +.highlight .nd { color: #AA22FF } /* Name.Decorator */ +.highlight .ni { color: #717171; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #0000FF } /* Name.Function */ +.highlight .nl { color: #767600 } /* Name.Label */ +.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #19177C } /* Name.Variable */ +.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mb { color: #666666 } /* Literal.Number.Bin */ +.highlight .mf { color: #666666 } /* Literal.Number.Float */ +.highlight .mh { color: #666666 } /* Literal.Number.Hex */ +.highlight .mi { color: #666666 } /* Literal.Number.Integer */ +.highlight .mo { color: #666666 } /* Literal.Number.Oct */ +.highlight .sa { color: #BA2121 } /* Literal.String.Affix */ +.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */ +.highlight .sc { color: #BA2121 } /* Literal.String.Char */ +.highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */ +.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #BA2121 } /* Literal.String.Double */ +.highlight .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */ +.highlight .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */ +.highlight .sx { color: #008000 } /* Literal.String.Other */ +.highlight .sr { color: #A45A77 } /* Literal.String.Regex */ +.highlight .s1 { color: #BA2121 } /* Literal.String.Single */ +.highlight .ss { color: #19177C } /* Literal.String.Symbol */ +.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */ +.highlight .fm { color: #0000FF } /* Name.Function.Magic */ +.highlight .vc { color: #19177C } /* Name.Variable.Class */ +.highlight .vg { color: #19177C } /* Name.Variable.Global */ +.highlight .vi { color: #19177C } /* Name.Variable.Instance */ +.highlight .vm { color: #19177C } /* Name.Variable.Magic */ +.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/docs/build/_static/searchtools.js b/docs/build/_static/searchtools.js new file mode 100644 index 000000000..7918c3fab --- /dev/null +++ b/docs/build/_static/searchtools.js @@ -0,0 +1,574 @@ +/* + * searchtools.js + * ~~~~~~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for the full-text search. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +/** + * Simple result scoring code. + */ +if (typeof Scorer === "undefined") { + var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [docname, title, anchor, descr, score, filename] + // and returns the new score. + /* + score: result => { + const [docname, title, anchor, descr, score, filename] = result + return score + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: { + 0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5, // used to be unimportantResults + }, + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + partialTitle: 7, + // query found in terms + term: 5, + partialTerm: 2, + }; +} + +const _removeChildren = (element) => { + while (element && element.lastChild) element.removeChild(element.lastChild); +}; + +/** + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping + */ +const _escapeRegExp = (string) => + string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string + +const _displayItem = (item, searchTerms, highlightTerms) => { + const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; + const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; + const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; + const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; + const contentRoot = document.documentElement.dataset.content_root; + + const [docName, title, anchor, descr, score, _filename] = item; + + let listItem = document.createElement("li"); + let requestUrl; + let linkUrl; + if (docBuilder === "dirhtml") { + // dirhtml builder + let dirname = docName + "/"; + if (dirname.match(/\/index\/$/)) + dirname = dirname.substring(0, dirname.length - 6); + else if (dirname === "index/") dirname = ""; + requestUrl = contentRoot + dirname; + linkUrl = requestUrl; + } else { + // normal html builders + requestUrl = contentRoot + docName + docFileSuffix; + linkUrl = docName + docLinkSuffix; + } + let linkEl = listItem.appendChild(document.createElement("a")); + linkEl.href = linkUrl + anchor; + linkEl.dataset.score = score; + linkEl.innerHTML = title; + if (descr) { + listItem.appendChild(document.createElement("span")).innerHTML = + " (" + descr + ")"; + // highlight search terms in the description + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); + } + else if (showSearchSummary) + fetch(requestUrl) + .then((responseData) => responseData.text()) + .then((data) => { + if (data) + listItem.appendChild( + Search.makeSearchSummary(data, searchTerms) + ); + // highlight search terms in the summary + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); + }); + Search.output.appendChild(listItem); +}; +const _finishSearch = (resultCount) => { + Search.stopPulse(); + Search.title.innerText = _("Search Results"); + if (!resultCount) + Search.status.innerText = Documentation.gettext( + "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories." + ); + else + Search.status.innerText = _( + `Search finished, found ${resultCount} page(s) matching the search query.` + ); +}; +const _displayNextItem = ( + results, + resultCount, + searchTerms, + highlightTerms, +) => { + // results left, load the summary and display it + // this is intended to be dynamic (don't sub resultsCount) + if (results.length) { + _displayItem(results.pop(), searchTerms, highlightTerms); + setTimeout( + () => _displayNextItem(results, resultCount, searchTerms, highlightTerms), + 5 + ); + } + // search finished, update title and status message + else _finishSearch(resultCount); +}; + +/** + * Default splitQuery function. Can be overridden in ``sphinx.search`` with a + * custom function per language. + * + * The regular expression works by splitting the string on consecutive characters + * that are not Unicode letters, numbers, underscores, or emoji characters. + * This is the same as ``\W+`` in Python, preserving the surrogate pair area. + */ +if (typeof splitQuery === "undefined") { + var splitQuery = (query) => query + .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) + .filter(term => term) // remove remaining empty strings +} + +/** + * Search Module + */ +const Search = { + _index: null, + _queued_query: null, + _pulse_status: -1, + + htmlToText: (htmlString) => { + const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); + htmlElement.querySelectorAll(".headerlink").forEach((el) => { el.remove() }); + const docContent = htmlElement.querySelector('[role="main"]'); + if (docContent !== undefined) return docContent.textContent; + console.warn( + "Content block not found. Sphinx search tries to obtain it via '[role=main]'. Could you check your theme or template." + ); + return ""; + }, + + init: () => { + const query = new URLSearchParams(window.location.search).get("q"); + document + .querySelectorAll('input[name="q"]') + .forEach((el) => (el.value = query)); + if (query) Search.performSearch(query); + }, + + loadIndex: (url) => + (document.body.appendChild(document.createElement("script")).src = url), + + setIndex: (index) => { + Search._index = index; + if (Search._queued_query !== null) { + const query = Search._queued_query; + Search._queued_query = null; + Search.query(query); + } + }, + + hasIndex: () => Search._index !== null, + + deferQuery: (query) => (Search._queued_query = query), + + stopPulse: () => (Search._pulse_status = -1), + + startPulse: () => { + if (Search._pulse_status >= 0) return; + + const pulse = () => { + Search._pulse_status = (Search._pulse_status + 1) % 4; + Search.dots.innerText = ".".repeat(Search._pulse_status); + if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); + }; + pulse(); + }, + + /** + * perform a search for something (or wait until index is loaded) + */ + performSearch: (query) => { + // create the required interface elements + const searchText = document.createElement("h2"); + searchText.textContent = _("Searching"); + const searchSummary = document.createElement("p"); + searchSummary.classList.add("search-summary"); + searchSummary.innerText = ""; + const searchList = document.createElement("ul"); + searchList.classList.add("search"); + + const out = document.getElementById("search-results"); + Search.title = out.appendChild(searchText); + Search.dots = Search.title.appendChild(document.createElement("span")); + Search.status = out.appendChild(searchSummary); + Search.output = out.appendChild(searchList); + + const searchProgress = document.getElementById("search-progress"); + // Some themes don't use the search progress node + if (searchProgress) { + searchProgress.innerText = _("Preparing search..."); + } + Search.startPulse(); + + // index already loaded, the browser was quick! + if (Search.hasIndex()) Search.query(query); + else Search.deferQuery(query); + }, + + /** + * execute search (requires search index to be loaded) + */ + query: (query) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + + // stem the search terms and add them to the correct list + const stemmer = new Stemmer(); + const searchTerms = new Set(); + const excludedTerms = new Set(); + const highlightTerms = new Set(); + const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); + splitQuery(query.trim()).forEach((queryTerm) => { + const queryTermLower = queryTerm.toLowerCase(); + + // maybe skip this "word" + // stopwords array is from language_data.js + if ( + stopwords.indexOf(queryTermLower) !== -1 || + queryTerm.match(/^\d+$/) + ) + return; + + // stem the word + let word = stemmer.stemWord(queryTermLower); + // select the correct list + if (word[0] === "-") excludedTerms.add(word.substr(1)); + else { + searchTerms.add(word); + highlightTerms.add(queryTermLower); + } + }); + + if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js + localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" ")) + } + + // console.debug("SEARCH: searching for:"); + // console.info("required: ", [...searchTerms]); + // console.info("excluded: ", [...excludedTerms]); + + // array of [docname, title, anchor, descr, score, filename] + let results = []; + _removeChildren(document.getElementById("search-progress")); + + const queryLower = query.toLowerCase(); + for (const [title, foundTitles] of Object.entries(allTitles)) { + if (title.toLowerCase().includes(queryLower) && (queryLower.length >= title.length/2)) { + for (const [file, id] of foundTitles) { + let score = Math.round(100 * queryLower.length / title.length) + results.push([ + docNames[file], + titles[file] !== title ? `${titles[file]} > ${title}` : title, + id !== null ? "#" + id : "", + null, + score, + filenames[file], + ]); + } + } + } + + // search for explicit entries in index directives + for (const [entry, foundEntries] of Object.entries(indexEntries)) { + if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { + for (const [file, id] of foundEntries) { + let score = Math.round(100 * queryLower.length / entry.length) + results.push([ + docNames[file], + titles[file], + id ? "#" + id : "", + null, + score, + filenames[file], + ]); + } + } + } + + // lookup as object + objectTerms.forEach((term) => + results.push(...Search.performObjectSearch(term, objectTerms)) + ); + + // lookup as search terms in fulltext + results.push(...Search.performTermsSearch(searchTerms, excludedTerms)); + + // let the scorer override scores with a custom scoring function + if (Scorer.score) results.forEach((item) => (item[4] = Scorer.score(item))); + + // now sort the results by score (in opposite order of appearance, since the + // display function below uses pop() to retrieve items) and then + // alphabetically + results.sort((a, b) => { + const leftScore = a[4]; + const rightScore = b[4]; + if (leftScore === rightScore) { + // same score: sort alphabetically + const leftTitle = a[1].toLowerCase(); + const rightTitle = b[1].toLowerCase(); + if (leftTitle === rightTitle) return 0; + return leftTitle > rightTitle ? -1 : 1; // inverted is intentional + } + return leftScore > rightScore ? 1 : -1; + }); + + // remove duplicate search results + // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept + let seen = new Set(); + results = results.reverse().reduce((acc, result) => { + let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(','); + if (!seen.has(resultStr)) { + acc.push(result); + seen.add(resultStr); + } + return acc; + }, []); + + results = results.reverse(); + + // for debugging + //Search.lastresults = results.slice(); // a copy + // console.info("search results:", Search.lastresults); + + // print the results + _displayNextItem(results, results.length, searchTerms, highlightTerms); + }, + + /** + * search for object names + */ + performObjectSearch: (object, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const objects = Search._index.objects; + const objNames = Search._index.objnames; + const titles = Search._index.titles; + + const results = []; + + const objectSearchCallback = (prefix, match) => { + const name = match[4] + const fullname = (prefix ? prefix + "." : "") + name; + const fullnameLower = fullname.toLowerCase(); + if (fullnameLower.indexOf(object) < 0) return; + + let score = 0; + const parts = fullnameLower.split("."); + + // check for different match types: exact matches of full name or + // "last name" (i.e. last dotted part) + if (fullnameLower === object || parts.slice(-1)[0] === object) + score += Scorer.objNameMatch; + else if (parts.slice(-1)[0].indexOf(object) > -1) + score += Scorer.objPartialMatch; // matches in last name + + const objName = objNames[match[1]][2]; + const title = titles[match[0]]; + + // If more than one term searched for, we require other words to be + // found in the name/title/description + const otherTerms = new Set(objectTerms); + otherTerms.delete(object); + if (otherTerms.size > 0) { + const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); + if ( + [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) + ) + return; + } + + let anchor = match[3]; + if (anchor === "") anchor = fullname; + else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; + + const descr = objName + _(", in ") + title; + + // add custom score for some objects according to scorer + if (Scorer.objPrio.hasOwnProperty(match[2])) + score += Scorer.objPrio[match[2]]; + else score += Scorer.objPrioDefault; + + results.push([ + docNames[match[0]], + fullname, + "#" + anchor, + descr, + score, + filenames[match[0]], + ]); + }; + Object.keys(objects).forEach((prefix) => + objects[prefix].forEach((array) => + objectSearchCallback(prefix, array) + ) + ); + return results; + }, + + /** + * search for full-text terms in the index + */ + performTermsSearch: (searchTerms, excludedTerms) => { + // prepare search + const terms = Search._index.terms; + const titleTerms = Search._index.titleterms; + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + + const scoreMap = new Map(); + const fileMap = new Map(); + + // perform the search on the required terms + searchTerms.forEach((word) => { + const files = []; + const arr = [ + { files: terms[word], score: Scorer.term }, + { files: titleTerms[word], score: Scorer.title }, + ]; + // add support for partial matches + if (word.length > 2) { + const escapedWord = _escapeRegExp(word); + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord) && !terms[word]) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord) && !titleTerms[word]) + arr.push({ files: titleTerms[word], score: Scorer.partialTitle }); + }); + } + + // no match but word was a required one + if (arr.every((record) => record.files === undefined)) return; + + // found search word in contents + arr.forEach((record) => { + if (record.files === undefined) return; + + let recordFiles = record.files; + if (recordFiles.length === undefined) recordFiles = [recordFiles]; + files.push(...recordFiles); + + // set score for the word in each file + recordFiles.forEach((file) => { + if (!scoreMap.has(file)) scoreMap.set(file, {}); + scoreMap.get(file)[word] = record.score; + }); + }); + + // create the mapping + files.forEach((file) => { + if (fileMap.has(file) && fileMap.get(file).indexOf(word) === -1) + fileMap.get(file).push(word); + else fileMap.set(file, [word]); + }); + }); + + // now check if the files don't contain excluded terms + const results = []; + for (const [file, wordList] of fileMap) { + // check if all requirements are matched + + // as search terms with length < 3 are discarded + const filteredTermCount = [...searchTerms].filter( + (term) => term.length > 2 + ).length; + if ( + wordList.length !== searchTerms.size && + wordList.length !== filteredTermCount + ) + continue; + + // ensure that none of the excluded terms is in the search result + if ( + [...excludedTerms].some( + (term) => + terms[term] === file || + titleTerms[term] === file || + (terms[term] || []).includes(file) || + (titleTerms[term] || []).includes(file) + ) + ) + break; + + // select one (max) score for the file. + const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w])); + // add result to the result list + results.push([ + docNames[file], + titles[file], + "", + null, + score, + filenames[file], + ]); + } + return results; + }, + + /** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words. + */ + makeSearchSummary: (htmlText, keywords) => { + const text = Search.htmlToText(htmlText); + if (text === "") return null; + + const textLower = text.toLowerCase(); + const actualStartPosition = [...keywords] + .map((k) => textLower.indexOf(k.toLowerCase())) + .filter((i) => i > -1) + .slice(-1)[0]; + const startWithContext = Math.max(actualStartPosition - 120, 0); + + const top = startWithContext === 0 ? "" : "..."; + const tail = startWithContext + 240 < text.length ? "..." : ""; + + let summary = document.createElement("p"); + summary.classList.add("context"); + summary.textContent = top + text.substr(startWithContext, 240).trim() + tail; + + return summary; + }, +}; + +_ready(Search.init); diff --git a/docs/build/_static/sphinx_highlight.js b/docs/build/_static/sphinx_highlight.js new file mode 100644 index 000000000..8a96c69a1 --- /dev/null +++ b/docs/build/_static/sphinx_highlight.js @@ -0,0 +1,154 @@ +/* Highlighting utilities for Sphinx HTML documentation. */ +"use strict"; + +const SPHINX_HIGHLIGHT_ENABLED = true + +/** + * highlight a given string on a node by wrapping it in + * span elements with the given class name. + */ +const _highlight = (node, addItems, text, className) => { + if (node.nodeType === Node.TEXT_NODE) { + const val = node.nodeValue; + const parent = node.parentNode; + const pos = val.toLowerCase().indexOf(text); + if ( + pos >= 0 && + !parent.classList.contains(className) && + !parent.classList.contains("nohighlight") + ) { + let span; + + const closestNode = parent.closest("body, svg, foreignObject"); + const isInSVG = closestNode && closestNode.matches("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.classList.add(className); + } + + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + const rest = document.createTextNode(val.substr(pos + text.length)); + parent.insertBefore( + span, + parent.insertBefore( + rest, + node.nextSibling + ) + ); + node.nodeValue = val.substr(0, pos); + /* There may be more occurrences of search term in this node. So call this + * function recursively on the remaining fragment. + */ + _highlight(rest, addItems, text, className); + + if (isInSVG) { + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + const bbox = parent.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute("class", className); + addItems.push({ parent: parent, target: rect }); + } + } + } else if (node.matches && !node.matches("button, select, textarea")) { + node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); + } +}; +const _highlightText = (thisNode, text, className) => { + let addItems = []; + _highlight(thisNode, addItems, text, className); + addItems.forEach((obj) => + obj.parent.insertAdjacentElement("beforebegin", obj.target) + ); +}; + +/** + * Small JavaScript module for the documentation. + */ +const SphinxHighlight = { + + /** + * highlight the search words provided in localstorage in the text + */ + highlightSearchWords: () => { + if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight + + // get and clear terms from localstorage + const url = new URL(window.location); + const highlight = + localStorage.getItem("sphinx_highlight_terms") + || url.searchParams.get("highlight") + || ""; + localStorage.removeItem("sphinx_highlight_terms") + url.searchParams.delete("highlight"); + window.history.replaceState({}, "", url); + + // get individual terms from highlight string + const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); + if (terms.length === 0) return; // nothing to do + + // There should never be more than one element matching "div.body" + const divBody = document.querySelectorAll("div.body"); + const body = divBody.length ? divBody[0] : document.querySelector("body"); + window.setTimeout(() => { + terms.forEach((term) => _highlightText(body, term, "highlighted")); + }, 10); + + const searchBox = document.getElementById("searchbox"); + if (searchBox === null) return; + searchBox.appendChild( + document + .createRange() + .createContextualFragment( + '" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(() => { + /* Do not call highlightSearchWords() when we are on the search page. + * It will highlight words from the *previous* search query. + */ + if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); + SphinxHighlight.initEscapeListener(); +}); diff --git a/docs/build/analysis.html b/docs/build/analysis.html new file mode 100644 index 000000000..2d6b316da --- /dev/null +++ b/docs/build/analysis.html @@ -0,0 +1,297 @@ + + + + + + + Post-simulation analysis — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +
+

Post-simulation analysis

+
+

Submodules

+
+
+

cost_analysis module

+

This module contains the CostEstimator Class, which estimates the cost of the different grid and DER components +from the simulation.

+
+
+class analysis.cost_analysis.CostEstimator(num_days)[source]
+

Bases: object

+

This class is used to calculate levelized cost of DER assets in EV-Ecosim.

+
+
Parameters:
+

num_days – The number of days for which the calculation is run.

+
+
+
+
+calculate_battery_cost(result_dir)[source]
+

Calculates the battery costs and updates the different cost components, including LCOE.

+
+
Parameters:
+

result_dir – Directory in which to save the results dictionary.

+
+
Return dict result_dict:
+

Dictionary of results.

+
+
+
+ +
+
+calculate_electricity_cost_PGEBEV2s(result_dir, PGE_separate_file=True)[source]
+

Calculates the overall electricity PGEBEV2S cost for a given scenario.

+
+
Parameters:
+
    +
  • result_dir (str) – Directory in which the result is saved.

  • +
  • PGE_separate_file

  • +
+
+
Return dict result_dict:
+

A dictionary comprising all the cost components and their dollar amounts.

+
+
+
+ +
+
+calculate_solar_cost()[source]
+

Values are pulled from the NREL solar cost calculator. +Ref: https://www.nrel.gov/solar/market-research-analysis/solar-levelized-cost.html +To be deprecated soon.

+
+
Returns:
+

None

+
+
+
+ +
+
+calculate_trans_loss_of_life(result_dir)[source]
+

Estimates the expected transformer loss of life.

+

Reference:

+
    +
  • 5.11.3 of IEEE Std C57.12.00-2010 a minimum normal insulation life expectancy of 180 000 hours is expected.

  • +
+
+
Parameters:
+

result_dir – Directory in which the loss results is saved.

+
+
Returns:
+

Dictionary of transformer losses.

+
+
+
+ +
+
+static plot_loads(total_load, net_load, prefix=None, labels: list | None = None)[source]
+

Creates plots overlaying load and net loads for post-simulation visualization.

+
+
Parameters:
+
    +
  • total_load – Overall EV load demand at node, can include building load if controllable.

  • +
  • net_load – total_load minus DER buffer.

  • +
  • prefix – Plot file label prefix.

  • +
  • labels – Legend labels for each plotted curve.

  • +
+
+
Returns:
+

None.

+
+
+
+ +
+
+static plot_power(power, power_pred, prefix=None, labels: list | None = None)[source]
+

Plots the controller predicted and true power of the battery system.

+
+
Parameters:
+
    +
  • power – True power.

  • +
  • power_pred – Controller predicted power.

  • +
  • prefix – Plot file label prefix.

  • +
  • labels – Legend labels for each plotted curve.

  • +
+
+
Returns:
+

None.

+
+
+
+ +
+
+static plot_soc(soc, soc_pred, prefix=None, labels: list | None = None)[source]
+

Plots the controller predicted and true state of charge of the battery system.

+
+
Parameters:
+
    +
  • soc – True state of charge.

  • +
  • soc_pred – Controller predicted state of charge.

  • +
  • prefix – Plot file label prefix.

  • +
  • labels – Legend labels for each plotted curve.

  • +
+
+
Returns:
+

None.

+
+
+
+ +
+
+solar_cost(result_dir)[source]
+

Calculates the overall capital cost of the solar system. +Not fully implemented.

+
+
Parameters:
+

result_dir (str) – Location to save the result.

+
+
Returns:
+

Solar PV capital cost.

+
+
+
+ +
+
+transformer_cost()[source]
+

Cannot find good resource data for this yet.

+
+ +
+ +
+
+

load_post_opt_costs module

+
+
+

plot_results module

+
+
+

Module contents

+

This module runs the post-simulation cost calculations for DER assets and transformer aging. +This module also estimates the voltage violations within the distribution network.

+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/build/charging_sim.html b/docs/build/charging_sim.html new file mode 100644 index 000000000..527142b1a --- /dev/null +++ b/docs/build/charging_sim.html @@ -0,0 +1,653 @@ + + + + + + + Charging simulator — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +
+

Charging simulator

+
+

Submodules

+
+
+

charging_sim.battery module

+
+
+

charging_sim.batteryAgingSim module

+

This module contains the BatteryAging class. The battery aging objects enact on the battery object and update the +battery capacity and resistance at each simulation time-step.

+
+
+class charging_sim.batteryAgingSim.BatteryAging(datetime, num_steps, res=15)[source]
+

Bases: object

+

Current aging model is for LiNiMnCoO2 (NMC) battery cells. More aging models will be added in the future.

+

Link to Paper: https://www.sciencedirect.com/science/article/pii/S0378775314001876

+
+
Default Params from paper:
    +
  • beta_cap: capacity fade aging factor for cycle aging

  • +
  • alpha_cap capacity fade aging factor for calendar aging

  • +
  • beta_res: resistance growth aging factor for cycle aging

  • +
  • alpha_res: resistance growth aging factor for calendar aging

  • +
+
+
Assumptions:
    +
  • Homogenous battery with dynamics modelled.

  • +
  • Uniform aging across all cells.

  • +
  • Constant temperature profile in vicinity of battery.

  • +
+
+
+
+
+static LFP_cal_aging()[source]
+
+ +
+
+static LFP_cyc_aging()[source]
+
+ +
+
+static NMC_cal_aging()[source]
+
+ +
+
+static NMC_cyc_aging()[source]
+
+ +
+
+get_aging_value(battery)[source]
+

Returns the total capacity fade and resistance growth of the battery object.

+
+
Parameters:
+

battery – The battery (pack) object.

+
+
Returns:
+

List of total capacity fade and resistance growth of the battery.

+
+
+
+ +
+
+get_calendar_aging(battery)[source]
+

Returns the calendar aging of the battery object.

+
+
Parameters:
+

battery – The battery object.

+
+
Returns:
+

A tuple of capacity fade and resistance growth due to calendar aging.

+
+
+
+ +
+
+get_cyc_aging(battery)[source]
+

Calculates the resistance growth and capacity fade from cycle aging.

+
+
Parameters:
+

battery – THe batt

+
+
Returns:
+

+
+
+
+ +
+
+get_total_aging(battery: object)[source]
+

Returns the total capacity fade of the battery object. This includes both cycle and calendar aging.

+
+
Parameters:
+

battery (object) – The battery (pack) object.

+
+
Returns:
+

Total calendar + cycle aging of the battery.

+
+
+
+ +
+
+run(battery)[source]
+

Runs the aging model for the battery object.

+
+
Parameters:
+

battery – The battery (pack) object.

+
+
Returns:
+

None. Updates the battery object.

+
+
+
+ +
+
+update_capacity(battery)[source]
+

Updates the capacity of the battery based on the aging model adopted from Schmalsteig Et. Al.

+
+
Parameters:
+

battery – Battery object.

+
+
Returns:
+

None. Updates the battery object capacity.

+
+
+
+ +
+
+update_resistance(battery)[source]
+

Updates the resistance of the battery based on the aging model adopted from Schmalsteig Et. Al.

+
+
Parameters:
+

battery – Battery object.

+
+
Returns:
+

None. Updates the battery object resistance.

+
+
+
+ +
+ +
+
+

charging_sim.batterypack module

+
+
+

charging_sim.batterytest module

+
+
+

charging_sim.capacitor module

+

This file hosts the class for capacitors. Future work

+
+
+class charging_sim.capacitor.Capacitor(name)[source]
+

Bases: object

+
+ +
+
+

charging_sim.chargingStation module

+
+
+

charging_sim.controller module

+
+
+

charging_sim.electricityPrices module

+

This module contains the class that loads the electricity price data and structure used for sampling prices during +simulation.

+

Based on the prices.json config file, this module will load the desired price TOU rate file that will be used in +optimization problem. The default is the PGE_BEV2_S rate file, which is valid for California, however users can load +their own TOU rate file. The prices are loaded into a numpy array and can be sampled from during simulation. +The prices are sampled based on the month of the year and the hour of the day.

+
+
+class charging_sim.electricityPrices.PriceLoader(config, path_prefix=None)[source]
+

Bases: object

+

This class pre-loads prices and is used to sample prices that are used for optimization of EVSE profits/costs +during charging simulation.

+
+
Parameters:
+
    +
  • config (dict) – Configuration dictionary for the price loader.

  • +
  • path_prefix – This string path prefix is obtained first based on your repository location to set the

  • +
+
+
+

correct path for obtaining the data.

+
+
+downscale(input_res, output_res)[source]
+

Downscales the price data into a finer resolution, similar to the downscaling method in Pandas. +Typically only used once.

+
+
Parameters:
+
    +
  • input_res – Resolution of the input data.

  • +
  • output_res – Resolution of the output data.

  • +
+
+
Returns:
+

None. Saves output data to a csv file.

+
+
+
+ +
+
+get_prices(start_idx, num_steps, month=7)[source]
+

Returns time-of-use (TOU) rate prices from data. This assumes TOU rates do not change day-to-day.

+
+
Parameters:
+
    +
  • start_idx (int) – Starting index from which to price vector will start.

  • +
  • num_steps (int) – Cardinality of the price vector being returned.

  • +
  • month (int) – Month for which the price vector will be obtained (for example, 1 - Jan, 12 - December).

  • +
+
+
Return ndarray price_vector:
+

The TOU price vector, which is a numpy array.

+
+
+
+ +
+
+set_month_data(month)[source]
+

Sets the month for which the prices will be obtained.

+
+
Parameters:
+

month – Month to set the data to.

+
+
Returns:
+

None.

+
+
+
+ +
+ +
+
+charging_sim.electricityPrices.main()[source]
+

This is only run to generate new downscaled data or for testing.

+
+ +
+
+

charging_sim.optimization module

+

Contains the Optimization class, which is used by controller to solve the optimization problem.

+
+
+class charging_sim.optimization.Optimization(objective_type, objective, controller, power_demand, time_res, transformer, battery, time=0, name=None, solar=None, solver='GUROBI')[source]
+

Bases: object

+

Constructor for the overall optimization problem solved by the optimization-based controller.

+
    +
  • Designed to include future cost functions such as transformer degradation and battery aging.

  • +
  • Limited to convex and Mixed Integer programs, depending on the selected solver.

  • +
  • Note, each desired solver must be installed separately on user’s PC for a successful run.

  • +
+
+
Parameters:
+
    +
  • objective_type – Type of objective problem being optimized.

  • +
  • objective – CVXPY objective function object.

  • +
  • controller – Controller object.

  • +
  • power_demand – Power demand at the Charging Station.

  • +
  • time_res – Time resolution of problem data.

  • +
  • transformer – Transformer object (optional, not implemented yet).

  • +
  • battery – Battery object.

  • +
  • time – Time Counter.

  • +
  • name – Optimization identifier.

  • +
  • solar – Solar Object.

  • +
  • solver (str) – Available backend solver to invoke (ECOS, MOSEK, GUROBI, etc.).

  • +
+
+
+
+
+add_demand_charge(charge)[source]
+

Including demand charge in the objective function (Deprecated).

+
+
Parameters:
+

charge – Demand charge ($/kW).

+
+
Returns:
+

+
+
+
+ +
+
+aggregate_constraints()[source]
+

Aggregates all the constraints into one constraint list within the object.

+
+
Returns:
+

None.

+
+
+
+ +
+
+build_battery_cost()[source]
+

Build battery cost (to be implemented in future version).

+
+
Returns:
+

+
+
+
+ +
+
+build_emissions_cost()[source]
+

Builds emission cost to be included in the objective function (future work).

+
+
Returns:
+

+
+
+
+ +
+
+build_transformer_cost()[source]
+

Build Transformer cost (to be implemented in future version).

+
+
Returns:
+

+
+
+
+ +
+
+get_battery_constraint()[source]
+

Returns the list of battery constraints within the controller.

+
+
Returns:
+

Battery constraints.

+
+
+
+ +
+
+get_constraints()[source]
+

Returns the constraints list.

+
+
Returns:
+

List of all constraints within the problem.

+
+
+
+ +
+
+run()[source]
+

Runs an instance of the optimization problem.

+
+
Return float:
+

Optimal objective value.

+
+
+
+ +
+ +
+
+

charging_sim.orchestrator module

+
+
+

charging_sim.simulate module

+
+
+

charging_sim.solar module

+

This module contains the Solar class. The solar class is used to simulate the solar power generation at a given site +by sampling Global Horizontal Irradiance (GHI) data from the dataset of the desired location.

+
+
+class charging_sim.solar.Solar(config, path_prefix=None, controller=None, num_steps=None)[source]
+

Bases: object

+

This class is used to simulate the solar power generation at a given site by sampling Global Horizontal Irradiance +and estimating the solar generation, given the solar nameplate capacity that can be modified it its configuration +file solar.json. It also contains the optimization variables for the solar system.

+

The solar power generation is estimated using the following equation:

+
+\[P_{solar} = \min(P_{rated}, \eta * A * GHI).\]
+

Where \(P_{solar}\) is the solar power generation, \(\eta\) is the efficiency of the solar system, +\(P_{rated}\) is the solar nameplate capacity, \(A\) is the area of the solar panels, and \(GHI\) is +the Global Horizontal Irradiance.

+
+
Parameters:
+
    +
  • config – Solar configuration dictionary.

  • +
  • path_prefix – This string path prefix is obtained first based on your repository location to set the right path.

  • +
  • controller – Controller object for making decisions on flow of power from energy devices.

  • +
  • num_steps – Number of steps in the simulation.

  • +
+
+
+
+
+downscale(input_res, output_res)[source]
+

This is used only to initially downscale data to desired resolution

+
+ +
+
+get_constraints()[source]
+
+ +
+
+get_power(start_idx, num_steps, desired_shape=(96, 1), month=None)[source]
+
+ +
+
+get_solar_output()[source]
+
+ +
+
+modify_res(new_res)[source]
+
+ +
+
+update_history()[source]
+
+ +
+ +
+
+charging_sim.solar.main()[source]
+

THis is mainly to testing or generating new data purposes

+
+ +
+
+

charging_sim.utils module

+

Maybe stores general configurations and general functions

+
+
+charging_sim.utils.PGE_BEV2_S()[source]
+

Price schedule/TOU rate for PGE EVSE doc can be found here:

+
+ +
+
+charging_sim.utils.add_power_profile_to_object(battery, index, battery_power_profile)[source]
+
+ +
+
+charging_sim.utils.build_cost_PGE_BEV2S(controller, load, energy_prices_TOU, penalize_max_power=True, max_power_pen=1000)[source]
+

This will need to use a heuristic and take the average conservative estimate for gamma

+
+ +
+
+charging_sim.utils.build_electricity_cost(controller, load, energy_prices_TOU, demand_charge=False)[source]
+

Need to update from home load right now; maybe this can be useful in future opt.

+
+ +
+
+charging_sim.utils.build_objective(mode, electricity_cost, battery_degradation_cost, transformer_cost=0)[source]
+

Builds the objective function that we will minimize.

+
+ +
+
+charging_sim.utils.load_prices(time_intervals, price, price_vector)[source]
+
+ +
+
+

Module contents

+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/build/doctrees/batt_sys_identification.doctree b/docs/build/doctrees/batt_sys_identification.doctree new file mode 100644 index 000000000..f247b036e Binary files /dev/null and b/docs/build/doctrees/batt_sys_identification.doctree differ diff --git a/docs/build/doctrees/environment.pickle b/docs/build/doctrees/environment.pickle index de6b716f8..1563c979b 100644 Binary files a/docs/build/doctrees/environment.pickle and b/docs/build/doctrees/environment.pickle differ diff --git a/docs/build/doctrees/modules.doctree b/docs/build/doctrees/modules.doctree index deba12fb2..daa7757c2 100644 Binary files a/docs/build/doctrees/modules.doctree and b/docs/build/doctrees/modules.doctree differ diff --git a/docs/build/feeder_population.html b/docs/build/feeder_population.html new file mode 100644 index 000000000..8d10b693f --- /dev/null +++ b/docs/build/feeder_population.html @@ -0,0 +1,313 @@ + + + + + + + Feeder population — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +
+

Feeder population

+
+

Submodules

+
+
+

feeder_population.feeder_population module

+
+
+

feeder_population.glm_mod_functions module

+

Functions for modifying GridLAB-D power system simulation models

+
+
+feeder_population.glm_mod_functions.load_base_glm(base_file_dir, base_glm_file)[source]
+

Loads the glm as list and populates it into dict and returns the output

+
+
Parameters:
+
    +
  • base_file_dir

  • +
  • base_glm_file

  • +
+
+
Returns:
+

+
+
+
+ +
+
+feeder_population.glm_mod_functions.replace_load_w_meter(glm_dict, match_str, rep_str, obj_type)[source]
+

Replace all instances of load in glm_dict with meter.

+
+
Parameters:
+
    +
  • glm_dict

  • +
  • match_str

  • +
  • rep_str

  • +
  • obj_type

  • +
+
+
Returns:
+

+
+
+
+ +
+
+feeder_population.glm_mod_functions.replace_load_w_meter_old(glm_dict, match_str, rep_str, obj_type)[source]
+

Replace all instances of load in glm_dict with meter.

+
+
Parameters:
+
    +
  • glm_dict

  • +
  • match_str

  • +
  • rep_str

  • +
  • obj_type

  • +
+
+
Returns:
+

+
+
+
+ +
+
+feeder_population.glm_mod_functions.write_base_glm(glm_dict, obj_type, globals_list, include_list, out_dir, file_name, sync_list)[source]
+

Writes the glm file from the dict structure.

+
+
Parameters:
+
    +
  • glm_dict

  • +
  • obj_type

  • +
  • globals_list

  • +
  • include_list

  • +
  • out_dir

  • +
  • file_name

  • +
  • sync_list

  • +
+
+
Returns:
+

+
+
+
+ +
+
+feeder_population.glm_mod_functions.write_class_dict(file, gld_dict, class_name)[source]
+

Write dictionary corresponding to GLD class to .glm file.

+
+
Parameters:
+
    +
  • file

  • +
  • gld_dict

  • +
  • class_name

  • +
+
+
Returns:
+

+
+
+
+ +
+
+feeder_population.glm_mod_functions.write_clock_dict(file, gld_dict)[source]
+

Write dictionary corresponding to GLD clock to .glm file.

+
+
Parameters:
+
    +
  • file

  • +
  • gld_dict

  • +
+
+
Returns:
+

+
+
+
+ +
+
+feeder_population.glm_mod_functions.write_filter_dict(file, gld_dict, class_name)[source]
+

Write dictionary corresponding to GLD filter to .glm file.

+
+
Parameters:
+
    +
  • file

  • +
  • gld_dict

  • +
  • class_name

  • +
+
+
Returns:
+

+
+
+
+ +
+
+feeder_population.glm_mod_functions.write_mod_dict(file, gld_dict, mod_name)[source]
+

Write dictionary corresponding to GLD module to .glm file.

+
+
Parameters:
+
    +
  • file

  • +
  • gld_dict

  • +
  • mod_name

  • +
+
+
Returns:
+

+
+
+
+ +
+
+feeder_population.glm_mod_functions.write_obj_dict(file, gld_dict, dict_key, obj_type)[source]
+

Write dictionary corresponding to GLD objects to .glm file.

+
+
Parameters:
+
    +
  • file

  • +
  • gld_dict

  • +
  • dict_key

  • +
  • obj_type

  • +
+
+
Returns:
+

+
+
+
+ +
+
+

Module contents

+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/build/genindex.html b/docs/build/genindex.html new file mode 100644 index 000000000..dbf121627 --- /dev/null +++ b/docs/build/genindex.html @@ -0,0 +1,557 @@ + + + + + + Index — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ + +

Index

+ +
+ A + | B + | C + | D + | F + | G + | L + | M + | N + | O + | P + | R + | S + | T + | U + | W + +
+

A

+ + + +
    +
  • + analysis + +
  • +
  • + analysis.cost_analysis + +
  • +
+ +

B

+ + + +
+ +

C

+ + + +
+ +

D

+ + +
+ +

F

+ + + +
    +
  • + feeder_population + +
  • +
    +
  • + feeder_population.glm_mod_functions + +
  • +
+ +

G

+ + + +
+ +

L

+ + + +
+ +

M

+ + +
+ +

N

+ + + +
+ +

O

+ + +
+ +

P

+ + + +
+ +

R

+ + + +
+ +

S

+ + + +
+ +

T

+ + + +
    +
  • + test_cases + +
  • +
  • + test_cases.base_case + +
  • +
  • + test_cases.battery + +
  • +
+ +

U

+ + + +
+ +

W

+ + + +
+ + + +
+
+
+ +
+ +
+

© Copyright 2023, Emmanuel Balogun, Stanford University S3L Lab.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/build/html/_modules/batt_sys_identification/battery_identification.html b/docs/build/html/_modules/batt_sys_identification/battery_identification.html new file mode 100644 index 000000000..a7525c0a0 --- /dev/null +++ b/docs/build/html/_modules/batt_sys_identification/battery_identification.html @@ -0,0 +1,554 @@ + + + + + + batt_sys_identification.battery_identification — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for batt_sys_identification.battery_identification

+"""
+This module hosts the Battery System Identification class used for fitting battery ECM model parameters from data.
+"""
+
+import numpy as np
+import matplotlib.pyplot as plt
+import copy
+
+import pandas as pd
+import pygad
+import cvxpy as cp
+
+
+
+[docs] +class BatteryParams: + """ + Battery system identification class with open circuit voltage correction scheme. + This class takes in dataframe or csv with some given fields during instantiation.\n + + Dataframe fields (columns) must include the following literally and case-sensitive: + + * current - battery/cell current time-series. + * voltage - corresponding battery/cell voltage time-series. + * soc - corresponding battery/cell state of charge time-series. + * ocv - corresponding battery/cell open circuit voltage time-series. + + How to use: + + * data = pd.read_csv(data_path). This loads a pandas dataframe. + * module = BatteryParams(data) + * module.run_sys_identification() + * module.plot_correction_scheme_comparison() + + Writes new corrected open-circuit voltages and battery parameters to file within the folder. Can be downloaded via + the web-tool. + + :param data: Battery test data from which to fit the identification params. + """ + def __init__(self, data): + self.data = data + self.current = data.current.values + self.voltage = data.voltage.values + self.ocv = data.ocv.values + self.ocv_no_corr = data.ocv.values # Uncorrected open circuit voltage. + self.soc = data.soc.values + self.params = [] + self.params_uncorr = [] + self.init_params = [] # Can be initialized later. + self._default_population = [ + [1.058596e-02, 5.93096e-02, -4.17993e+00, 1.58777e-02, 9.75325e+03, 7.45710e-03, 4.01823e+03], + [3.43209856e-02, 1.74575496e-02, -4.29315177e+00, 2.01081488e-04, 9.56317565e+03, 2.12122173e-03, 9.57647155e+03], + [2.30552317e-02, 8.44786075e-02, -3.99474379e+00, 2.99153462e-03, 8.87442972e+03, 2.30526762e-03, 9.05492854e+03], + [-5.82959510e-03, 5.20569661e-02, -2.18763704e-01, 8.67466142e-04, 7.05178934e+03, 9.52035315e-03, 6.81286695e+03], + [5.72212881e-02, -1.43378662e-02, -6.12054235e-01, 4.80304568e-03, 5.45105883e+03, 4.74474171e-04, 7.31264565e+03], + [2.69767183e-03, 9.62504736e-02, -1.29365965e+00, 6.11142914e-03, 9.80086309e+03, 1.69531170e-03, 8.00324801e+03], + [1.16897734e-02, 4.54745088e-02, -3.28524770e+00, 1.35089385e-02, 5.69817778e+03, 3.98807635e-03, 8.31128396e+03], + [1.17640691e-02, 7.63076005e-02, -3.66411278e+00, 1.23863884e-02, 9.30697417e+03, 4.56975167e-04, 5.57718908e+03], + [1.93628327e-03, 5.21192971e-02, -1.96503048e+00, 1.77612540e-02, 5.47448933e+03, 6.42417508e-03, 8.05424318e+03], + [6.78756010e-03, 2.96217428e-02, -2.03289183e+00, 1.88927411e-02, 1.91748586e+03, 9.10005523e-03, 5.14585687e+03] + ] + + def _assert_data_len(self): + """ + Checks the imported data to ensure all fields have the same length. + + :return: None. + """ + assert self.voltage.shape[0] == self.soc.shape[0] + assert self.soc.shape[0] == self.current.shape[0] + assert self.soc.shape[0] == self.ocv.shape[0] + + def _cost_fun_pygad(self, ga_instance, x, idx): + """ + Provides the cost function used by PyGAD for parameter search. + + :param object ga_instance: Genetic Algorithm instance (pygad). + :param x: ndarray/vector of parameters $\theta$. + :param idx: default param used by ga_instance to run the problem + :return: Cost function, as described in EV-Ecosim paper. + """ + cost = 0 + V_data = self.voltage + data_len = V_data.shape[0] + A_Ro = x[0] + B_Ro = x[1] + C_Ro = x[2] + R1 = x[3] + C1 = x[4] + R2 = x[5] + C2 = x[6] + dt = 1 + + Ro = B_Ro * np.exp(C_Ro * self.soc) + A_Ro * np.exp(self.soc) # updated the new Ro based on intuition + I_t = -self.current # this will be loaded from .npy + + I_R1 = np.zeros((I_t.shape[0],)) + I_R2 = np.zeros((I_t.shape[0],)) + for j in range(1, len(I_R1)): + I_R1[j] = np.round(np.exp(-dt / (R1 * C1)) * I_R1[j - 1] + (1 - np.exp(-dt / (R1 * C1))) * I_t[j - 1], + 10) + I_R2[j] = np.round(np.exp(-dt / (R2 * C2)) * I_R2[j - 1] + (1 - np.exp(-dt / (R2 * C2))) * I_t[j - 1], + 10) + V_t = self.ocv - np.multiply(I_t, Ro) - np.multiply(I_R1, R1) - np.multiply(I_R2, R2) + assert V_t.shape == self.voltage.shape + cost += np.sum(np.square(V_t - V_data)) + cost = np.sqrt(cost / data_len) + if Ro.min() <= 0: + cost += 100 + if Ro[0] > Ro[-1]: + cost += 1 + return -10 * cost + + def _init_population(self): + """ + Initializes the PyGAD population. This is used to use a preset population as a warm-start. This helps the + parameter search to converge much quickly than starting from random genes within desired bounds. + + :return: + """ + print('Initializing population for warm-start...') + # f = open('init_pop.txt', 'r') + # initial_params = f.read() + # f.close() + # self.init_params = ast.literal_eval(initial_params) + self.init_params = self._default_population + print('Done initializing population.') + + @staticmethod + def _get_pygad_bounds(): + """ + Returns gene space range, representing the minimum and maximum values for each gene in the parameter vector. + + :return list gene_space_range: List of dicts providing the range for each gene. + """ + lb2 = [-0.1, -0.1, -5, 0.0001, 100, 0.0004, 4000] + ub2 = [0.1, 0.1, 0, 0.02, 10000, 0.01, 10000] + + lb3 = [-10, -10, -10, 0.00004, 0.03, 0.0004, 600] # change the range for testing capacitance variation with SOC if any + ub3 = [10, 10, 10, 0.01, 0.06, 0.01, 10000] + + lb = [0.02, 0.0001, 100, 0.00004, 900] + ub = [0.04, 0.01, 10000, 0.004, 10000] + gene_space_range = [{'low': low, 'high': high} for low, high in zip(lb2, ub2)] + return gene_space_range + +
+[docs] + def ga(self, num_generations=100, num_parents_mating=2, sol_per_pop=10, num_genes=7, crossover_type="single_point", + mutation_type="adaptive", parent_selection_type="sss", mutation_percent_genes=60, + mutation_prob=(0.3, 0.1), crossover_prob=None): + """ + Runs the genetic algorithm instance. Please see PyGAD official documentation for more explanation of + fields/params. + The default parameters have been selected to optimize accuracy and speed, however, any user may find a + combination of params that work better for a given set of battery data. + + :param crossover_prob: + :param num_generations: Number of generations. Default is 100. + :param num_parents_mating: Number of parents to combine to form the next offspring. Default is 2. + :param sol_per_pop: Number of solutions per population (a set of genes is one solution), or offspring size. + :param num_genes: Equivalent to the number of parameters being searched + :param crossover_type: Describes how the cross-over between mating genes is done. + :param mutation_type: Describes gene mutation. Default adaptive + :param parent_selection_type: Parent selection scheme for the next population. + :param mutation_percent_genes: The percentage of genes that undergo mutation. + :param mutation_prob: The probability of selecting a gene for applying the mutation operation. + Its value must be between 0.0 and 1.0 inclusive. + :return: Solution vector of optimized parameters. + """ + gene_space_range = self._get_pygad_bounds() # Get the gene space range. + if self.init_params: + ga_instance = pygad.GA(num_generations=num_generations, + initial_population=self.init_params, + num_parents_mating=num_parents_mating, + fitness_func=self._cost_fun_pygad, + sol_per_pop=sol_per_pop, + num_genes=num_genes, + mutation_type=mutation_type, + mutation_probability=mutation_prob, + mutation_percent_genes=mutation_percent_genes, + parent_selection_type=parent_selection_type, + crossover_type=crossover_type, + allow_duplicate_genes=False, + crossover_probability=crossover_prob, + stop_criteria=["reach_0.05", "saturate_20"], + gene_space=gene_space_range, + parallel_processing=8) + else: + ga_instance = pygad.GA(num_generations=num_generations, + num_parents_mating=num_parents_mating, + fitness_func=self._cost_fun_pygad, + sol_per_pop=sol_per_pop, + num_genes=num_genes, + mutation_type=mutation_type, + mutation_probability=mutation_prob, + mutation_percent_genes=mutation_percent_genes, + parent_selection_type=parent_selection_type, + crossover_type=crossover_type, + allow_duplicate_genes=False, + crossover_probability=crossover_prob, + stop_criteria=["reach_0.05", "saturate_20"], + gene_space=gene_space_range, + parallel_processing=8) + + ga_instance.run() + solution, solution_fitness, solution_idx = ga_instance.best_solution() + ga_instance.plot_fitness() + print(f'Parameters of the best solution : {solution}') + print(f"Fitness value of the best solution = {solution_fitness}") + return solution
+ + +
+[docs] + def run_sys_identification(self, cell_name=0, diagn=0, use_initial_pop=True, quadratic_bias=True): + """ + Runs the GA for system identification. + + :return: + """ + if use_initial_pop: + self._init_population() + self.params = self.ga() + + if quadratic_bias: + self.run_ocv_correction(use_quadratic=True) + else: + self.run_ocv_correction() # Uses simple linear bias correction. + # Run again. + self.params = self.ga() # New params. + np.savetxt(f'battery_params_{cell_name}_{diagn}.csv', self.params, delimiter=',')
+ + +
+[docs] + def run_ocv_correction(self, use_quadratic=False, cell_name=0, diagn=0): + """ + Fits the parameters for the open circuit voltage correction scheme. Updates the ocv attribute. The open circuit + voltage correction scheme can be quadratic or linear. The quadratic scheme was used in the original paper. + + :return: None. + """ + self._validate_params() + self.params_uncorr = copy.copy(self.params) + x = self.params + V_data = self.voltage + A_Ro = x[0] + B_Ro = x[1] + C_Ro = x[2] + R1 = x[3] + C1 = x[4] + R2 = x[5] + C2 = x[6] + dt = 1 + + Ro = B_Ro * np.exp(C_Ro * self.soc) + A_Ro * np.exp(self.soc) # updated the new Ro based on intuition + I_t = -self.current # this will be loaded from .npy + I_R1 = np.zeros((I_t.shape[0],)) + I_R2 = np.zeros((I_t.shape[0],)) + + for j in range(1, len(I_R1)): + I_R1[j] = np.round(np.exp(-dt / (R1 * C1)) * I_R1[j - 1] + (1 - np.exp(-dt / (R1 * C1))) * I_t[j - 1], 10) + I_R2[j] = np.round(np.exp(-dt / (R2 * C2)) * I_R2[j - 1] + (1 - np.exp(-dt / (R2 * C2))) * I_t[j - 1], 10) + V_t = self.ocv - np.multiply(I_t, Ro) - np.multiply(I_R1, R1) - np.multiply(I_R2, R2) + beta = cp.Variable(1) + const_bias = cp.Variable(1) + + if use_quadratic: + ocv_corr = self.ocv**2 * beta + const_bias # work on improving the representation of this ocv correction term + else: + ocv_corr = self.ocv * beta + const_bias + V_t2 = ocv_corr - np.multiply(I_t, Ro) - np.multiply(I_R1, R1) - np.multiply(I_R2, R2) + obj = cp.Minimize(cp.sum(cp.abs(V_t2 - V_data))) + problem = cp.Problem(obj) + problem.solve(solver=cp.ECOS, verbose=False) + print("OCV correction beta: ", beta.value) + print("OCV correction const. bias: ", const_bias.value) + ocv_bias_correction_vector = np.array([beta.value, const_bias.value]) + np.savetxt('OCV_bias_correction_params_{}_{}.csv'.format(cell_name, diagn), ocv_bias_correction_vector) + self.ocv = ocv_corr.value + self.data['ocv_corr'] = self.ocv + self.data.to_csv('input_data_with_ocv_corr_voltage.csv') # adds corrected ocv as field and writes the input data
+ + + def _validate_params(self): + """ + Internal method. + Validates that the parameter list has been updated, will throw an exception if list is not updated. + + :raise : Assertion error if not validated. + :return: None. + """ + assert len(self.params) > 0 + +
+[docs] + def plot_correction_scheme_comparison(self, xlim=(20000, 36000), ylim=(2.75, 3.85)): + """ + Generates a plot of OCV corrected model and non-OCV corrected model. + + :return: None + """ + v_corr = self.get_corrected_voltages() + v_uncorr = self.get_uncorrected_voltages() + plt.figure() + plt.plot(self.voltage, label='experimental data') + plt.plot(v_uncorr, '--', label='ECM without OCV correction') + plt.plot(v_corr, '--', label='ECM with OCV correction', color='k') + # plt.xlim(xlim) + # plt.ylim(ylim) + plt.xticks(rotation=45) + plt.xlabel("Time Step (s)") + plt.ylabel("Voltage") + plt.legend() + plt.tight_layout() + plt.savefig('model_comparison_ocv_correction_scheme.png')
+ + +
+[docs] + def get_uncorrected_voltages(self): + """ + Returns the vector of uncorrected voltages from ECM model response. + + :return: Vector of uncorrected voltages. + """ + A_Ro = self.params_uncorr[0] + B_Ro = self.params_uncorr[1] + C_Ro = self.params_uncorr[2] + R1 = self.params_uncorr[3] + C1 = self.params_uncorr[4] + R2 = self.params_uncorr[5] + C2 = self.params_uncorr[6] + dt = 1 + Ro = B_Ro * np.exp(C_Ro * self.soc) + A_Ro * np.exp(self.soc) # updated the new Ro based on intuition + I_t = -self.current # this will be loaded from .npy + I_R1 = np.zeros((I_t.shape[0],)) + I_R2 = np.zeros((I_t.shape[0],)) + + for j in range(1, len(I_R1)): + I_R1[j] = np.round(np.exp(-dt / (R1 * C1)) * I_R1[j - 1] + (1 - np.exp(-dt / (R1 * C1))) * I_t[j - 1], 10) + I_R2[j] = np.round(np.exp(-dt / (R2 * C2)) * I_R2[j - 1] + (1 - np.exp(-dt / (R2 * C2))) * I_t[j - 1], 10) + V_t = self.ocv_no_corr - np.multiply(I_t, Ro) - np.multiply(I_R1, R1) - np.multiply(I_R2, R2) + return V_t
+ + +
+[docs] + def get_corrected_voltages(self): + """ + Returns the voltage response with corrected open circuit voltage. + + :return: Vector of voltage response with corrected open circuit voltage. + """ + A_Ro = self.params[0] + B_Ro = self.params[1] + C_Ro = self.params[2] + R1 = self.params[3] + C1 = self.params[4] + R2 = self.params[5] + C2 = self.params[6] + dt = 1 + + Ro = B_Ro * np.exp(C_Ro * self.soc) + A_Ro * np.exp(self.soc) # updated the new Ro based on intuition + I_t = -self.current # this will be loaded from .npy + I_R1 = np.zeros((I_t.shape[0],)) + I_R2 = np.zeros((I_t.shape[0],)) + + for j in range(1, len(I_R1)): + I_R1[j] = np.round(np.exp(-dt / (R1 * C1)) * I_R1[j - 1] + (1 - np.exp(-dt / (R1 * C1))) * I_t[j - 1], 10) + I_R2[j] = np.round(np.exp(-dt / (R2 * C2)) * I_R2[j - 1] + (1 - np.exp(-dt / (R2 * C2))) * I_t[j - 1], 10) + V_t = self.ocv - np.multiply(I_t, Ro) - np.multiply(I_R1, R1) - np.multiply(I_R2, R2) + return V_t
+ + +
+[docs] + def get_Ro(self): + """ + Returns the high frequency (Ro) resistance of the battery. + + :return: Resistance (R_o). + """ + A_Ro = self.params[0] + B_Ro = self.params[1] + C_Ro = self.params[2] + return B_Ro * np.exp(C_Ro * self.soc) + A_Ro * np.exp(self.soc)
+ + +
+[docs] + def plot_Ro(self): + """ + Plots the high frequency resistance (Ro) of the battery. + + :return: None. + """ + Ro = self.get_Ro() + self.params[3] + self.params[5] + fig, ax = plt.subplots(1, 1) + ax.plot(self.soc, Ro) + plt.title("Ro vs. SoC plot") + plt.xlabel('State of charge') + plt.ylabel('Ro (Resistance)') + plt.show()
+ + +
+[docs] + def simulate_response(self): + """ + Simulates the response of the ECM model. Not complete yet. + + :return: + """ + voltage = self.get_uncorrected_voltages()
+ + # todo: complete later + +
+[docs] + def run_pre_checks(self): + """ + Runs pre-checks on input values to ensure they are all of desired lengths. This is run at the beginning to + ensure no errors in data length. + + :return: None. + """ + self._assert_data_len()
+ + + def _estimate_soc_vector(self): + """ + Estimates the SOC vector for users that do not have the vector but have the capacity and + current profiles. Not fully implemented yet. + + :return: Error message. + """ + return NotImplementedError("Method has not been implemented yet!")
+ + + +if __name__ == '__main__': + import os + # List all the csv files in current directory and let user choose one. + # User uploaded data will be saved in the current directory as a temp_data.csv file. + data_path = os.path.join(os.getcwd(), 'temp_data.csv') + batt_data = pd.read_csv(data_path) + module = BatteryParams(batt_data) + # Create button option to toggle initial population on or off. + module.run_sys_identification(use_initial_pop=True) + module.plot_correction_scheme_comparison() +
+ +
+
+
+ +
+ +
+

© Copyright 2023, Emmanuel Balogun, Stanford University S3L Lab.

+
+ + Built with Sphinx using a + theme + provided by Read the Docs. + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/build/html/_modules/index.html b/docs/build/html/_modules/index.html index 4f4da7391..e6bfc2bdf 100644 --- a/docs/build/html/_modules/index.html +++ b/docs/build/html/_modules/index.html @@ -70,6 +70,7 @@

All modules for which code is available

  • analysis.cost_analysis
  • +
  • batt_sys_identification.battery_identification
  • charging_sim.battery
  • charging_sim.batteryAgingSim
  • charging_sim.batterypack
  • diff --git a/docs/build/html/_sources/batt_sys_identification.rst.txt b/docs/build/html/_sources/batt_sys_identification.rst.txt new file mode 100644 index 000000000..7f758d41c --- /dev/null +++ b/docs/build/html/_sources/batt_sys_identification.rst.txt @@ -0,0 +1,12 @@ +Battery System Identification +================ + +Submodules +---------- + +Battery system identification +------------------------------ +.. automodule:: batt_sys_identification.battery_identification + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/build/html/_sources/modules.rst.txt b/docs/build/html/_sources/modules.rst.txt index a328dd802..d1aadf509 100644 --- a/docs/build/html/_sources/modules.rst.txt +++ b/docs/build/html/_sources/modules.rst.txt @@ -3,9 +3,11 @@ Packages .. toctree:: :maxdepth: 4 - analysis - charging_sim feeder_population + batt_sys_identification + charging_sim test_cases + analysis + diff --git a/docs/build/html/analysis.html b/docs/build/html/analysis.html index 2d6b316da..f634ae3c1 100644 --- a/docs/build/html/analysis.html +++ b/docs/build/html/analysis.html @@ -19,8 +19,7 @@ - - + @@ -46,6 +45,10 @@
    • Readme
    • Packages @@ -267,8 +267,7 @@

      plot_results module - - +
      diff --git a/docs/build/html/batt_sys_identification.html b/docs/build/html/batt_sys_identification.html new file mode 100644 index 000000000..2d0412fd8 --- /dev/null +++ b/docs/build/html/batt_sys_identification.html @@ -0,0 +1,268 @@ + + + + + + + Battery System Identification — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + +
      + + +
      + +
      +
      +
      +
        +
      • + +
      • +
      • +
      +
      +
      +
      +
      + +
      +

      Battery System Identification

      +
      +

      Submodules

      +
      +
      +

      Battery system identification

      +

      This module hosts the Battery System Identification class used for fitting battery ECM model parameters from data.

      +
      +
      +class batt_sys_identification.battery_identification.BatteryParams(data)[source]
      +

      Bases: object

      +

      Battery system identification class with open circuit voltage correction scheme. +This class takes in dataframe or csv with some given fields during instantiation.

      +

      Dataframe fields (columns) must include the following literally and case-sensitive:

      +
        +
      • current - battery/cell current time-series.

      • +
      • voltage - corresponding battery/cell voltage time-series.

      • +
      • soc - corresponding battery/cell state of charge time-series.

      • +
      • ocv - corresponding battery/cell open circuit voltage time-series.

      • +
      +

      How to use:

      +
        +
      • data = pd.read_csv(data_path). This loads a pandas dataframe.

      • +
      • module = BatteryParams(data)

      • +
      • module.run_sys_identification()

      • +
      • module.plot_correction_scheme_comparison()

      • +
      +

      Writes new corrected open-circuit voltages and battery parameters to file within the folder. Can be downloaded via +the web-tool.

      +
      +
      Parameters:
      +

      data – Battery test data from which to fit the identification params.

      +
      +
      +
      +
      +ga(num_generations=100, num_parents_mating=2, sol_per_pop=10, num_genes=7, crossover_type='single_point', mutation_type='adaptive', parent_selection_type='sss', mutation_percent_genes=60, mutation_prob=(0.3, 0.1), crossover_prob=None)[source]
      +

      Runs the genetic algorithm instance. Please see PyGAD official documentation for more explanation of +fields/params. +The default parameters have been selected to optimize accuracy and speed, however, any user may find a +combination of params that work better for a given set of battery data.

      +
      +
      Parameters:
      +
        +
      • crossover_prob

      • +
      • num_generations – Number of generations. Default is 100.

      • +
      • num_parents_mating – Number of parents to combine to form the next offspring. Default is 2.

      • +
      • sol_per_pop – Number of solutions per population (a set of genes is one solution), or offspring size.

      • +
      • num_genes – Equivalent to the number of parameters being searched

      • +
      • crossover_type – Describes how the cross-over between mating genes is done.

      • +
      • mutation_type – Describes gene mutation. Default adaptive

      • +
      • parent_selection_type – Parent selection scheme for the next population.

      • +
      • mutation_percent_genes – The percentage of genes that undergo mutation.

      • +
      • mutation_prob – The probability of selecting a gene for applying the mutation operation.

      • +
      +
      +
      +

      Its value must be between 0.0 and 1.0 inclusive. +:return: Solution vector of optimized parameters.

      +
      + +
      +
      +get_Ro()[source]
      +

      Returns the high frequency (Ro) resistance of the battery.

      +
      +
      Returns:
      +

      Resistance (R_o).

      +
      +
      +
      + +
      +
      +get_corrected_voltages()[source]
      +

      Returns the voltage response with corrected open circuit voltage.

      +
      +
      Returns:
      +

      Vector of voltage response with corrected open circuit voltage.

      +
      +
      +
      + +
      +
      +get_uncorrected_voltages()[source]
      +

      Returns the vector of uncorrected voltages from ECM model response.

      +
      +
      Returns:
      +

      Vector of uncorrected voltages.

      +
      +
      +
      + +
      +
      +plot_Ro()[source]
      +

      Plots the high frequency resistance (Ro) of the battery.

      +
      +
      Returns:
      +

      None.

      +
      +
      +
      + +
      +
      +plot_correction_scheme_comparison(xlim=(20000, 36000), ylim=(2.75, 3.85))[source]
      +

      Generates a plot of OCV corrected model and non-OCV corrected model.

      +
      +
      Returns:
      +

      None

      +
      +
      +
      + +
      +
      +run_ocv_correction(use_quadratic=False, cell_name=0, diagn=0)[source]
      +

      Fits the parameters for the open circuit voltage correction scheme. Updates the ocv attribute. The open circuit +voltage correction scheme can be quadratic or linear. The quadratic scheme was used in the original paper.

      +
      +
      Returns:
      +

      None.

      +
      +
      +
      + +
      +
      +run_pre_checks()[source]
      +

      Runs pre-checks on input values to ensure they are all of desired lengths. This is run at the beginning to +ensure no errors in data length.

      +
      +
      Returns:
      +

      None.

      +
      +
      +
      + +
      +
      +run_sys_identification(cell_name=0, diagn=0, use_initial_pop=True, quadratic_bias=True)[source]
      +

      Runs the GA for system identification.

      +
      +
      Returns:
      +

      +
      +
      +
      + +
      +
      +simulate_response()[source]
      +

      Simulates the response of the ECM model. Not complete yet.

      +
      +
      Returns:
      +

      +
      +
      +
      + +
      + +
      +
      + + +
      +
      +
      + +
      + +
      +

      © Copyright 2023, Emmanuel Balogun, Stanford University S3L Lab.

      +
      + + Built with Sphinx using a + theme + provided by Read the Docs. + + +
      +
      +
      +
      +
      + + + + \ No newline at end of file diff --git a/docs/build/html/charging_sim.html b/docs/build/html/charging_sim.html index 5b2ec363b..b411a2d4c 100644 --- a/docs/build/html/charging_sim.html +++ b/docs/build/html/charging_sim.html @@ -20,8 +20,8 @@ - - + + @@ -47,7 +47,8 @@
      • Readme
      • Packages @@ -1816,8 +1817,8 @@

        charging_sim.batterytest module - - + +
        diff --git a/docs/build/html/feeder_population.html b/docs/build/html/feeder_population.html index 8d10b693f..775028d21 100644 --- a/docs/build/html/feeder_population.html +++ b/docs/build/html/feeder_population.html @@ -19,8 +19,8 @@ - - + + @@ -46,8 +46,6 @@ @@ -283,8 +284,8 @@

        feeder_population.feeder_population module - - + +
        diff --git a/docs/build/html/genindex.html b/docs/build/html/genindex.html index de401b37d..544e2b382 100644 --- a/docs/build/html/genindex.html +++ b/docs/build/html/genindex.html @@ -124,6 +124,13 @@

        A

        B

        + + + + + + + + + id="toggle-3" style="display: none" alt="-" /> - + - + - + - + - + - + - + - + - + - + - + - + + id="toggle-4" style="display: none" alt="-" /> - + + id="toggle-5" style="display: none" alt="-" /> - + - + - + - +
        diff --git a/docs/build/html/modules.html b/docs/build/html/modules.html index 8758b520e..5e21ad2a7 100644 --- a/docs/build/html/modules.html +++ b/docs/build/html/modules.html @@ -19,7 +19,7 @@ - + @@ -46,10 +46,11 @@ @@ -81,26 +82,42 @@

        Packages

        @@ -367,7 +388,7 @@

        Packages

        diff --git a/docs/build/html/objects.inv b/docs/build/html/objects.inv index 5ff93a962..a9b582d85 100644 Binary files a/docs/build/html/objects.inv and b/docs/build/html/objects.inv differ diff --git a/docs/build/html/py-modindex.html b/docs/build/html/py-modindex.html index 2be0c6685..d75f674f1 100644 --- a/docs/build/html/py-modindex.html +++ b/docs/build/html/py-modindex.html @@ -76,6 +76,7 @@

        Python Module Index

        a | + b | c | f | t @@ -97,70 +98,84 @@

        Python Module Index

        analysis.cost_analysis

         
        + b
        + batt_sys_identification +
            + batt_sys_identification.battery_identification +
         
        c
        charging_sim
            charging_sim.battery
            charging_sim.batteryAgingSim
            charging_sim.batterypack
            charging_sim.capacitor
            charging_sim.chargingStation
            charging_sim.controller
            charging_sim.electricityPrices
            charging_sim.optimization
            charging_sim.orchestrator
            charging_sim.simulate
            charging_sim.solar
            charging_sim.utils @@ -170,11 +185,11 @@

        Python Module Index

        f
        feeder_population
            feeder_population.glm_mod_functions @@ -184,26 +199,26 @@

        Python Module Index

        t
        test_cases
            test_cases.base_case
            test_cases.battery
            test_cases.battery.feeder_population
            test_cases.battery.feeder_population.glm_mod_functions diff --git a/docs/build/html/searchindex.js b/docs/build/html/searchindex.js index 778bbff0e..77fd1826d 100644 --- a/docs/build/html/searchindex.js +++ b/docs/build/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({"docnames": ["README", "analysis", "charging_sim", "feeder_population", "index", "modules", "readme", "test_cases", "test_cases.base_case", "test_cases.battery", "test_cases.battery.feeder_population"], "filenames": ["README.md", "analysis.rst", "charging_sim.rst", "feeder_population.rst", "index.rst", "modules.rst", "readme.rst", "test_cases.rst", "test_cases.base_case.rst", "test_cases.battery.rst", "test_cases.battery.feeder_population.rst"], "titles": ["EV-Ecosim platform", "Post-simulation analysis", "Charging simulator", "Feeder population", "Welcome to EV-Ecosim 1.0.0", "Packages", "Readme", "Test cases", "test_cases.base_case package", "test_cases.battery package", "test_cases.battery.feeder_population package"], "terms": {"A": [0, 1, 2], "grid": [0, 1, 2, 4], "awar": [0, 4], "design": [0, 2], "vehicl": [0, 2], "paper": [0, 2], "http": [0, 1, 2], "doi": [0, 2], "org": [0, 2], "10": [0, 2], "36227": [0, 2], "techrxiv": [0, 2], "23596725": [0, 2], "v2": [0, 2], "emmanuel": 0, "balogun": [0, 2], "ebalogun": 0, "stanford": 0, "edu": 0, "lili": 0, "buechler": 0, "ebuech": 0, "gismo": 0, "slac": 0, "gridlab": [0, 3, 4, 10], "d": [0, 3, 4, 10], "instal": [0, 2], "master": 0, "branch": 0, "github": [0, 4], "com": [0, 2], "arra": 0, "energi": [0, 2], "gridlabd": 0, "version": [0, 2, 4], "python": [0, 4], "recommend": 0, "aw": 0, "ec2": 0, "hipa": 0, "ami": 0, "beauharnoi": 0, "x": 0, "ambient": [0, 2], "_": 0, "data": [0, 1, 2], "temperatur": [0, 2], "captur": 0, "effect": [0, 2], "environment": 0, "condit": 0, "subsystem": 0, "transform": [0, 1, 2], "base": [0, 1, 2, 4, 10], "load": [0, 1, 2, 3, 10], "includ": [0, 1, 2, 4], "exist": [0, 2], "build": [0, 1, 2], "home": [0, 2], "usual": [0, 2], "uncontrol": 0, "within": [0, 1, 2], "distribut": [0, 1, 2, 4], "work": [0, 2], "proprietari": 0, "pecan": 0, "street": 0, "below": 0, "an": [0, 2], "exmapl": 0, "prototyp": 0, "note": [0, 2], "column": 0, "field": 0, "ar": [0, 1, 2], "sensit": 0, "The": [0, 1, 2, 4], "origin": 0, "ha": [0, 2], "minut": [0, 2], "resolut": [0, 2], "power": [0, 1, 2, 3, 4, 10], "system": [0, 1, 2, 3, 4, 10], "batt": [0, 2], "sy": 0, "identif": [0, 2], "class": [0, 1, 2, 3, 10], "gener": [0, 2], "paramet": [0, 1, 2, 3, 10], "from": [0, 1, 2, 3], "experiment": 0, "leverag": 0, "genet": 0, "algorithm": 0, "model": [0, 2, 3, 4, 10], "2nd": 0, "order": 0, "rc": 0, "equival": 0, "circuit": [0, 2], "ecm": 0, "One": 0, "can": [0, 1, 2], "custom": 0, "nmc": [0, 2], "upload": 0, "csv": [0, 2], "file": [0, 1, 2, 3, 10], "param": [0, 2], "shown": [0, 4], "save": [0, 1, 2], "new": [0, 2], "addit": 0, "correct": [0, 2], "open": [0, 2], "voltag": [0, 1, 2], "ocv": [0, 2], "valu": [0, 1, 2], "label": [0, 1], "ocv_corr": 0, "abov": 0, "onc": [0, 2], "thei": 0, "battery_data": 0, "config": [0, 2, 5], "json": [0, 2], "modifi": [0, 2, 3, 10], "so": [0, 2], "sim": [0, 2, 5, 7], "contain": [0, 1, 2, 4, 10], "which": [0, 1, 2], "configur": [0, 2], "all": [0, 1, 2, 3], "relev": [0, 2], "implement": [0, 1, 2], "physic": [0, 2], "legaci": 0, "forecast": [0, 2], "develop": [0, 4], "need": [0, 2], "elec": 0, "rate": [0, 2], "time": [0, 2], "tou": [0, 2], "input": [0, 2], "user": [0, 2], "must": [0, 2], "normal": [0, 1], "full": [0, 2], "year": [0, 2], "size": 0, "365": 0, "dai": [0, 1, 2], "avoid": 0, "ani": [0, 2], "error": 0, "format": 0, "read": 0, "sampl": [0, 2], "dure": [0, 2], "should": [0, 2], "one": [0, 2], "15": [0, 2], "also": [0, 1, 2], "help": [0, 2], "downscal": [0, 2, 5], "much": [0, 2], "coarser": 0, "librari": [0, 2], "ieee": [0, 1], "test": [0, 2, 4, 5], "pnnl": 0, "taxonomi": 0, "glm": [0, 3, 10], "have": [0, 2, 4], "spot": 0, "specifi": [0, 2], "primari": 0, "level": [0, 1, 2], "secondari": [0, 2], "popul": [0, 4, 5], "script": 0, "vari": 0, "resourc": [0, 1], "necessari": 0, "txt": [0, 2], "residenti": 0, "repo": 0, "limit": [0, 2], "access": [0, 2, 4], "irradi": [0, 2], "overal": [0, 1, 2], "default": [0, 2], "nation": 0, "radiat": 0, "databas": 0, "nsrdb": 0, "san": 0, "francisco": 0, "bai": 0, "area": [0, 2], "renew": 0, "laboratori": 0, "nrel": [0, 1], "month": [0, 2], "index": [0, 2, 4], "1": [0, 2], "12": [0, 1, 2], "inclus": 0, "januari": 0, "decemb": [0, 2], "hourli": 0, "interv": 0, "oversampl": 0, "4": 0, "dataset": [0, 2], "ghi": [0, 2], "repres": 0, "global": [0, 2], "horizont": [0, 2], "w": 0, "m": 0, "2": 0, "total": [0, 2], "amount": [0, 1], "shortwav": 0, "receiv": 0, "surfac": [0, 2], "ground": 0, "base_cas": [0, 5, 7], "write": [0, 3, 10], "inject": [0, 2], "each": [0, 1, 2], "timestep": 0, "rlsf": 0, "plu": 0, "recurs": 0, "least": [0, 2], "squar": 0, "filter": [0, 3, 10], "estim": [0, 1, 2, 4], "network": [0, 1, 2, 4], "onlin": 0, "thermal": [0, 2], "integr": [0, 4], "plot": [0, 1, 2], "result": [0, 1, 2], "calcul": [0, 1, 2], "impact": [0, 4], "plot_result": [0, 5], "pars": 0, "percentag": 0, "violat": [0, 1], "per": [0, 2], "ansi": 0, "c84": 0, "variabl": [0, 2], "string": [0, 2], "path": [0, 2], "where": [0, 2], "powerflow": 0, "output": [0, 2, 3], "node": [0, 1, 2], "load_post_opt_cost": [0, 5], "tabl": 0, "matric": 0, "respect": [0, 2], "cost_analysi": [0, 5], "costestim": [0, 1, 5], "differ": [0, 1, 2], "compon": [0, 1], "creat": [0, 1, 2], "environ": 0, "conda": 0, "env": 0, "name": [0, 2], "your": [0, 2], "f": [0, 2], "yml": 0, "OR": 0, "packag": [0, 4, 7], "list": [0, 1, 2, 3], "manual": 0, "ensur": [0, 2], "follow": [0, 2], "method": [0, 2], "For": 0, "navig": 0, "set": [0, 2], "prepar": 0, "confirm": 0, "successfulli": 0, "ieee123_secondari": 0, "ieee123_popul": 0, "you": 0, "done": [0, 2], "initi": [0, 2], "pre": [0, 2], "prep": 0, "now": [0, 2], "out": [0, 2], "scenario": [0, 1, 2, 5, 7], "python3": 0, "ev50_cosimul": 0, "master_sim": [0, 5, 7], "pleas": 0, "see": 0, "section": 0, "more": [0, 2], "detail": 0, "thi": [1, 2, 4], "cost": [1, 2], "der": [1, 2], "simul": [3, 4, 5, 10], "num_dai": 1, "sourc": [1, 2, 3, 10], "object": [1, 2, 3, 10], "i": [1, 2, 4], "us": [1, 2, 4], "asset": [1, 2], "ev": [1, 2], "ecosim": [1, 2], "number": [1, 2], "run": [1, 2, 4, 5], "calculate_battery_cost": [1, 5], "result_dir": 1, "batteri": [1, 4, 5, 7], "updat": [1, 2], "lcoe": 1, "directori": 1, "dictionari": [1, 2, 3, 10], "return": [1, 2, 3, 10], "dict": [1, 2, 3], "result_dict": 1, "calculate_electricity_cost_pgebev2": [1, 5], "pge_separate_fil": 1, "true": [1, 2], "electr": [1, 2], "pgebev2": 1, "given": [1, 2], "str": [1, 2], "compris": 1, "dollar": 1, "calculate_solar_cost": [1, 5], "pull": [1, 2], "solar": [1, 4, 5], "ref": [1, 2], "www": [1, 2], "gov": 1, "market": 1, "research": 1, "html": 1, "To": 1, "deprec": [1, 2], "soon": 1, "none": [1, 2], "calculate_trans_loss_of_lif": [1, 5], "expect": 1, "loss": [1, 2], "life": [1, 2], "refer": 1, "5": 1, "11": 1, "3": [1, 4], "std": 1, "c57": 1, "00": 1, "2010": 1, "minimum": [1, 2], "insul": 1, "180": 1, "000": 1, "hour": [1, 2], "static": [1, 2], "plot_load": [1, 5], "total_load": 1, "net_load": 1, "prefix": [1, 2], "overlai": 1, "net": [1, 2], "post": [2, 4, 5], "visual": [1, 2, 5], "demand": [1, 2], "control": [1, 5], "minu": 1, "buffer": 1, "legend": 1, "curv": 1, "plot_pow": [1, 5], "power_pr": 1, "predict": [1, 2], "plot_soc": [1, 5], "soc": [1, 2], "soc_pr": 1, "state": [1, 2], "charg": [1, 4, 5], "solar_cost": [1, 5], "capit": 1, "Not": [1, 2], "fulli": [1, 2], "locat": [1, 2], "pv": [1, 2], "transformer_cost": [1, 2, 5], "cannot": [1, 2], "find": [1, 2], "good": 1, "yet": [1, 2], "ag": [1, 2], "battery_typ": [2, 5], "instanti": 2, "constraint": 2, "properti": 2, "mainli": 2, "max": 2, "c": 2, "determin": 2, "capac": 2, "cell": 2, "multipl": 2, "v": 2, "maximum": 2, "allow": 2, "min": 2, "nomin": 2, "kwh": 2, "deliver": 2, "id": 2, "celsiu": 2, "type": 2, "inconsequenti": 2, "current": 2, "dynam": [2, 5], "bu": 2, "resid": 2, "self": 2, "main": [2, 5], "attribut": 2, "battery_setup": [2, 5], "up": 2, "seri": 2, "parallel": 2, "scale": 2, "ah": 2, "setup": [2, 5], "fix": 2, "while": 2, "float": 2, "pack": 2, "wh": 2, "topologi": 2, "battery_setup_2": [2, 5], "instead": 2, "therebi": 2, "same": 2, "pack_max_ah": 2, "watt": 2, "amp": 2, "cell_amp_hr": 2, "cell_voltag": 2, "propag": 2, "forward": 2, "step": [2, 5], "It": [2, 4], "take": 2, "amper": 2, "np": 2, "cycl": 2, "respons": 2, "est_calendar_ag": [2, 5], "constant": 2, "calendar": 2, "sole": 2, "depend": 2, "later": 2, "linear": 2, "est_cyc_ag": [2, 5], "hess": 2, "et": 2, "al": 2, "its": 2, "cvx": 2, "cvxpy": 2, "describ": 2, "function": [2, 3, 10], "get_ocv": [2, 5], "map": 2, "store": 2, "via": [2, 4], "interpol": 2, "obtain": 2, "priori": 2, "": 2, "get_ro": [2, 5], "possibli": 2, "get_aging_valu": [2, 5], "experienc": 2, "far": 2, "get_power_profil": [2, 5], "profil": 2, "certain": 2, "get_properti": [2, 5], "get_roundtrip_effici": [2, 5], "get_total_ag": [2, 5], "get_true_pow": [2, 5], "save_sim_data": [2, 5], "save_prefix": 2, "over": 2, "call": 2, "upon": 2, "conclus": 2, "desir": 2, "folder": 2, "save_st": [2, 5], "state_eqn": [2, 5], "append": 2, "discret": 2, "equat": 2, "here": 2, "g": 2, "l": 2, "plett": 2, "manag": 2, "volum": 2, "artech": 2, "hous": 2, "2015": 2, "vol": 2, "boolean": 2, "decid": 2, "track": 2, "b": 2, "analys": 2, "histori": 2, "vector": 2, "thermal_dynam": [2, 5], "futur": 2, "track_soc": [2, 5], "update_soc": [2, 5], "update_capac": [2, 5], "anticip": 2, "update_max_curr": [2, 5], "verbos": 2, "fals": 2, "update_param": [2, 5], "chang": 2, "update_voltag": [2, 5], "option": 2, "batteryag": [2, 5], "enact": 2, "resist": 2, "datetim": 2, "num_step": 2, "re": 2, "linimncoo2": 2, "ad": 2, "link": [2, 4], "sciencedirect": 2, "scienc": 2, "articl": 2, "pii": 2, "s0378775314001876": 2, "beta_cap": 2, "fade": 2, "factor": 2, "alpha_cap": 2, "beta_r": 2, "growth": 2, "alpha_r": 2, "assumpt": 2, "homogen": 2, "uniform": 2, "across": 2, "vicin": 2, "lfp_cal_ag": [2, 5], "lfp_cyc_ag": [2, 5], "nmc_cal_ag": [2, 5], "nmc_cyc_ag": [2, 5], "get_calendar_ag": [2, 5], "tupl": 2, "due": 2, "get_cyc_ag": [2, 5], "THe": 2, "both": 2, "adopt": 2, "schmalsteig": 2, "update_resist": [2, 5], "program": 2, "usag": 2, "proper": 2, "py": 2, "exampl": 2, "battery_config_path": 2, "r": 2, "battery_config": 2, "params_list": 2, "kei": 2, "params_": 2, "Then": 2, "params_kei": 2, "actual": 2, "those": 2, "prior": 2, "loadtxt": 2, "path_prefix": 2, "constructor": 2, "buffer_batteri": 2, "r_pack": [2, 5], "sum": 2, "aging_c": 2, "lost": 2, "after": 2, "round": 2, "trip": 2, "effici": 2, "_eff": 2, "last": 2, "load_pack_prop": [2, 5], "dx": 2, "nominal_pack_cap": [2, 5], "meth": 2, "intern": 2, "avail": [2, 4], "defer": 2, "TO": 2, "BE": 2, "anymor": 2, "onli": 2, "right": 2, "behavior": 2, "inspect": 2, "end": 2, "host": 2, "station": [2, 4], "storag": 2, "statu": 2, "idl": 2, "produc": 2, "reactiv": 2, "contribut": 2, "retain": 2, "inform": [2, 4], "etc": 2, "ingest": 2, "assign": 2, "get_current_load": [2, 5], "kw": 2, "is_ev_arriv": [2, 5], "is_charg": [2, 5], "set_current_load": [2, 5], "update_load": [2, 5], "net_grid_load": 2, "ev_load": 2, "mpc": [2, 5], "mode": 2, "update_load_oneshot": [2, 5], "offlin": 2, "non": 2, "update_statu": [2, 5], "scheme": 2, "bess": 2, "compute_control": [2, 5], "price_vector": 2, "action": 2, "comput": 2, "pass": 2, "control_act": 2, "signal": 2, "arbitrag": 2, "get_battery_constraint": [2, 5], "requir": 2, "satisfi": 2, "storage_constraint": 2, "initialize_forecast_data": [2, 5], "load_battery_ocv": [2, 5], "learn": 2, "reset_load": [2, 5], "oneshot": [2, 5], "96": 2, "feedback": 2, "price": 2, "structur": [2, 3, 10], "problem": 2, "pge_bev2_": [2, 5], "valid": 2, "california": 2, "howev": 2, "own": 2, "numpi": 2, "arrai": 2, "priceload": [2, 5], "evs": 2, "profit": 2, "loader": 2, "first": 2, "repositori": 2, "input_r": 2, "output_r": 2, "finer": 2, "similar": 2, "panda": 2, "typic": 2, "get_pric": [2, 5], "start_idx": 2, "7": 2, "assum": 2, "do": 2, "int": 2, "start": 2, "cardin": 2, "being": 2, "jan": 2, "ndarrai": 2, "set_month_data": [2, 5], "solv": 2, "objective_typ": 2, "power_demand": 2, "time_r": 2, "0": 2, "solver": [2, 4], "gurobi": 2, "degrad": 2, "convex": 2, "mix": 2, "integ": 2, "select": 2, "separ": 2, "pc": 2, "success": 2, "counter": 2, "identifi": 2, "backend": 2, "invok": 2, "eco": 2, "mosek": 2, "add_demand_charg": [2, 5], "aggregate_constraint": [2, 5], "aggreg": 2, "build_battery_cost": [2, 5], "build_emissions_cost": [2, 5], "emiss": 2, "build_transformer_cost": [2, 5], "get_constraint": [2, 5], "instanc": [2, 3], "chargingsim": [2, 5], "entir": 2, "num_charging_sit": 2, "6": 2, "num_ev": 2, "1600": 2, "custom_ev_data": 2, "custom_ev_data_path": 2, "custom_solar_data": 2, "custom_solar_data_path": 2, "organ": 2, "other": 2, "sequenti": 2, "manner": 2, "bool": 2, "If": 2, "site": 2, "o": 2, "create_battery_object": [2, 5], "idx": 2, "node_prop": 2, "l2": 2, "dcfc": 2, "create_charging_st": [2, 5], "power_nod": 2, "buse": 2, "create_charging_stations_oneshot": [2, 5], "create_solar_object": [2, 5], "loc": 2, "get_act": [2, 5], "get_charger_obj_by_loc": [2, 5], "get_charging_sit": [2, 5], "initialize_aging_sim": [2, 5], "initialize_control": [2, 5], "initialize_price_load": [2, 5], "memori": 2, "initialize_solar_modul": [2, 5], "load_battery_param": [2, 5], "directli": 2, "unless": 2, "otherwis": 2, "load_config": [2, 5], "walk": 2, "through": 2, "them": 2, "load_results_summari": [2, 5], "save_path_prefix": 2, "some": 2, "multistep": [2, 5], "faster": 2, "than": 2, "horizon": 2, "perfect": 2, "foresight": 2, "daili": 2, "reset": 2, "power_nodes_list": 2, "accordingli": 2, "specif": 2, "stepsiz": 2, "update_scenario": [2, 5], "match": 2, "update_step": [2, 5], "move": 2, "namepl": 2, "p_": 2, "eta": 2, "panel": 2, "make": 2, "decis": 2, "flow": [2, 4], "devic": 2, "get_pow": [2, 5], "desired_shap": 2, "get_solar_output": [2, 5], "modify_r": [2, 5], "new_r": 2, "update_histori": [2, 5], "purpos": 2, "mayb": 2, "schedul": 2, "pge": 2, "doc": 2, "found": 2, "add_power_profile_to_object": [2, 5], "battery_power_profil": 2, "build_cost_pge_bev2": [2, 5], "energy_prices_t": 2, "penalize_max_pow": 2, "max_power_pen": 2, "1000": 2, "heurist": 2, "averag": 2, "conserv": 2, "gamma": 2, "build_electricity_cost": [2, 5], "demand_charg": 2, "opt": 2, "build_object": [2, 5], "electricity_cost": 2, "battery_degradation_cost": 2, "we": [2, 4], "minim": 2, "load_pric": [2, 5], "time_interv": 2, "load_base_glm": [3, 5, 9, 10], "base_file_dir": [3, 10], "base_glm_fil": [3, 10], "replace_load_w_met": [3, 5, 9, 10], "glm_dict": [3, 10], "match_str": [3, 10], "rep_str": [3, 10], "obj_typ": [3, 10], "replac": [3, 10], "meter": [3, 10], "replace_load_w_meter_old": [3, 5, 9, 10], "write_base_glm": [3, 5, 9, 10], "globals_list": [3, 10], "include_list": [3, 10], "out_dir": [3, 10], "file_nam": [3, 10], "sync_list": [3, 10], "write_class_dict": [3, 5, 9, 10], "gld_dict": [3, 10], "class_nam": [3, 10], "correspond": [3, 10], "gld": [3, 10], "write_clock_dict": [3, 5, 9, 10], "clock": [3, 10], "write_filter_dict": [3, 5, 9, 10], "write_mod_dict": [3, 5, 9, 10], "mod_nam": [3, 10], "write_obj_dict": [3, 5, 9, 10], "dict_kei": [3, 10], "co": 4, "platform": 4, "interfac": 4, "phase": 4, "unbalanc": 4, "fast": 4, "made": 4, "web": 4, "tool": 4, "public": 4, "most": 4, "code": 4, "document": 4, "project": 4, "still": 4, "under": 4, "activ": 4, "improv": 4, "todo": 4, "tutori": 4, "analysi": [4, 5], "feeder": [4, 5], "case": [4, 5], "readm": 4, "guid": [], "cite": [], "modul": [4, 5], "search": 4, "page": 4, "submodul": [5, 7], "content": 5, "charging_sim": 5, "batteryagingsim": 5, "batterypack": 5, "batterytest": 5, "capacitor": 5, "chargingst": 5, "electricitypric": 5, "optim": 5, "orchestr": 5, "util": 5, "feeder_popul": [5, 7, 9], "glm_mod_funct": [5, 7, 9], "subpackag": 5, "test_cas": [5, 7], "event_handl": [5, 7], "gblvar": [5, 7], "glmptime": [5, 7], "voltdump2": [5, 7], "data_analysi": [5, 7], "event_handlers_oneshot": [5, 7], "parse_voltag": [5, 7], "feeder_population_old": [7, 9], "without": 2, "studi": 2, "character": 2, "what": 2, "would": 2, "occur": 2, "situ": 2, "wa": 2, "make_scenario": [2, 5], "No": 2, "preload": 2, "reflect": 2, "run_scenario_singl": [2, 5], "singl": 2, "run_scenarios_parallel": [2, 5], "multiprocess": 2, "enough": 2, "core": 2, "ram": 2, "mai": 2, "lead": 2, "process": 2, "freez": 2, "run_scenarios_sequenti": [2, 5], "combin": 2}, "objects": {"": [[1, 0, 0, "-", "analysis"], [2, 0, 0, "-", "charging_sim"], [3, 0, 0, "-", "feeder_population"], [7, 0, 0, "-", "test_cases"]], "analysis": [[1, 0, 0, "-", "cost_analysis"]], "analysis.cost_analysis": [[1, 1, 1, "", "CostEstimator"]], "analysis.cost_analysis.CostEstimator": [[1, 2, 1, "", "calculate_battery_cost"], [1, 2, 1, "", "calculate_electricity_cost_PGEBEV2s"], [1, 2, 1, "", "calculate_solar_cost"], [1, 2, 1, "", "calculate_trans_loss_of_life"], [1, 2, 1, "", "plot_loads"], [1, 2, 1, "", "plot_power"], [1, 2, 1, "", "plot_soc"], [1, 2, 1, "", "solar_cost"], [1, 2, 1, "", "transformer_cost"]], "charging_sim": [[2, 0, 0, "-", "battery"], [2, 0, 0, "-", "batteryAgingSim"], [2, 0, 0, "-", "batterypack"], [2, 0, 0, "-", "capacitor"], [2, 0, 0, "-", "chargingStation"], [2, 0, 0, "-", "controller"], [2, 0, 0, "-", "electricityPrices"], [2, 0, 0, "-", "optimization"], [2, 0, 0, "-", "orchestrator"], [2, 0, 0, "-", "simulate"], [2, 0, 0, "-", "solar"], [2, 0, 0, "-", "utils"]], "charging_sim.battery": [[2, 1, 1, "", "Battery"], [2, 3, 1, "", "test"]], "charging_sim.battery.Battery": [[2, 2, 1, "", "battery_setup"], [2, 2, 1, "", "battery_setup_2"], [2, 2, 1, "", "dynamics"], [2, 2, 1, "", "est_calendar_aging"], [2, 2, 1, "", "est_cyc_aging"], [2, 2, 1, "", "get_OCV"], [2, 2, 1, "", "get_Ro"], [2, 2, 1, "", "get_aging_value"], [2, 2, 1, "", "get_power_profile"], [2, 2, 1, "", "get_properties"], [2, 2, 1, "", "get_roundtrip_efficiency"], [2, 2, 1, "", "get_total_aging"], [2, 2, 1, "", "get_true_power"], [2, 2, 1, "", "save_sim_data"], [2, 2, 1, "", "save_states"], [2, 2, 1, "", "state_eqn"], [2, 2, 1, "", "thermal_dynamics"], [2, 2, 1, "", "track_SOC"], [2, 2, 1, "", "update_SOC"], [2, 2, 1, "", "update_capacity"], [2, 2, 1, "", "update_max_current"], [2, 2, 1, "", "update_params"], [2, 2, 1, "", "update_voltage"], [2, 2, 1, "", "visualize"]], "charging_sim.batteryAgingSim": [[2, 1, 1, "", "BatteryAging"]], "charging_sim.batteryAgingSim.BatteryAging": [[2, 2, 1, "", "LFP_cal_aging"], [2, 2, 1, "", "LFP_cyc_aging"], [2, 2, 1, "", "NMC_cal_aging"], [2, 2, 1, "", "NMC_cyc_aging"], [2, 2, 1, "", "get_aging_value"], [2, 2, 1, "", "get_calendar_aging"], [2, 2, 1, "", "get_cyc_aging"], [2, 2, 1, "", "get_total_aging"], [2, 2, 1, "", "run"], [2, 2, 1, "", "update_capacity"], [2, 2, 1, "", "update_resistance"]], "charging_sim.batterypack": [[2, 1, 1, "", "Battery"], [2, 3, 1, "", "test"]], "charging_sim.batterypack.Battery": [[2, 4, 1, "", "R_pack"], [2, 2, 1, "", "battery_setup"], [2, 2, 1, "", "battery_setup_2"], [2, 4, 1, "", "battery_type"], [2, 4, 1, "", "config"], [2, 4, 1, "", "controller"], [2, 2, 1, "", "dynamics"], [2, 2, 1, "", "est_calendar_aging"], [2, 2, 1, "", "est_cyc_aging"], [2, 2, 1, "", "get_OCV"], [2, 2, 1, "", "get_aging_value"], [2, 2, 1, "", "get_power_profile"], [2, 2, 1, "", "get_roundtrip_efficiency"], [2, 2, 1, "", "get_total_aging"], [2, 2, 1, "", "get_true_power"], [2, 2, 1, "", "load_pack_props"], [2, 4, 1, "", "nominal_pack_cap"], [2, 2, 1, "", "save_sim_data"], [2, 2, 1, "", "state_eqn"], [2, 2, 1, "", "thermal_dynamics"], [2, 2, 1, "", "track_SOC"], [2, 2, 1, "", "update_capacity"], [2, 2, 1, "", "update_max_current"], [2, 2, 1, "", "update_voltage"], [2, 2, 1, "", "visualize"]], "charging_sim.capacitor": [[2, 1, 1, "", "Capacitor"]], "charging_sim.chargingStation": [[2, 1, 1, "", "ChargingStation"]], "charging_sim.chargingStation.ChargingStation": [[2, 2, 1, "", "get_current_load"], [2, 2, 1, "", "is_EV_arrived"], [2, 2, 1, "", "is_charging"], [2, 2, 1, "", "save_sim_data"], [2, 2, 1, "", "set_current_load"], [2, 2, 1, "", "update_load"], [2, 2, 1, "", "update_load_oneshot"], [2, 2, 1, "", "update_status"], [2, 2, 1, "", "visualize"]], "charging_sim.controller": [[2, 1, 1, "", "MPC"], [2, 1, 1, "", "Oneshot"]], "charging_sim.controller.MPC": [[2, 2, 1, "", "compute_control"], [2, 2, 1, "", "get_battery_constraints"], [2, 2, 1, "", "initialize_forecast_data"], [2, 2, 1, "", "load_battery_ocv"], [2, 2, 1, "", "reset_load"]], "charging_sim.controller.Oneshot": [[2, 2, 1, "", "compute_control"], [2, 2, 1, "", "get_battery_constraints"], [2, 2, 1, "", "load_battery_ocv"], [2, 2, 1, "", "reset_load"]], "charging_sim.electricityPrices": [[2, 1, 1, "", "PriceLoader"], [2, 3, 1, "", "main"]], "charging_sim.electricityPrices.PriceLoader": [[2, 2, 1, "", "downscale"], [2, 2, 1, "", "get_prices"], [2, 2, 1, "", "set_month_data"]], "charging_sim.optimization": [[2, 1, 1, "", "Optimization"]], "charging_sim.optimization.Optimization": [[2, 2, 1, "", "add_demand_charge"], [2, 2, 1, "", "aggregate_constraints"], [2, 2, 1, "", "build_battery_cost"], [2, 2, 1, "", "build_emissions_cost"], [2, 2, 1, "", "build_transformer_cost"], [2, 2, 1, "", "get_battery_constraint"], [2, 2, 1, "", "get_constraints"], [2, 2, 1, "", "run"]], "charging_sim.orchestrator": [[2, 1, 1, "", "ChargingSim"]], "charging_sim.orchestrator.ChargingSim": [[2, 2, 1, "", "create_battery_object"], [2, 2, 1, "", "create_charging_stations"], [2, 2, 1, "", "create_charging_stations_oneshot"], [2, 2, 1, "", "create_solar_object"], [2, 2, 1, "", "get_action"], [2, 2, 1, "", "get_charger_obj_by_loc"], [2, 2, 1, "", "get_charging_sites"], [2, 2, 1, "", "initialize_aging_sim"], [2, 2, 1, "", "initialize_controllers"], [2, 2, 1, "", "initialize_price_loader"], [2, 2, 1, "", "initialize_solar_module"], [2, 2, 1, "", "load_battery_params"], [2, 2, 1, "", "load_config"], [2, 2, 1, "", "load_results_summary"], [2, 2, 1, "", "multistep"], [2, 2, 1, "", "reset_loads"], [2, 2, 1, "", "setup"], [2, 2, 1, "", "step"], [2, 2, 1, "", "update_scenario"], [2, 2, 1, "", "update_steps"]], "charging_sim.simulate": [[2, 3, 1, "", "make_scenarios"], [2, 3, 1, "", "run"], [2, 3, 1, "", "run_scenario_single"], [2, 3, 1, "", "run_scenarios_parallel"], [2, 3, 1, "", "run_scenarios_sequential"]], "charging_sim.solar": [[2, 1, 1, "", "Solar"], [2, 3, 1, "", "main"]], "charging_sim.solar.Solar": [[2, 2, 1, "", "downscale"], [2, 2, 1, "", "get_constraints"], [2, 2, 1, "", "get_power"], [2, 2, 1, "", "get_solar_output"], [2, 2, 1, "", "modify_res"], [2, 2, 1, "", "update_history"]], "charging_sim.utils": [[2, 3, 1, "", "PGE_BEV2_S"], [2, 3, 1, "", "add_power_profile_to_object"], [2, 3, 1, "", "build_cost_PGE_BEV2S"], [2, 3, 1, "", "build_electricity_cost"], [2, 3, 1, "", "build_objective"], [2, 3, 1, "", "load_prices"]], "feeder_population": [[3, 0, 0, "-", "glm_mod_functions"]], "feeder_population.glm_mod_functions": [[3, 3, 1, "", "load_base_glm"], [3, 3, 1, "", "replace_load_w_meter"], [3, 3, 1, "", "replace_load_w_meter_old"], [3, 3, 1, "", "write_base_glm"], [3, 3, 1, "", "write_class_dict"], [3, 3, 1, "", "write_clock_dict"], [3, 3, 1, "", "write_filter_dict"], [3, 3, 1, "", "write_mod_dict"], [3, 3, 1, "", "write_obj_dict"]], "test_cases": [[8, 0, 0, "-", "base_case"], [9, 0, 0, "-", "battery"]], "test_cases.battery": [[10, 0, 0, "-", "feeder_population"]], "test_cases.battery.feeder_population": [[10, 0, 0, "-", "glm_mod_functions"]], "test_cases.battery.feeder_population.glm_mod_functions": [[10, 3, 1, "", "load_base_glm"], [10, 3, 1, "", "replace_load_w_meter"], [10, 3, 1, "", "replace_load_w_meter_old"], [10, 3, 1, "", "write_base_glm"], [10, 3, 1, "", "write_class_dict"], [10, 3, 1, "", "write_clock_dict"], [10, 3, 1, "", "write_filter_dict"], [10, 3, 1, "", "write_mod_dict"], [10, 3, 1, "", "write_obj_dict"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:method", "3": "py:function", "4": "py:attribute"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"], "3": ["py", "function", "Python function"], "4": ["py", "attribute", "Python attribute"]}, "titleterms": {"ev": [0, 4], "ecosim": [0, 4], "platform": 0, "author": 0, "requir": 0, "folder": 0, "descript": 0, "ambient_data": 0, "base_load_data": 0, "batt_sys_identif": 0, "charging_sim": [0, 2], "batteri": [0, 2, 9, 10], "py": 0, "cell": 0, "modul": [0, 1, 2, 3, 7, 8, 9, 10], "batterypack": [0, 2], "pack": 0, "batteryagingsim": [0, 2], "ag": 0, "control": [0, 2], "chargingst": [0, 2], "charg": [0, 2], "station": 0, "electricitypric": [0, 2], "electr": 0, "price": 0, "optim": [0, 2], "orchestr": [0, 2], "simul": [0, 1, 2], "solar": [0, 2], "pv": 0, "util": [0, 2], "host": 0, "function": 0, "us": 0, "some": 0, "offlin": 0, "der": 0, "cost": 0, "minim": 0, "thi": 0, "i": 0, "run": 0, "mode": 0, "state": 0, "feedback": 0, "dlmodel": 0, "elec_r": 0, "feeder": [0, 3], "feeder_popul": [0, 3, 10], "solar_data": 0, "test_cas": [0, 8, 9, 10], "co": 0, "case": [0, 7], "analysi": [0, 1], "how": 0, "post": [0, 1], "packag": [5, 8, 9, 10], "submodul": [1, 2, 3, 8, 9, 10], "cost_analysi": 1, "load_post_opt_cost": 1, "plot_result": 1, "content": [1, 2, 3, 4, 7, 8, 9, 10], "batterytest": 2, "capacitor": 2, "popul": 3, "glm_mod_funct": [3, 10], "welcom": 4, "1": 4, "0": 4, "indic": 4, "tabl": 4, "test": 7, "subpackag": [7, 9], "base_cas": 8, "event_handl": [8, 9], "gblvar": [8, 9], "glmptime": [8, 9], "master_sim": [8, 9], "sim": [8, 9], "voltdump2": [8, 9], "data_analysi": 9, "event_handlers_oneshot": 9, "parse_voltag": 9, "scenario": 9, "feeder_population_old": 10, "readm": 6}, "envversion": {"sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.todo": 2, "sphinx.ext.viewcode": 1, "sphinx": 60}, "alltitles": {"Packages": [[5, "packages"]], "Test cases": [[7, "test-cases"]], "Subpackages": [[7, "subpackages"], [9, "subpackages"]], "Module contents": [[7, "module-test_cases"], [1, "module-analysis"], [2, "module-charging_sim"], [3, "module-feeder_population"], [8, "module-test_cases.base_case"], [9, "module-test_cases.battery"], [10, "module-test_cases.battery.feeder_population"]], "Welcome to EV-Ecosim 1.0.0": [[4, "welcome-to-ev-ecosim-1-0-0"]], "Contents:": [[4, null]], "Indices and tables": [[4, "indices-and-tables"]], "Readme": [[6, "readme"]], "EV-Ecosim platform": [[0, "ev-ecosim-platform"]], "Authors": [[0, "authors"]], "Requirements": [[0, "requirements"]], "Folder descriptions": [[0, "folder-descriptions"]], "ambient_data": [[0, "ambient-data"]], "base_load_data": [[0, "base-load-data"]], "batt_sys_identification": [[0, "batt-sys-identification"]], "charging_sim": [[0, "charging-sim"]], "battery.py - Battery cell module.": [[0, "battery-py-battery-cell-module"]], "batterypack.py - Battery pack module.": [[0, "batterypack-py-battery-pack-module"]], "batteryAgingSim.py - Battery aging module.": [[0, "batteryagingsim-py-battery-aging-module"]], "controller.py - Controller module.": [[0, "controller-py-controller-module"]], "chargingStation.py - Charging station module.": [[0, "chargingstation-py-charging-station-module"]], "electricityPrices.py - Electricity prices module.": [[0, "electricityprices-py-electricity-prices-module"]], "optimization.py - Optimization module.": [[0, "optimization-py-optimization-module"]], "orchestrator.py - Simulation orchestrator module.": [[0, "orchestrator-py-simulation-orchestrator-module"]], "solar.py - Solar PV module.": [[0, "solar-py-solar-pv-module"]], "utils.py - Hosts utility functions used by some modules.": [[0, "utils-py-hosts-utility-functions-used-by-some-modules"]], "simulate.py - Offline DER control optimization for cost minimization (this is run for offline mode (no state feedback)).": [[0, "simulate-py-offline-der-control-optimization-for-cost-minimization-this-is-run-for-offline-mode-no-state-feedback"]], "DLMODELS": [[0, "dlmodels"]], "elec_rates": [[0, "elec-rates"]], "feeders": [[0, "feeders"]], "feeder_population": [[0, "feeder-population"]], "solar_data": [[0, "solar-data"]], "test_cases": [[0, "test-cases"]], "Co-simulation cases.": [[0, "co-simulation-cases"]], "analysis": [[0, "analysis"]], "How to run": [[0, "how-to-run"]], "Post-simulation analysis": [[0, "post-simulation-analysis"], [1, "post-simulation-analysis"]], "Submodules": [[1, "submodules"], [2, "submodules"], [3, "submodules"], [8, "submodules"], [9, "submodules"], [10, "submodules"]], "cost_analysis module": [[1, "module-analysis.cost_analysis"]], "load_post_opt_costs module": [[1, "load-post-opt-costs-module"]], "plot_results module": [[1, "plot-results-module"]], "Charging simulator": [[2, "charging-simulator"]], "charging_sim.battery module": [[2, "module-charging_sim.battery"]], "charging_sim.batteryAgingSim module": [[2, "module-charging_sim.batteryAgingSim"]], "charging_sim.batterypack module": [[2, "module-charging_sim.batterypack"]], "charging_sim.batterytest module": [[2, "charging-sim-batterytest-module"]], "charging_sim.capacitor module": [[2, "module-charging_sim.capacitor"]], "charging_sim.chargingStation module": [[2, "module-charging_sim.chargingStation"]], "charging_sim.controller module": [[2, "module-charging_sim.controller"]], "charging_sim.electricityPrices module": [[2, "module-charging_sim.electricityPrices"]], "charging_sim.optimization module": [[2, "module-charging_sim.optimization"]], "charging_sim.orchestrator module": [[2, "module-charging_sim.orchestrator"]], "charging_sim.simulate module": [[2, "module-charging_sim.simulate"]], "charging_sim.solar module": [[2, "module-charging_sim.solar"]], "charging_sim.utils module": [[2, "module-charging_sim.utils"]], "Feeder population": [[3, "feeder-population"]], "feeder_population.feeder_population module": [[3, "feeder-population-feeder-population-module"]], "feeder_population.glm_mod_functions module": [[3, "module-feeder_population.glm_mod_functions"]], "test_cases.base_case package": [[8, "test-cases-base-case-package"]], "test_cases.base_case.event_handlers module": [[8, "test-cases-base-case-event-handlers-module"]], "test_cases.base_case.gblvar module": [[8, "test-cases-base-case-gblvar-module"]], "test_cases.base_case.glmptime module": [[8, "test-cases-base-case-glmptime-module"]], "test_cases.base_case.master_sim module": [[8, "test-cases-base-case-master-sim-module"]], "test_cases.base_case.sim module": [[8, "test-cases-base-case-sim-module"]], "test_cases.base_case.voltdump2 module": [[8, "test-cases-base-case-voltdump2-module"]], "test_cases.battery package": [[9, "test-cases-battery-package"]], "test_cases.battery.data_analysis module": [[9, "test-cases-battery-data-analysis-module"]], "test_cases.battery.event_handlers module": [[9, "test-cases-battery-event-handlers-module"]], "test_cases.battery.event_handlers_oneshot module": [[9, "test-cases-battery-event-handlers-oneshot-module"]], "test_cases.battery.gblvar module": [[9, "test-cases-battery-gblvar-module"]], "test_cases.battery.glmptime module": [[9, "test-cases-battery-glmptime-module"]], "test_cases.battery.master_sim module": [[9, "test-cases-battery-master-sim-module"]], "test_cases.battery.parse_voltages module": [[9, "test-cases-battery-parse-voltages-module"]], "test_cases.battery.scenarios module": [[9, "test-cases-battery-scenarios-module"]], "test_cases.battery.sim module": [[9, "test-cases-battery-sim-module"]], "test_cases.battery.voltdump2 module": [[9, "test-cases-battery-voltdump2-module"]], "test_cases.battery.feeder_population package": [[10, "test-cases-battery-feeder-population-package"]], "test_cases.battery.feeder_population.feeder_population module": [[10, "test-cases-battery-feeder-population-feeder-population-module"]], "test_cases.battery.feeder_population.feeder_population_old module": [[10, "test-cases-battery-feeder-population-feeder-population-old-module"]], "test_cases.battery.feeder_population.glm_mod_functions module": [[10, "module-test_cases.battery.feeder_population.glm_mod_functions"]]}, "indexentries": {"costestimator (class in analysis.cost_analysis)": [[1, "analysis.cost_analysis.CostEstimator"]], "analysis": [[1, "module-analysis"]], "analysis.cost_analysis": [[1, "module-analysis.cost_analysis"]], "calculate_battery_cost() (analysis.cost_analysis.costestimator method)": [[1, "analysis.cost_analysis.CostEstimator.calculate_battery_cost"]], "calculate_electricity_cost_pgebev2s() (analysis.cost_analysis.costestimator method)": [[1, "analysis.cost_analysis.CostEstimator.calculate_electricity_cost_PGEBEV2s"]], "calculate_solar_cost() (analysis.cost_analysis.costestimator method)": [[1, "analysis.cost_analysis.CostEstimator.calculate_solar_cost"]], "calculate_trans_loss_of_life() (analysis.cost_analysis.costestimator method)": [[1, "analysis.cost_analysis.CostEstimator.calculate_trans_loss_of_life"]], "module": [[1, "module-analysis"], [1, "module-analysis.cost_analysis"], [2, "module-charging_sim"], [2, "module-charging_sim.battery"], [2, "module-charging_sim.batteryAgingSim"], [2, "module-charging_sim.batterypack"], [2, "module-charging_sim.capacitor"], [2, "module-charging_sim.chargingStation"], [2, "module-charging_sim.controller"], [2, "module-charging_sim.electricityPrices"], [2, "module-charging_sim.optimization"], [2, "module-charging_sim.orchestrator"], [2, "module-charging_sim.simulate"], [2, "module-charging_sim.solar"], [2, "module-charging_sim.utils"], [3, "module-feeder_population"], [3, "module-feeder_population.glm_mod_functions"], [7, "module-test_cases"], [8, "module-test_cases.base_case"], [9, "module-test_cases.battery"], [10, "module-test_cases.battery.feeder_population"], [10, "module-test_cases.battery.feeder_population.glm_mod_functions"]], "plot_loads() (analysis.cost_analysis.costestimator static method)": [[1, "analysis.cost_analysis.CostEstimator.plot_loads"]], "plot_power() (analysis.cost_analysis.costestimator static method)": [[1, "analysis.cost_analysis.CostEstimator.plot_power"]], "plot_soc() (analysis.cost_analysis.costestimator static method)": [[1, "analysis.cost_analysis.CostEstimator.plot_soc"]], "solar_cost() (analysis.cost_analysis.costestimator method)": [[1, "analysis.cost_analysis.CostEstimator.solar_cost"]], "transformer_cost() (analysis.cost_analysis.costestimator method)": [[1, "analysis.cost_analysis.CostEstimator.transformer_cost"]], "battery (class in charging_sim.battery)": [[2, "charging_sim.battery.Battery"]], "battery (class in charging_sim.batterypack)": [[2, "charging_sim.batterypack.Battery"]], "batteryaging (class in charging_sim.batteryagingsim)": [[2, "charging_sim.batteryAgingSim.BatteryAging"]], "capacitor (class in charging_sim.capacitor)": [[2, "charging_sim.capacitor.Capacitor"]], "chargingsim (class in charging_sim.orchestrator)": [[2, "charging_sim.orchestrator.ChargingSim"]], "chargingstation (class in charging_sim.chargingstation)": [[2, "charging_sim.chargingStation.ChargingStation"]], "lfp_cal_aging() (charging_sim.batteryagingsim.batteryaging static method)": [[2, "charging_sim.batteryAgingSim.BatteryAging.LFP_cal_aging"]], "lfp_cyc_aging() (charging_sim.batteryagingsim.batteryaging static method)": [[2, "charging_sim.batteryAgingSim.BatteryAging.LFP_cyc_aging"]], "mpc (class in charging_sim.controller)": [[2, "charging_sim.controller.MPC"]], "nmc_cal_aging() (charging_sim.batteryagingsim.batteryaging static method)": [[2, "charging_sim.batteryAgingSim.BatteryAging.NMC_cal_aging"]], "nmc_cyc_aging() (charging_sim.batteryagingsim.batteryaging static method)": [[2, "charging_sim.batteryAgingSim.BatteryAging.NMC_cyc_aging"]], "oneshot (class in charging_sim.controller)": [[2, "charging_sim.controller.Oneshot"]], "optimization (class in charging_sim.optimization)": [[2, "charging_sim.optimization.Optimization"]], "pge_bev2_s() (in module charging_sim.utils)": [[2, "charging_sim.utils.PGE_BEV2_S"]], "priceloader (class in charging_sim.electricityprices)": [[2, "charging_sim.electricityPrices.PriceLoader"]], "r_pack (charging_sim.batterypack.battery attribute)": [[2, "charging_sim.batterypack.Battery.R_pack"]], "solar (class in charging_sim.solar)": [[2, "charging_sim.solar.Solar"]], "add_demand_charge() (charging_sim.optimization.optimization method)": [[2, "charging_sim.optimization.Optimization.add_demand_charge"]], "add_power_profile_to_object() (in module charging_sim.utils)": [[2, "charging_sim.utils.add_power_profile_to_object"]], "aggregate_constraints() (charging_sim.optimization.optimization method)": [[2, "charging_sim.optimization.Optimization.aggregate_constraints"]], "battery_setup() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.battery_setup"]], "battery_setup() (charging_sim.batterypack.battery method)": [[2, "charging_sim.batterypack.Battery.battery_setup"]], "battery_setup_2() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.battery_setup_2"]], "battery_setup_2() (charging_sim.batterypack.battery method)": [[2, "charging_sim.batterypack.Battery.battery_setup_2"]], "battery_type (charging_sim.batterypack.battery attribute)": [[2, "charging_sim.batterypack.Battery.battery_type"]], "build_battery_cost() (charging_sim.optimization.optimization method)": [[2, "charging_sim.optimization.Optimization.build_battery_cost"]], "build_cost_pge_bev2s() (in module charging_sim.utils)": [[2, "charging_sim.utils.build_cost_PGE_BEV2S"]], "build_electricity_cost() (in module charging_sim.utils)": [[2, "charging_sim.utils.build_electricity_cost"]], "build_emissions_cost() (charging_sim.optimization.optimization method)": [[2, "charging_sim.optimization.Optimization.build_emissions_cost"]], "build_objective() (in module charging_sim.utils)": [[2, "charging_sim.utils.build_objective"]], "build_transformer_cost() (charging_sim.optimization.optimization method)": [[2, "charging_sim.optimization.Optimization.build_transformer_cost"]], "charging_sim": [[2, "module-charging_sim"]], "charging_sim.battery": [[2, "module-charging_sim.battery"]], "charging_sim.batteryagingsim": [[2, "module-charging_sim.batteryAgingSim"]], "charging_sim.batterypack": [[2, "module-charging_sim.batterypack"]], "charging_sim.capacitor": [[2, "module-charging_sim.capacitor"]], "charging_sim.chargingstation": [[2, "module-charging_sim.chargingStation"]], "charging_sim.controller": [[2, "module-charging_sim.controller"]], "charging_sim.electricityprices": [[2, "module-charging_sim.electricityPrices"]], "charging_sim.optimization": [[2, "module-charging_sim.optimization"]], "charging_sim.orchestrator": [[2, "module-charging_sim.orchestrator"]], "charging_sim.simulate": [[2, "module-charging_sim.simulate"]], "charging_sim.solar": [[2, "module-charging_sim.solar"]], "charging_sim.utils": [[2, "module-charging_sim.utils"]], "compute_control() (charging_sim.controller.mpc method)": [[2, "charging_sim.controller.MPC.compute_control"]], "compute_control() (charging_sim.controller.oneshot method)": [[2, "charging_sim.controller.Oneshot.compute_control"]], "config (charging_sim.batterypack.battery attribute)": [[2, "charging_sim.batterypack.Battery.config"]], "controller (charging_sim.batterypack.battery attribute)": [[2, "charging_sim.batterypack.Battery.controller"]], "create_battery_object() (charging_sim.orchestrator.chargingsim method)": [[2, "charging_sim.orchestrator.ChargingSim.create_battery_object"]], "create_charging_stations() (charging_sim.orchestrator.chargingsim method)": [[2, "charging_sim.orchestrator.ChargingSim.create_charging_stations"]], "create_charging_stations_oneshot() (charging_sim.orchestrator.chargingsim method)": [[2, "charging_sim.orchestrator.ChargingSim.create_charging_stations_oneshot"]], "create_solar_object() (charging_sim.orchestrator.chargingsim method)": [[2, "charging_sim.orchestrator.ChargingSim.create_solar_object"]], "downscale() (charging_sim.electricityprices.priceloader method)": [[2, "charging_sim.electricityPrices.PriceLoader.downscale"]], "downscale() (charging_sim.solar.solar method)": [[2, "charging_sim.solar.Solar.downscale"]], "dynamics() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.dynamics"]], "dynamics() (charging_sim.batterypack.battery method)": [[2, "charging_sim.batterypack.Battery.dynamics"]], "est_calendar_aging() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.est_calendar_aging"]], "est_calendar_aging() (charging_sim.batterypack.battery method)": [[2, "charging_sim.batterypack.Battery.est_calendar_aging"]], "est_cyc_aging() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.est_cyc_aging"]], "est_cyc_aging() (charging_sim.batterypack.battery method)": [[2, "charging_sim.batterypack.Battery.est_cyc_aging"]], "get_ocv() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.get_OCV"]], "get_ocv() (charging_sim.batterypack.battery method)": [[2, "charging_sim.batterypack.Battery.get_OCV"]], "get_ro() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.get_Ro"]], "get_action() (charging_sim.orchestrator.chargingsim static method)": [[2, "charging_sim.orchestrator.ChargingSim.get_action"]], "get_aging_value() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.get_aging_value"]], "get_aging_value() (charging_sim.batteryagingsim.batteryaging method)": [[2, "charging_sim.batteryAgingSim.BatteryAging.get_aging_value"]], "get_aging_value() (charging_sim.batterypack.battery method)": [[2, "charging_sim.batterypack.Battery.get_aging_value"]], "get_battery_constraint() (charging_sim.optimization.optimization method)": [[2, "charging_sim.optimization.Optimization.get_battery_constraint"]], "get_battery_constraints() (charging_sim.controller.mpc method)": [[2, "charging_sim.controller.MPC.get_battery_constraints"]], "get_battery_constraints() (charging_sim.controller.oneshot method)": [[2, "charging_sim.controller.Oneshot.get_battery_constraints"]], "get_calendar_aging() (charging_sim.batteryagingsim.batteryaging method)": [[2, "charging_sim.batteryAgingSim.BatteryAging.get_calendar_aging"]], "get_charger_obj_by_loc() (charging_sim.orchestrator.chargingsim method)": [[2, "charging_sim.orchestrator.ChargingSim.get_charger_obj_by_loc"]], "get_charging_sites() (charging_sim.orchestrator.chargingsim method)": [[2, "charging_sim.orchestrator.ChargingSim.get_charging_sites"]], "get_constraints() (charging_sim.optimization.optimization method)": [[2, "charging_sim.optimization.Optimization.get_constraints"]], "get_constraints() (charging_sim.solar.solar method)": [[2, "charging_sim.solar.Solar.get_constraints"]], "get_current_load() (charging_sim.chargingstation.chargingstation method)": [[2, "charging_sim.chargingStation.ChargingStation.get_current_load"]], "get_cyc_aging() (charging_sim.batteryagingsim.batteryaging method)": [[2, "charging_sim.batteryAgingSim.BatteryAging.get_cyc_aging"]], "get_power() (charging_sim.solar.solar method)": [[2, "charging_sim.solar.Solar.get_power"]], "get_power_profile() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.get_power_profile"]], "get_power_profile() (charging_sim.batterypack.battery method)": [[2, "charging_sim.batterypack.Battery.get_power_profile"]], "get_prices() (charging_sim.electricityprices.priceloader method)": [[2, "charging_sim.electricityPrices.PriceLoader.get_prices"]], "get_properties() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.get_properties"]], "get_roundtrip_efficiency() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.get_roundtrip_efficiency"]], "get_roundtrip_efficiency() (charging_sim.batterypack.battery method)": [[2, "charging_sim.batterypack.Battery.get_roundtrip_efficiency"]], "get_solar_output() (charging_sim.solar.solar method)": [[2, "charging_sim.solar.Solar.get_solar_output"]], "get_total_aging() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.get_total_aging"]], "get_total_aging() (charging_sim.batteryagingsim.batteryaging method)": [[2, "charging_sim.batteryAgingSim.BatteryAging.get_total_aging"]], "get_total_aging() (charging_sim.batterypack.battery method)": [[2, "charging_sim.batterypack.Battery.get_total_aging"]], "get_true_power() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.get_true_power"]], "get_true_power() (charging_sim.batterypack.battery method)": [[2, "charging_sim.batterypack.Battery.get_true_power"]], "initialize_aging_sim() (charging_sim.orchestrator.chargingsim method)": [[2, "charging_sim.orchestrator.ChargingSim.initialize_aging_sim"]], "initialize_controllers() (charging_sim.orchestrator.chargingsim method)": [[2, "charging_sim.orchestrator.ChargingSim.initialize_controllers"]], "initialize_forecast_data() (charging_sim.controller.mpc method)": [[2, "charging_sim.controller.MPC.initialize_forecast_data"]], "initialize_price_loader() (charging_sim.orchestrator.chargingsim method)": [[2, "charging_sim.orchestrator.ChargingSim.initialize_price_loader"]], "initialize_solar_module() (charging_sim.orchestrator.chargingsim method)": [[2, "charging_sim.orchestrator.ChargingSim.initialize_solar_module"]], "is_ev_arrived() (charging_sim.chargingstation.chargingstation method)": [[2, "charging_sim.chargingStation.ChargingStation.is_EV_arrived"]], "is_charging() (charging_sim.chargingstation.chargingstation method)": [[2, "charging_sim.chargingStation.ChargingStation.is_charging"]], "load_battery_ocv() (charging_sim.controller.mpc method)": [[2, "charging_sim.controller.MPC.load_battery_ocv"]], "load_battery_ocv() (charging_sim.controller.oneshot method)": [[2, "charging_sim.controller.Oneshot.load_battery_ocv"]], "load_battery_params() (charging_sim.orchestrator.chargingsim method)": [[2, "charging_sim.orchestrator.ChargingSim.load_battery_params"]], "load_config() (charging_sim.orchestrator.chargingsim method)": [[2, "charging_sim.orchestrator.ChargingSim.load_config"]], "load_pack_props() (charging_sim.batterypack.battery method)": [[2, "charging_sim.batterypack.Battery.load_pack_props"]], "load_prices() (in module charging_sim.utils)": [[2, "charging_sim.utils.load_prices"]], "load_results_summary() (charging_sim.orchestrator.chargingsim method)": [[2, "charging_sim.orchestrator.ChargingSim.load_results_summary"]], "main() (in module charging_sim.electricityprices)": [[2, "charging_sim.electricityPrices.main"]], "main() (in module charging_sim.solar)": [[2, "charging_sim.solar.main"]], "make_scenarios() (in module charging_sim.simulate)": [[2, "charging_sim.simulate.make_scenarios"]], "modify_res() (charging_sim.solar.solar method)": [[2, "charging_sim.solar.Solar.modify_res"]], "multistep() (charging_sim.orchestrator.chargingsim method)": [[2, "charging_sim.orchestrator.ChargingSim.multistep"]], "nominal_pack_cap (charging_sim.batterypack.battery attribute)": [[2, "charging_sim.batterypack.Battery.nominal_pack_cap"]], "reset_load() (charging_sim.controller.mpc method)": [[2, "charging_sim.controller.MPC.reset_load"]], "reset_load() (charging_sim.controller.oneshot method)": [[2, "charging_sim.controller.Oneshot.reset_load"]], "reset_loads() (charging_sim.orchestrator.chargingsim method)": [[2, "charging_sim.orchestrator.ChargingSim.reset_loads"]], "run() (charging_sim.batteryagingsim.batteryaging method)": [[2, "charging_sim.batteryAgingSim.BatteryAging.run"]], "run() (charging_sim.optimization.optimization method)": [[2, "charging_sim.optimization.Optimization.run"]], "run() (in module charging_sim.simulate)": [[2, "charging_sim.simulate.run"]], "run_scenario_single() (in module charging_sim.simulate)": [[2, "charging_sim.simulate.run_scenario_single"]], "run_scenarios_parallel() (in module charging_sim.simulate)": [[2, "charging_sim.simulate.run_scenarios_parallel"]], "run_scenarios_sequential() (in module charging_sim.simulate)": [[2, "charging_sim.simulate.run_scenarios_sequential"]], "save_sim_data() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.save_sim_data"]], "save_sim_data() (charging_sim.batterypack.battery method)": [[2, "charging_sim.batterypack.Battery.save_sim_data"]], "save_sim_data() (charging_sim.chargingstation.chargingstation method)": [[2, "charging_sim.chargingStation.ChargingStation.save_sim_data"]], "save_states() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.save_states"]], "set_current_load() (charging_sim.chargingstation.chargingstation method)": [[2, "charging_sim.chargingStation.ChargingStation.set_current_load"]], "set_month_data() (charging_sim.electricityprices.priceloader method)": [[2, "charging_sim.electricityPrices.PriceLoader.set_month_data"]], "setup() (charging_sim.orchestrator.chargingsim method)": [[2, "charging_sim.orchestrator.ChargingSim.setup"]], "state_eqn() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.state_eqn"]], "state_eqn() (charging_sim.batterypack.battery method)": [[2, "charging_sim.batterypack.Battery.state_eqn"]], "step() (charging_sim.orchestrator.chargingsim method)": [[2, "charging_sim.orchestrator.ChargingSim.step"]], "test() (in module charging_sim.battery)": [[2, "charging_sim.battery.test"]], "test() (in module charging_sim.batterypack)": [[2, "charging_sim.batterypack.test"]], "thermal_dynamics() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.thermal_dynamics"]], "thermal_dynamics() (charging_sim.batterypack.battery method)": [[2, "charging_sim.batterypack.Battery.thermal_dynamics"]], "track_soc() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.track_SOC"]], "track_soc() (charging_sim.batterypack.battery method)": [[2, "charging_sim.batterypack.Battery.track_SOC"]], "update_soc() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.update_SOC"]], "update_capacity() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.update_capacity"]], "update_capacity() (charging_sim.batteryagingsim.batteryaging method)": [[2, "charging_sim.batteryAgingSim.BatteryAging.update_capacity"]], "update_capacity() (charging_sim.batterypack.battery method)": [[2, "charging_sim.batterypack.Battery.update_capacity"]], "update_history() (charging_sim.solar.solar method)": [[2, "charging_sim.solar.Solar.update_history"]], "update_load() (charging_sim.chargingstation.chargingstation method)": [[2, "charging_sim.chargingStation.ChargingStation.update_load"]], "update_load_oneshot() (charging_sim.chargingstation.chargingstation method)": [[2, "charging_sim.chargingStation.ChargingStation.update_load_oneshot"]], "update_max_current() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.update_max_current"]], "update_max_current() (charging_sim.batterypack.battery method)": [[2, "charging_sim.batterypack.Battery.update_max_current"]], "update_params() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.update_params"]], "update_resistance() (charging_sim.batteryagingsim.batteryaging method)": [[2, "charging_sim.batteryAgingSim.BatteryAging.update_resistance"]], "update_scenario() (charging_sim.orchestrator.chargingsim method)": [[2, "charging_sim.orchestrator.ChargingSim.update_scenario"]], "update_status() (charging_sim.chargingstation.chargingstation method)": [[2, "charging_sim.chargingStation.ChargingStation.update_status"]], "update_steps() (charging_sim.orchestrator.chargingsim method)": [[2, "charging_sim.orchestrator.ChargingSim.update_steps"]], "update_voltage() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.update_voltage"]], "update_voltage() (charging_sim.batterypack.battery method)": [[2, "charging_sim.batterypack.Battery.update_voltage"]], "visualize() (charging_sim.battery.battery method)": [[2, "charging_sim.battery.Battery.visualize"]], "visualize() (charging_sim.batterypack.battery method)": [[2, "charging_sim.batterypack.Battery.visualize"]], "visualize() (charging_sim.chargingstation.chargingstation method)": [[2, "charging_sim.chargingStation.ChargingStation.visualize"]], "feeder_population": [[3, "module-feeder_population"]], "feeder_population.glm_mod_functions": [[3, "module-feeder_population.glm_mod_functions"]], "load_base_glm() (in module feeder_population.glm_mod_functions)": [[3, "feeder_population.glm_mod_functions.load_base_glm"]], "replace_load_w_meter() (in module feeder_population.glm_mod_functions)": [[3, "feeder_population.glm_mod_functions.replace_load_w_meter"]], "replace_load_w_meter_old() (in module feeder_population.glm_mod_functions)": [[3, "feeder_population.glm_mod_functions.replace_load_w_meter_old"]], "write_base_glm() (in module feeder_population.glm_mod_functions)": [[3, "feeder_population.glm_mod_functions.write_base_glm"]], "write_class_dict() (in module feeder_population.glm_mod_functions)": [[3, "feeder_population.glm_mod_functions.write_class_dict"]], "write_clock_dict() (in module feeder_population.glm_mod_functions)": [[3, "feeder_population.glm_mod_functions.write_clock_dict"]], "write_filter_dict() (in module feeder_population.glm_mod_functions)": [[3, "feeder_population.glm_mod_functions.write_filter_dict"]], "write_mod_dict() (in module feeder_population.glm_mod_functions)": [[3, "feeder_population.glm_mod_functions.write_mod_dict"]], "write_obj_dict() (in module feeder_population.glm_mod_functions)": [[3, "feeder_population.glm_mod_functions.write_obj_dict"]], "test_cases": [[7, "module-test_cases"]], "test_cases.base_case": [[8, "module-test_cases.base_case"]], "test_cases.battery": [[9, "module-test_cases.battery"]], "load_base_glm() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[10, "test_cases.battery.feeder_population.glm_mod_functions.load_base_glm"]], "replace_load_w_meter() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[10, "test_cases.battery.feeder_population.glm_mod_functions.replace_load_w_meter"]], "replace_load_w_meter_old() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[10, "test_cases.battery.feeder_population.glm_mod_functions.replace_load_w_meter_old"]], "test_cases.battery.feeder_population": [[10, "module-test_cases.battery.feeder_population"]], "test_cases.battery.feeder_population.glm_mod_functions": [[10, "module-test_cases.battery.feeder_population.glm_mod_functions"]], "write_base_glm() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[10, "test_cases.battery.feeder_population.glm_mod_functions.write_base_glm"]], "write_class_dict() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[10, "test_cases.battery.feeder_population.glm_mod_functions.write_class_dict"]], "write_clock_dict() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[10, "test_cases.battery.feeder_population.glm_mod_functions.write_clock_dict"]], "write_filter_dict() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[10, "test_cases.battery.feeder_population.glm_mod_functions.write_filter_dict"]], "write_mod_dict() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[10, "test_cases.battery.feeder_population.glm_mod_functions.write_mod_dict"]], "write_obj_dict() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[10, "test_cases.battery.feeder_population.glm_mod_functions.write_obj_dict"]]}}) \ No newline at end of file +Search.setIndex({"docnames": ["README", "analysis", "batt_sys_identification", "charging_sim", "feeder_population", "index", "modules", "readme", "test_cases", "test_cases.base_case", "test_cases.battery", "test_cases.battery.feeder_population"], "filenames": ["README.md", "analysis.rst", "batt_sys_identification.rst", "charging_sim.rst", "feeder_population.rst", "index.rst", "modules.rst", "readme.rst", "test_cases.rst", "test_cases.base_case.rst", "test_cases.battery.rst", "test_cases.battery.feeder_population.rst"], "titles": ["EV-Ecosim platform", "Post-simulation analysis", "Battery System Identification", "Charging simulator", "Feeder population", "Welcome to EV-Ecosim 1.0.0", "Packages", "Readme", "Test cases", "test_cases.base_case package", "test_cases.battery package", "test_cases.battery.feeder_population package"], "terms": {"A": [0, 1, 3], "grid": [0, 1, 3, 5], "awar": [0, 5], "design": [0, 3], "vehicl": [0, 3], "paper": [0, 2, 3], "http": [0, 1, 3], "doi": [0, 3], "org": [0, 3], "10": [0, 2, 3], "36227": [0, 3], "techrxiv": [0, 3], "23596725": [0, 3], "v2": [0, 3], "emmanuel": 0, "balogun": [0, 3], "ebalogun": 0, "stanford": 0, "edu": 0, "lili": 0, "buechler": 0, "ebuech": 0, "gismo": 0, "slac": 0, "gridlab": [0, 4, 5, 11], "d": [0, 4, 5, 11], "instal": [0, 3], "master": 0, "branch": 0, "github": [0, 5], "com": [0, 3], "arra": 0, "energi": [0, 3], "gridlabd": 0, "version": [0, 3, 5], "python": [0, 5], "recommend": 0, "aw": 0, "ec2": 0, "hipa": 0, "ami": 0, "beauharnoi": 0, "x": 0, "ambient": [0, 3], "_": 0, "data": [0, 1, 2, 3], "temperatur": [0, 3], "captur": 0, "effect": [0, 3], "environment": 0, "condit": 0, "subsystem": 0, "transform": [0, 1, 3], "base": [0, 1, 2, 3, 5, 11], "load": [0, 1, 2, 3, 4, 11], "includ": [0, 1, 2, 3, 5], "exist": [0, 3], "build": [0, 1, 3], "home": [0, 3], "usual": [0, 3], "uncontrol": 0, "within": [0, 1, 2, 3], "distribut": [0, 1, 3, 5], "work": [0, 2, 3], "proprietari": 0, "pecan": 0, "street": 0, "below": 0, "an": [0, 3], "exmapl": 0, "prototyp": 0, "note": [0, 3], "column": [0, 2], "field": [0, 2], "ar": [0, 1, 2, 3], "sensit": [0, 2], "The": [0, 1, 2, 3, 5], "origin": [0, 2], "ha": [0, 3], "minut": [0, 3], "resolut": [0, 3], "power": [0, 1, 3, 4, 5, 11], "system": [0, 1, 3, 4, 5, 6, 11], "batt": [0, 3], "sy": 0, "identif": [0, 3, 5, 6], "class": [0, 1, 2, 3, 4, 11], "gener": [0, 2, 3], "paramet": [0, 1, 2, 3, 4, 11], "from": [0, 1, 2, 3, 4], "experiment": 0, "leverag": 0, "genet": [0, 2], "algorithm": [0, 2], "model": [0, 2, 3, 4, 5, 11], "2nd": 0, "order": 0, "rc": 0, "equival": [0, 2], "circuit": [0, 2, 3], "ecm": [0, 2], "One": 0, "can": [0, 1, 2, 3], "custom": 0, "nmc": [0, 3], "upload": 0, "csv": [0, 2, 3], "file": [0, 1, 2, 3, 4, 11], "param": [0, 2, 3], "shown": [0, 5], "save": [0, 1, 3], "new": [0, 2, 3], "addit": 0, "correct": [0, 2, 3], "open": [0, 2, 3], "voltag": [0, 1, 2, 3], "ocv": [0, 2, 3], "valu": [0, 1, 2, 3], "label": [0, 1], "ocv_corr": 0, "abov": 0, "onc": [0, 3], "thei": [0, 2], "battery_data": 0, "config": [0, 3, 6], "json": [0, 3], "modifi": [0, 3, 4, 11], "so": [0, 3], "sim": [0, 3, 6, 8], "contain": [0, 1, 3, 5, 11], "which": [0, 1, 2, 3], "configur": [0, 3], "all": [0, 1, 2, 3, 4], "relev": [0, 3], "implement": [0, 1, 3], "physic": [0, 3], "legaci": 0, "forecast": [0, 3], "develop": [0, 5], "need": [0, 3], "elec": 0, "rate": [0, 3], "time": [0, 2, 3], "tou": [0, 3], "input": [0, 2, 3], "user": [0, 2, 3], "must": [0, 2, 3], "normal": [0, 1], "full": [0, 3], "year": [0, 3], "size": [0, 2], "365": 0, "dai": [0, 1, 3], "avoid": 0, "ani": [0, 2, 3], "error": [0, 2], "format": 0, "read": 0, "sampl": [0, 3], "dure": [0, 2, 3], "should": [0, 3], "one": [0, 2, 3], "15": [0, 3], "also": [0, 1, 3], "help": [0, 3], "downscal": [0, 3, 6], "much": [0, 3], "coarser": 0, "librari": [0, 3], "ieee": [0, 1], "test": [0, 2, 3, 5, 6], "pnnl": 0, "taxonomi": 0, "glm": [0, 4, 11], "have": [0, 2, 3, 5], "spot": 0, "specifi": [0, 3], "primari": 0, "level": [0, 1, 3], "secondari": [0, 3], "popul": [0, 2, 5, 6], "script": 0, "vari": 0, "resourc": [0, 1], "necessari": 0, "txt": [0, 3], "residenti": 0, "repo": 0, "limit": [0, 3], "access": [0, 3, 5], "irradi": [0, 3], "overal": [0, 1, 3], "default": [0, 2, 3], "nation": 0, "radiat": 0, "databas": 0, "nsrdb": 0, "san": 0, "francisco": 0, "bai": 0, "area": [0, 3], "renew": 0, "laboratori": 0, "nrel": [0, 1], "month": [0, 3], "index": [0, 3, 5], "1": [0, 2, 3], "12": [0, 1, 3], "inclus": [0, 2], "januari": 0, "decemb": [0, 3], "hourli": 0, "interv": 0, "oversampl": 0, "4": 0, "dataset": [0, 3], "ghi": [0, 3], "repres": 0, "global": [0, 3], "horizont": [0, 3], "w": 0, "m": 0, "2": [0, 2], "total": [0, 3], "amount": [0, 1], "shortwav": 0, "receiv": 0, "surfac": [0, 3], "ground": 0, "base_cas": [0, 6, 8], "write": [0, 2, 4, 11], "inject": [0, 3], "each": [0, 1, 3], "timestep": 0, "rlsf": 0, "plu": 0, "recurs": 0, "least": [0, 3], "squar": 0, "filter": [0, 4, 11], "estim": [0, 1, 3, 5], "network": [0, 1, 3, 5], "onlin": 0, "thermal": [0, 3], "integr": [0, 5], "plot": [0, 1, 2, 3], "result": [0, 1, 3], "calcul": [0, 1, 3], "impact": [0, 5], "plot_result": [0, 6], "pars": 0, "percentag": [0, 2], "violat": [0, 1], "per": [0, 2, 3], "ansi": 0, "c84": 0, "variabl": [0, 3], "string": [0, 3], "path": [0, 3], "where": [0, 3], "powerflow": 0, "output": [0, 3, 4], "node": [0, 1, 3], "load_post_opt_cost": [0, 6], "tabl": 0, "matric": 0, "respect": [0, 3], "cost_analysi": [0, 6], "costestim": [0, 1, 6], "differ": [0, 1, 3], "compon": [0, 1], "creat": [0, 1, 3], "environ": 0, "conda": 0, "env": 0, "name": [0, 3], "your": [0, 3], "f": [0, 3], "yml": 0, "OR": 0, "packag": [0, 5, 8], "list": [0, 1, 3, 4], "manual": 0, "ensur": [0, 2, 3], "follow": [0, 2, 3], "method": [0, 3], "For": 0, "navig": 0, "set": [0, 2, 3], "prepar": 0, "confirm": 0, "successfulli": 0, "ieee123_secondari": 0, "ieee123_popul": 0, "you": 0, "done": [0, 2, 3], "initi": [0, 3], "pre": [0, 2, 3], "prep": 0, "now": [0, 3], "out": [0, 3], "scenario": [0, 1, 3, 6, 8], "python3": 0, "ev50_cosimul": 0, "master_sim": [0, 6, 8], "pleas": [0, 2], "see": [0, 2], "section": 0, "more": [0, 2, 3], "detail": 0, "thi": [1, 2, 3, 5], "cost": [1, 3], "der": [1, 3], "simul": [2, 4, 5, 6, 11], "num_dai": 1, "sourc": [1, 2, 3, 4, 11], "object": [1, 2, 3, 4, 11], "i": [1, 2, 3, 5], "us": [1, 2, 3, 5], "asset": [1, 3], "ev": [1, 3], "ecosim": [1, 3], "number": [1, 2, 3], "run": [1, 2, 3, 5, 6], "calculate_battery_cost": [1, 6], "result_dir": 1, "batteri": [1, 5, 6, 8], "updat": [1, 2, 3], "lcoe": 1, "directori": 1, "dictionari": [1, 3, 4, 11], "return": [1, 2, 3, 4, 11], "dict": [1, 3, 4], "result_dict": 1, "calculate_electricity_cost_pgebev2": [1, 6], "pge_separate_fil": 1, "true": [1, 2, 3], "electr": [1, 3], "pgebev2": 1, "given": [1, 2, 3], "str": [1, 3], "compris": 1, "dollar": 1, "calculate_solar_cost": [1, 6], "pull": [1, 3], "solar": [1, 5, 6], "ref": [1, 3], "www": [1, 3], "gov": 1, "market": 1, "research": 1, "html": 1, "To": 1, "deprec": [1, 3], "soon": 1, "none": [1, 2, 3], "calculate_trans_loss_of_lif": [1, 6], "expect": 1, "loss": [1, 3], "life": [1, 3], "refer": 1, "5": 1, "11": 1, "3": [1, 2, 5], "std": 1, "c57": 1, "00": 1, "2010": 1, "minimum": [1, 3], "insul": 1, "180": 1, "000": 1, "hour": [1, 3], "static": [1, 3], "plot_load": [1, 6], "total_load": 1, "net_load": 1, "prefix": [1, 3], "overlai": 1, "net": [1, 3], "post": [3, 5, 6], "visual": [1, 3, 6], "demand": [1, 3], "control": [1, 6], "minu": 1, "buffer": 1, "legend": 1, "curv": 1, "plot_pow": [1, 6], "power_pr": 1, "predict": [1, 3], "plot_soc": [1, 6], "soc": [1, 2, 3], "soc_pr": 1, "state": [1, 2, 3], "charg": [1, 2, 5, 6], "solar_cost": [1, 6], "capit": 1, "Not": [1, 2, 3], "fulli": [1, 3], "locat": [1, 3], "pv": [1, 3], "transformer_cost": [1, 3, 6], "cannot": [1, 3], "find": [1, 2, 3], "good": 1, "yet": [1, 2, 3], "ag": [1, 3], "battery_typ": [3, 6], "instanti": [2, 3], "constraint": 3, "properti": 3, "mainli": 3, "max": 3, "c": 3, "determin": 3, "capac": 3, "cell": [2, 3], "multipl": 3, "v": 3, "maximum": 3, "allow": 3, "min": 3, "nomin": 3, "kwh": 3, "deliver": 3, "id": 3, "celsiu": 3, "type": 3, "inconsequenti": 3, "current": [2, 3], "dynam": [3, 6], "bu": 3, "resid": 3, "self": 3, "main": [3, 6], "attribut": [2, 3], "battery_setup": [3, 6], "up": 3, "seri": [2, 3], "parallel": 3, "scale": 3, "ah": 3, "setup": [3, 6], "fix": 3, "while": 3, "float": 3, "pack": 3, "wh": 3, "topologi": 3, "battery_setup_2": [3, 6], "instead": 3, "therebi": 3, "same": 3, "pack_max_ah": 3, "watt": 3, "amp": 3, "cell_amp_hr": 3, "cell_voltag": 3, "propag": 3, "forward": 3, "step": [3, 6], "It": [3, 5], "take": [2, 3], "amper": 3, "np": 3, "cycl": 3, "respons": [2, 3], "est_calendar_ag": [3, 6], "constant": 3, "calendar": 3, "sole": 3, "depend": 3, "later": 3, "linear": [2, 3], "est_cyc_ag": [3, 6], "hess": 3, "et": 3, "al": 3, "its": 3, "cvx": 3, "cvxpy": 3, "describ": [2, 3], "function": [3, 4, 11], "get_ocv": [3, 6], "map": 3, "store": 3, "via": [2, 3, 5], "interpol": 3, "obtain": 3, "priori": 3, "": 3, "get_ro": [2, 3, 6], "possibli": 3, "get_aging_valu": [3, 6], "experienc": 3, "far": 3, "get_power_profil": [3, 6], "profil": 3, "certain": 3, "get_properti": [3, 6], "get_roundtrip_effici": [3, 6], "get_total_ag": [3, 6], "get_true_pow": [3, 6], "save_sim_data": [3, 6], "save_prefix": 3, "over": [2, 3], "call": 3, "upon": 3, "conclus": 3, "desir": [2, 3], "folder": [2, 3], "save_st": [3, 6], "state_eqn": [3, 6], "append": 3, "discret": 3, "equat": 3, "here": 3, "g": 3, "l": 3, "plett": 3, "manag": 3, "volum": 3, "artech": 3, "hous": 3, "2015": 3, "vol": 3, "boolean": 3, "decid": 3, "track": 3, "b": 3, "analys": 3, "histori": 3, "vector": [2, 3], "thermal_dynam": [3, 6], "futur": 3, "track_soc": [3, 6], "update_soc": [3, 6], "update_capac": [3, 6], "anticip": 3, "update_max_curr": [3, 6], "verbos": 3, "fals": [2, 3], "update_param": [3, 6], "chang": 3, "update_voltag": [3, 6], "option": 3, "batteryag": [3, 6], "enact": 3, "resist": [2, 3], "datetim": 3, "num_step": 3, "re": 3, "linimncoo2": 3, "ad": 3, "link": [3, 5], "sciencedirect": 3, "scienc": 3, "articl": 3, "pii": 3, "s0378775314001876": 3, "beta_cap": 3, "fade": 3, "factor": 3, "alpha_cap": 3, "beta_r": 3, "growth": 3, "alpha_r": 3, "assumpt": 3, "homogen": 3, "uniform": 3, "across": 3, "vicin": 3, "lfp_cal_ag": [3, 6], "lfp_cyc_ag": [3, 6], "nmc_cal_ag": [3, 6], "nmc_cyc_ag": [3, 6], "get_calendar_ag": [3, 6], "tupl": 3, "due": 3, "get_cyc_ag": [3, 6], "THe": 3, "both": 3, "adopt": 3, "schmalsteig": 3, "update_resist": [3, 6], "program": 3, "usag": 3, "proper": 3, "py": 3, "exampl": 3, "battery_config_path": 3, "r": 3, "battery_config": 3, "params_list": 3, "kei": 3, "params_": 3, "Then": 3, "params_kei": 3, "actual": 3, "those": 3, "prior": 3, "loadtxt": 3, "path_prefix": 3, "constructor": 3, "buffer_batteri": 3, "r_pack": [3, 6], "sum": 3, "aging_c": 3, "lost": 3, "after": 3, "round": 3, "trip": 3, "effici": 3, "_eff": 3, "last": 3, "load_pack_prop": [3, 6], "dx": 3, "nominal_pack_cap": [3, 6], "meth": 3, "intern": 3, "avail": [3, 5], "defer": 3, "TO": 3, "BE": 3, "anymor": 3, "onli": 3, "right": 3, "behavior": 3, "inspect": 3, "end": 3, "host": [2, 3], "station": [3, 5], "storag": 3, "statu": 3, "idl": 3, "produc": 3, "reactiv": 3, "contribut": 3, "retain": 3, "inform": [3, 5], "etc": 3, "ingest": 3, "assign": 3, "get_current_load": [3, 6], "kw": 3, "is_ev_arriv": [3, 6], "is_charg": [3, 6], "set_current_load": [3, 6], "update_load": [3, 6], "net_grid_load": 3, "ev_load": 3, "mpc": [3, 6], "mode": 3, "update_load_oneshot": [3, 6], "offlin": 3, "non": [2, 3], "update_statu": [3, 6], "scheme": [2, 3], "bess": 3, "compute_control": [3, 6], "price_vector": 3, "action": 3, "comput": 3, "pass": 3, "control_act": 3, "signal": 3, "arbitrag": 3, "get_battery_constraint": [3, 6], "requir": 3, "satisfi": 3, "storage_constraint": 3, "initialize_forecast_data": [3, 6], "load_battery_ocv": [3, 6], "learn": 3, "reset_load": [3, 6], "oneshot": [3, 6], "96": 3, "feedback": 3, "price": 3, "structur": [3, 4, 11], "problem": 3, "pge_bev2_": [3, 6], "valid": 3, "california": 3, "howev": [2, 3], "own": 3, "numpi": 3, "arrai": 3, "priceload": [3, 6], "evs": 3, "profit": 3, "loader": 3, "first": 3, "repositori": 3, "input_r": 3, "output_r": 3, "finer": 3, "similar": 3, "panda": [2, 3], "typic": 3, "get_pric": [3, 6], "start_idx": 3, "7": [2, 3], "assum": 3, "do": 3, "int": 3, "start": 3, "cardin": 3, "being": [2, 3], "jan": 3, "ndarrai": 3, "set_month_data": [3, 6], "solv": 3, "objective_typ": 3, "power_demand": 3, "time_r": 3, "0": [2, 3], "solver": [3, 5], "gurobi": 3, "degrad": 3, "convex": 3, "mix": 3, "integ": 3, "select": [2, 3], "separ": 3, "pc": 3, "success": 3, "counter": 3, "identifi": 3, "backend": 3, "invok": 3, "eco": 3, "mosek": 3, "add_demand_charg": [3, 6], "aggregate_constraint": [3, 6], "aggreg": 3, "build_battery_cost": [3, 6], "build_emissions_cost": [3, 6], "emiss": 3, "build_transformer_cost": [3, 6], "get_constraint": [3, 6], "instanc": [2, 3, 4], "chargingsim": [3, 6], "entir": 3, "num_charging_sit": 3, "6": 3, "num_ev": 3, "1600": 3, "custom_ev_data": 3, "custom_ev_data_path": 3, "custom_solar_data": 3, "custom_solar_data_path": 3, "organ": 3, "other": 3, "sequenti": 3, "manner": 3, "bool": 3, "If": 3, "site": 3, "o": 3, "create_battery_object": [3, 6], "idx": 3, "node_prop": 3, "l2": 3, "dcfc": 3, "create_charging_st": [3, 6], "power_nod": 3, "buse": 3, "create_charging_stations_oneshot": [3, 6], "create_solar_object": [3, 6], "loc": 3, "get_act": [3, 6], "get_charger_obj_by_loc": [3, 6], "get_charging_sit": [3, 6], "initialize_aging_sim": [3, 6], "initialize_control": [3, 6], "initialize_price_load": [3, 6], "memori": 3, "initialize_solar_modul": [3, 6], "load_battery_param": [3, 6], "directli": 3, "unless": 3, "otherwis": 3, "load_config": [3, 6], "walk": 3, "through": 3, "them": 3, "load_results_summari": [3, 6], "save_path_prefix": 3, "some": [2, 3], "multistep": [3, 6], "faster": 3, "than": 3, "horizon": 3, "perfect": 3, "foresight": 3, "daili": 3, "reset": 3, "power_nodes_list": 3, "accordingli": 3, "specif": 3, "stepsiz": 3, "update_scenario": [3, 6], "match": 3, "update_step": [3, 6], "move": 3, "namepl": 3, "p_": 3, "eta": 3, "panel": 3, "make": 3, "decis": 3, "flow": [3, 5], "devic": 3, "get_pow": [3, 6], "desired_shap": 3, "get_solar_output": [3, 6], "modify_r": [3, 6], "new_r": 3, "update_histori": [3, 6], "purpos": 3, "mayb": 3, "schedul": 3, "pge": 3, "doc": 3, "found": 3, "add_power_profile_to_object": [3, 6], "battery_power_profil": 3, "build_cost_pge_bev2": [3, 6], "energy_prices_t": 3, "penalize_max_pow": 3, "max_power_pen": 3, "1000": 3, "heurist": 3, "averag": 3, "conserv": 3, "gamma": 3, "build_electricity_cost": [3, 6], "demand_charg": 3, "opt": 3, "build_object": [3, 6], "electricity_cost": 3, "battery_degradation_cost": 3, "we": [3, 5], "minim": 3, "load_pric": [3, 6], "time_interv": 3, "load_base_glm": [4, 6, 10, 11], "base_file_dir": [4, 11], "base_glm_fil": [4, 11], "replace_load_w_met": [4, 6, 10, 11], "glm_dict": [4, 11], "match_str": [4, 11], "rep_str": [4, 11], "obj_typ": [4, 11], "replac": [4, 11], "meter": [4, 11], "replace_load_w_meter_old": [4, 6, 10, 11], "write_base_glm": [4, 6, 10, 11], "globals_list": [4, 11], "include_list": [4, 11], "out_dir": [4, 11], "file_nam": [4, 11], "sync_list": [4, 11], "write_class_dict": [4, 6, 10, 11], "gld_dict": [4, 11], "class_nam": [4, 11], "correspond": [2, 4, 11], "gld": [4, 11], "write_clock_dict": [4, 6, 10, 11], "clock": [4, 11], "write_filter_dict": [4, 6, 10, 11], "write_mod_dict": [4, 6, 10, 11], "mod_nam": [4, 11], "write_obj_dict": [4, 6, 10, 11], "dict_kei": [4, 11], "co": 5, "platform": 5, "interfac": 5, "phase": 5, "unbalanc": 5, "fast": 5, "made": 5, "web": [2, 5], "tool": [2, 5], "public": 5, "most": 5, "code": 5, "document": [2, 5], "project": 5, "still": 5, "under": 5, "activ": 5, "improv": 5, "todo": 5, "tutori": 5, "analysi": [5, 6], "feeder": [5, 6], "case": [2, 5, 6], "readm": 5, "guid": [], "cite": [], "modul": [2, 5, 6], "search": [2, 5], "page": 5, "submodul": [6, 8], "content": 6, "charging_sim": 6, "batteryagingsim": 6, "batterypack": 6, "batterytest": 6, "capacitor": 6, "chargingst": 6, "electricitypric": 6, "optim": [2, 6], "orchestr": 6, "util": 6, "feeder_popul": [6, 8, 10], "glm_mod_funct": [6, 8, 10], "subpackag": 6, "test_cas": [6, 8], "event_handl": [6, 8], "gblvar": [6, 8], "glmptime": [6, 8], "voltdump2": [6, 8], "data_analysi": [6, 8], "event_handlers_oneshot": [6, 8], "parse_voltag": [6, 8], "feeder_population_old": [8, 10], "without": 3, "studi": 3, "character": 3, "what": 3, "would": 3, "occur": 3, "situ": 3, "wa": [2, 3], "make_scenario": [3, 6], "No": 3, "preload": 3, "reflect": 3, "run_scenario_singl": [3, 6], "singl": 3, "run_scenarios_parallel": [3, 6], "multiprocess": 3, "enough": 3, "core": 3, "ram": 3, "mai": [2, 3], "lead": 3, "process": 3, "freez": 3, "run_scenarios_sequenti": [3, 6], "combin": [2, 3], "fit": 2, "batt_sys_identif": 2, "battery_identif": 2, "batteryparam": [2, 6], "datafram": 2, "liter": 2, "how": 2, "pd": 2, "read_csv": 2, "data_path": 2, "run_sys_identif": [2, 6], "plot_correction_scheme_comparison": [2, 6], "download": 2, "ga": [2, 6], "num_gener": 2, "100": 2, "num_parents_m": 2, "sol_per_pop": 2, "num_gen": 2, "crossover_typ": 2, "single_point": 2, "mutation_typ": 2, "adapt": 2, "parent_selection_typ": 2, "sss": 2, "mutation_percent_gen": 2, "60": 2, "mutation_prob": 2, "crossover_prob": 2, "pygad": 2, "offici": 2, "explan": 2, "been": 2, "accuraci": 2, "speed": 2, "better": 2, "parent": 2, "form": 2, "next": 2, "offspr": 2, "solut": 2, "gene": 2, "cross": 2, "between": 2, "mate": 2, "mutat": 2, "undergo": 2, "probabl": 2, "appli": 2, "oper": 2, "Its": 2, "high": 2, "frequenc": 2, "ro": 2, "r_o": 2, "get_corrected_voltag": [2, 6], "get_uncorrected_voltag": [2, 6], "uncorrect": 2, "plot_ro": [2, 6], "xlim": 2, "20000": 2, "36000": 2, "ylim": 2, "75": 2, "85": 2, "run_ocv_correct": [2, 6], "use_quadrat": 2, "cell_nam": 2, "diagn": 2, "quadrat": 2, "run_pre_check": [2, 6], "check": 2, "length": 2, "begin": 2, "use_initial_pop": 2, "quadratic_bia": 2, "simulate_respons": [2, 6], "complet": 2}, "objects": {"": [[1, 0, 0, "-", "analysis"], [3, 0, 0, "-", "charging_sim"], [4, 0, 0, "-", "feeder_population"], [8, 0, 0, "-", "test_cases"]], "analysis": [[1, 0, 0, "-", "cost_analysis"]], "analysis.cost_analysis": [[1, 1, 1, "", "CostEstimator"]], "analysis.cost_analysis.CostEstimator": [[1, 2, 1, "", "calculate_battery_cost"], [1, 2, 1, "", "calculate_electricity_cost_PGEBEV2s"], [1, 2, 1, "", "calculate_solar_cost"], [1, 2, 1, "", "calculate_trans_loss_of_life"], [1, 2, 1, "", "plot_loads"], [1, 2, 1, "", "plot_power"], [1, 2, 1, "", "plot_soc"], [1, 2, 1, "", "solar_cost"], [1, 2, 1, "", "transformer_cost"]], "batt_sys_identification": [[2, 0, 0, "-", "battery_identification"]], "batt_sys_identification.battery_identification": [[2, 1, 1, "", "BatteryParams"]], "batt_sys_identification.battery_identification.BatteryParams": [[2, 2, 1, "", "ga"], [2, 2, 1, "", "get_Ro"], [2, 2, 1, "", "get_corrected_voltages"], [2, 2, 1, "", "get_uncorrected_voltages"], [2, 2, 1, "", "plot_Ro"], [2, 2, 1, "", "plot_correction_scheme_comparison"], [2, 2, 1, "", "run_ocv_correction"], [2, 2, 1, "", "run_pre_checks"], [2, 2, 1, "", "run_sys_identification"], [2, 2, 1, "", "simulate_response"]], "charging_sim": [[3, 0, 0, "-", "battery"], [3, 0, 0, "-", "batteryAgingSim"], [3, 0, 0, "-", "batterypack"], [3, 0, 0, "-", "capacitor"], [3, 0, 0, "-", "chargingStation"], [3, 0, 0, "-", "controller"], [3, 0, 0, "-", "electricityPrices"], [3, 0, 0, "-", "optimization"], [3, 0, 0, "-", "orchestrator"], [3, 0, 0, "-", "simulate"], [3, 0, 0, "-", "solar"], [3, 0, 0, "-", "utils"]], "charging_sim.battery": [[3, 1, 1, "", "Battery"], [3, 3, 1, "", "test"]], "charging_sim.battery.Battery": [[3, 2, 1, "", "battery_setup"], [3, 2, 1, "", "battery_setup_2"], [3, 2, 1, "", "dynamics"], [3, 2, 1, "", "est_calendar_aging"], [3, 2, 1, "", "est_cyc_aging"], [3, 2, 1, "", "get_OCV"], [3, 2, 1, "", "get_Ro"], [3, 2, 1, "", "get_aging_value"], [3, 2, 1, "", "get_power_profile"], [3, 2, 1, "", "get_properties"], [3, 2, 1, "", "get_roundtrip_efficiency"], [3, 2, 1, "", "get_total_aging"], [3, 2, 1, "", "get_true_power"], [3, 2, 1, "", "save_sim_data"], [3, 2, 1, "", "save_states"], [3, 2, 1, "", "state_eqn"], [3, 2, 1, "", "thermal_dynamics"], [3, 2, 1, "", "track_SOC"], [3, 2, 1, "", "update_SOC"], [3, 2, 1, "", "update_capacity"], [3, 2, 1, "", "update_max_current"], [3, 2, 1, "", "update_params"], [3, 2, 1, "", "update_voltage"], [3, 2, 1, "", "visualize"]], "charging_sim.batteryAgingSim": [[3, 1, 1, "", "BatteryAging"]], "charging_sim.batteryAgingSim.BatteryAging": [[3, 2, 1, "", "LFP_cal_aging"], [3, 2, 1, "", "LFP_cyc_aging"], [3, 2, 1, "", "NMC_cal_aging"], [3, 2, 1, "", "NMC_cyc_aging"], [3, 2, 1, "", "get_aging_value"], [3, 2, 1, "", "get_calendar_aging"], [3, 2, 1, "", "get_cyc_aging"], [3, 2, 1, "", "get_total_aging"], [3, 2, 1, "", "run"], [3, 2, 1, "", "update_capacity"], [3, 2, 1, "", "update_resistance"]], "charging_sim.batterypack": [[3, 1, 1, "", "Battery"], [3, 3, 1, "", "test"]], "charging_sim.batterypack.Battery": [[3, 4, 1, "", "R_pack"], [3, 2, 1, "", "battery_setup"], [3, 2, 1, "", "battery_setup_2"], [3, 4, 1, "", "battery_type"], [3, 4, 1, "", "config"], [3, 4, 1, "", "controller"], [3, 2, 1, "", "dynamics"], [3, 2, 1, "", "est_calendar_aging"], [3, 2, 1, "", "est_cyc_aging"], [3, 2, 1, "", "get_OCV"], [3, 2, 1, "", "get_aging_value"], [3, 2, 1, "", "get_power_profile"], [3, 2, 1, "", "get_roundtrip_efficiency"], [3, 2, 1, "", "get_total_aging"], [3, 2, 1, "", "get_true_power"], [3, 2, 1, "", "load_pack_props"], [3, 4, 1, "", "nominal_pack_cap"], [3, 2, 1, "", "save_sim_data"], [3, 2, 1, "", "state_eqn"], [3, 2, 1, "", "thermal_dynamics"], [3, 2, 1, "", "track_SOC"], [3, 2, 1, "", "update_capacity"], [3, 2, 1, "", "update_max_current"], [3, 2, 1, "", "update_voltage"], [3, 2, 1, "", "visualize"]], "charging_sim.capacitor": [[3, 1, 1, "", "Capacitor"]], "charging_sim.chargingStation": [[3, 1, 1, "", "ChargingStation"]], "charging_sim.chargingStation.ChargingStation": [[3, 2, 1, "", "get_current_load"], [3, 2, 1, "", "is_EV_arrived"], [3, 2, 1, "", "is_charging"], [3, 2, 1, "", "save_sim_data"], [3, 2, 1, "", "set_current_load"], [3, 2, 1, "", "update_load"], [3, 2, 1, "", "update_load_oneshot"], [3, 2, 1, "", "update_status"], [3, 2, 1, "", "visualize"]], "charging_sim.controller": [[3, 1, 1, "", "MPC"], [3, 1, 1, "", "Oneshot"]], "charging_sim.controller.MPC": [[3, 2, 1, "", "compute_control"], [3, 2, 1, "", "get_battery_constraints"], [3, 2, 1, "", "initialize_forecast_data"], [3, 2, 1, "", "load_battery_ocv"], [3, 2, 1, "", "reset_load"]], "charging_sim.controller.Oneshot": [[3, 2, 1, "", "compute_control"], [3, 2, 1, "", "get_battery_constraints"], [3, 2, 1, "", "load_battery_ocv"], [3, 2, 1, "", "reset_load"]], "charging_sim.electricityPrices": [[3, 1, 1, "", "PriceLoader"], [3, 3, 1, "", "main"]], "charging_sim.electricityPrices.PriceLoader": [[3, 2, 1, "", "downscale"], [3, 2, 1, "", "get_prices"], [3, 2, 1, "", "set_month_data"]], "charging_sim.optimization": [[3, 1, 1, "", "Optimization"]], "charging_sim.optimization.Optimization": [[3, 2, 1, "", "add_demand_charge"], [3, 2, 1, "", "aggregate_constraints"], [3, 2, 1, "", "build_battery_cost"], [3, 2, 1, "", "build_emissions_cost"], [3, 2, 1, "", "build_transformer_cost"], [3, 2, 1, "", "get_battery_constraint"], [3, 2, 1, "", "get_constraints"], [3, 2, 1, "", "run"]], "charging_sim.orchestrator": [[3, 1, 1, "", "ChargingSim"]], "charging_sim.orchestrator.ChargingSim": [[3, 2, 1, "", "create_battery_object"], [3, 2, 1, "", "create_charging_stations"], [3, 2, 1, "", "create_charging_stations_oneshot"], [3, 2, 1, "", "create_solar_object"], [3, 2, 1, "", "get_action"], [3, 2, 1, "", "get_charger_obj_by_loc"], [3, 2, 1, "", "get_charging_sites"], [3, 2, 1, "", "initialize_aging_sim"], [3, 2, 1, "", "initialize_controllers"], [3, 2, 1, "", "initialize_price_loader"], [3, 2, 1, "", "initialize_solar_module"], [3, 2, 1, "", "load_battery_params"], [3, 2, 1, "", "load_config"], [3, 2, 1, "", "load_results_summary"], [3, 2, 1, "", "multistep"], [3, 2, 1, "", "reset_loads"], [3, 2, 1, "", "setup"], [3, 2, 1, "", "step"], [3, 2, 1, "", "update_scenario"], [3, 2, 1, "", "update_steps"]], "charging_sim.simulate": [[3, 3, 1, "", "make_scenarios"], [3, 3, 1, "", "run"], [3, 3, 1, "", "run_scenario_single"], [3, 3, 1, "", "run_scenarios_parallel"], [3, 3, 1, "", "run_scenarios_sequential"]], "charging_sim.solar": [[3, 1, 1, "", "Solar"], [3, 3, 1, "", "main"]], "charging_sim.solar.Solar": [[3, 2, 1, "", "downscale"], [3, 2, 1, "", "get_constraints"], [3, 2, 1, "", "get_power"], [3, 2, 1, "", "get_solar_output"], [3, 2, 1, "", "modify_res"], [3, 2, 1, "", "update_history"]], "charging_sim.utils": [[3, 3, 1, "", "PGE_BEV2_S"], [3, 3, 1, "", "add_power_profile_to_object"], [3, 3, 1, "", "build_cost_PGE_BEV2S"], [3, 3, 1, "", "build_electricity_cost"], [3, 3, 1, "", "build_objective"], [3, 3, 1, "", "load_prices"]], "feeder_population": [[4, 0, 0, "-", "glm_mod_functions"]], "feeder_population.glm_mod_functions": [[4, 3, 1, "", "load_base_glm"], [4, 3, 1, "", "replace_load_w_meter"], [4, 3, 1, "", "replace_load_w_meter_old"], [4, 3, 1, "", "write_base_glm"], [4, 3, 1, "", "write_class_dict"], [4, 3, 1, "", "write_clock_dict"], [4, 3, 1, "", "write_filter_dict"], [4, 3, 1, "", "write_mod_dict"], [4, 3, 1, "", "write_obj_dict"]], "test_cases": [[9, 0, 0, "-", "base_case"], [10, 0, 0, "-", "battery"]], "test_cases.battery": [[11, 0, 0, "-", "feeder_population"]], "test_cases.battery.feeder_population": [[11, 0, 0, "-", "glm_mod_functions"]], "test_cases.battery.feeder_population.glm_mod_functions": [[11, 3, 1, "", "load_base_glm"], [11, 3, 1, "", "replace_load_w_meter"], [11, 3, 1, "", "replace_load_w_meter_old"], [11, 3, 1, "", "write_base_glm"], [11, 3, 1, "", "write_class_dict"], [11, 3, 1, "", "write_clock_dict"], [11, 3, 1, "", "write_filter_dict"], [11, 3, 1, "", "write_mod_dict"], [11, 3, 1, "", "write_obj_dict"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:method", "3": "py:function", "4": "py:attribute"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"], "3": ["py", "function", "Python function"], "4": ["py", "attribute", "Python attribute"]}, "titleterms": {"ev": [0, 5], "ecosim": [0, 5], "platform": 0, "author": 0, "requir": 0, "folder": 0, "descript": 0, "ambient_data": 0, "base_load_data": 0, "batt_sys_identif": 0, "charging_sim": [0, 3], "batteri": [0, 2, 3, 10, 11], "py": 0, "cell": 0, "modul": [0, 1, 3, 4, 8, 9, 10, 11], "batterypack": [0, 3], "pack": 0, "batteryagingsim": [0, 3], "ag": 0, "control": [0, 3], "chargingst": [0, 3], "charg": [0, 3], "station": 0, "electricitypric": [0, 3], "electr": 0, "price": 0, "optim": [0, 3], "orchestr": [0, 3], "simul": [0, 1, 3], "solar": [0, 3], "pv": 0, "util": [0, 3], "host": 0, "function": 0, "us": 0, "some": 0, "offlin": 0, "der": 0, "cost": 0, "minim": 0, "thi": 0, "i": 0, "run": 0, "mode": 0, "state": 0, "feedback": 0, "dlmodel": 0, "elec_r": 0, "feeder": [0, 4], "feeder_popul": [0, 4, 11], "solar_data": 0, "test_cas": [0, 9, 10, 11], "co": 0, "case": [0, 8], "analysi": [0, 1], "how": 0, "post": [0, 1], "packag": [6, 9, 10, 11], "submodul": [1, 2, 3, 4, 9, 10, 11], "cost_analysi": 1, "load_post_opt_cost": 1, "plot_result": 1, "content": [1, 3, 4, 5, 8, 9, 10, 11], "batterytest": 3, "capacitor": 3, "popul": 4, "glm_mod_funct": [4, 11], "welcom": 5, "1": 5, "0": 5, "indic": 5, "tabl": 5, "test": 8, "subpackag": [8, 10], "base_cas": 9, "event_handl": [9, 10], "gblvar": [9, 10], "glmptime": [9, 10], "master_sim": [9, 10], "sim": [9, 10], "voltdump2": [9, 10], "data_analysi": 10, "event_handlers_oneshot": 10, "parse_voltag": 10, "scenario": 10, "feeder_population_old": 11, "readm": 7, "system": 2, "identif": 2}, "envversion": {"sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.todo": 2, "sphinx.ext.viewcode": 1, "sphinx": 60}, "alltitles": {"Test cases": [[8, "test-cases"]], "Subpackages": [[8, "subpackages"], [10, "subpackages"]], "Module contents": [[8, "module-test_cases"], [1, "module-analysis"], [3, "module-charging_sim"], [4, "module-feeder_population"], [9, "module-test_cases.base_case"], [10, "module-test_cases.battery"], [11, "module-test_cases.battery.feeder_population"]], "Welcome to EV-Ecosim 1.0.0": [[5, "welcome-to-ev-ecosim-1-0-0"]], "Contents:": [[5, null]], "Indices and tables": [[5, "indices-and-tables"]], "Readme": [[7, "readme"]], "Submodules": [[2, "submodules"], [1, "submodules"], [3, "submodules"], [4, "submodules"], [9, "submodules"], [10, "submodules"], [11, "submodules"]], "Battery System Identification": [[2, "battery-system-identification"]], "Battery system identification": [[2, "id1"]], "EV-Ecosim platform": [[0, "ev-ecosim-platform"]], "Authors": [[0, "authors"]], "Requirements": [[0, "requirements"]], "Folder descriptions": [[0, "folder-descriptions"]], "ambient_data": [[0, "ambient-data"]], "base_load_data": [[0, "base-load-data"]], "batt_sys_identification": [[0, "batt-sys-identification"]], "charging_sim": [[0, "charging-sim"]], "battery.py - Battery cell module.": [[0, "battery-py-battery-cell-module"]], "batterypack.py - Battery pack module.": [[0, "batterypack-py-battery-pack-module"]], "batteryAgingSim.py - Battery aging module.": [[0, "batteryagingsim-py-battery-aging-module"]], "controller.py - Controller module.": [[0, "controller-py-controller-module"]], "chargingStation.py - Charging station module.": [[0, "chargingstation-py-charging-station-module"]], "electricityPrices.py - Electricity prices module.": [[0, "electricityprices-py-electricity-prices-module"]], "optimization.py - Optimization module.": [[0, "optimization-py-optimization-module"]], "orchestrator.py - Simulation orchestrator module.": [[0, "orchestrator-py-simulation-orchestrator-module"]], "solar.py - Solar PV module.": [[0, "solar-py-solar-pv-module"]], "utils.py - Hosts utility functions used by some modules.": [[0, "utils-py-hosts-utility-functions-used-by-some-modules"]], "simulate.py - Offline DER control optimization for cost minimization (this is run for offline mode (no state feedback)).": [[0, "simulate-py-offline-der-control-optimization-for-cost-minimization-this-is-run-for-offline-mode-no-state-feedback"]], "DLMODELS": [[0, "dlmodels"]], "elec_rates": [[0, "elec-rates"]], "feeders": [[0, "feeders"]], "feeder_population": [[0, "feeder-population"]], "solar_data": [[0, "solar-data"]], "test_cases": [[0, "test-cases"]], "Co-simulation cases.": [[0, "co-simulation-cases"]], "analysis": [[0, "analysis"]], "How to run": [[0, "how-to-run"]], "Post-simulation analysis": [[0, "post-simulation-analysis"], [1, "post-simulation-analysis"]], "cost_analysis module": [[1, "module-analysis.cost_analysis"]], "load_post_opt_costs module": [[1, "load-post-opt-costs-module"]], "plot_results module": [[1, "plot-results-module"]], "Charging simulator": [[3, "charging-simulator"]], "charging_sim.battery module": [[3, "module-charging_sim.battery"]], "charging_sim.batteryAgingSim module": [[3, "module-charging_sim.batteryAgingSim"]], "charging_sim.batterypack module": [[3, "module-charging_sim.batterypack"]], "charging_sim.batterytest module": [[3, "charging-sim-batterytest-module"]], "charging_sim.capacitor module": [[3, "module-charging_sim.capacitor"]], "charging_sim.chargingStation module": [[3, "module-charging_sim.chargingStation"]], "charging_sim.controller module": [[3, "module-charging_sim.controller"]], "charging_sim.electricityPrices module": [[3, "module-charging_sim.electricityPrices"]], "charging_sim.optimization module": [[3, "module-charging_sim.optimization"]], "charging_sim.orchestrator module": [[3, "module-charging_sim.orchestrator"]], "charging_sim.simulate module": [[3, "module-charging_sim.simulate"]], "charging_sim.solar module": [[3, "module-charging_sim.solar"]], "charging_sim.utils module": [[3, "module-charging_sim.utils"]], "Feeder population": [[4, "feeder-population"]], "feeder_population.feeder_population module": [[4, "feeder-population-feeder-population-module"]], "feeder_population.glm_mod_functions module": [[4, "module-feeder_population.glm_mod_functions"]], "Packages": [[6, "packages"]], "test_cases.base_case package": [[9, "test-cases-base-case-package"]], "test_cases.base_case.event_handlers module": [[9, "test-cases-base-case-event-handlers-module"]], "test_cases.base_case.gblvar module": [[9, "test-cases-base-case-gblvar-module"]], "test_cases.base_case.glmptime module": [[9, "test-cases-base-case-glmptime-module"]], "test_cases.base_case.master_sim module": [[9, "test-cases-base-case-master-sim-module"]], "test_cases.base_case.sim module": [[9, "test-cases-base-case-sim-module"]], "test_cases.base_case.voltdump2 module": [[9, "test-cases-base-case-voltdump2-module"]], "test_cases.battery package": [[10, "test-cases-battery-package"]], "test_cases.battery.data_analysis module": [[10, "test-cases-battery-data-analysis-module"]], "test_cases.battery.event_handlers module": [[10, "test-cases-battery-event-handlers-module"]], "test_cases.battery.event_handlers_oneshot module": [[10, "test-cases-battery-event-handlers-oneshot-module"]], "test_cases.battery.gblvar module": [[10, "test-cases-battery-gblvar-module"]], "test_cases.battery.glmptime module": [[10, "test-cases-battery-glmptime-module"]], "test_cases.battery.master_sim module": [[10, "test-cases-battery-master-sim-module"]], "test_cases.battery.parse_voltages module": [[10, "test-cases-battery-parse-voltages-module"]], "test_cases.battery.scenarios module": [[10, "test-cases-battery-scenarios-module"]], "test_cases.battery.sim module": [[10, "test-cases-battery-sim-module"]], "test_cases.battery.voltdump2 module": [[10, "test-cases-battery-voltdump2-module"]], "test_cases.battery.feeder_population package": [[11, "test-cases-battery-feeder-population-package"]], "test_cases.battery.feeder_population.feeder_population module": [[11, "test-cases-battery-feeder-population-feeder-population-module"]], "test_cases.battery.feeder_population.feeder_population_old module": [[11, "test-cases-battery-feeder-population-feeder-population-old-module"]], "test_cases.battery.feeder_population.glm_mod_functions module": [[11, "module-test_cases.battery.feeder_population.glm_mod_functions"]]}, "indexentries": {"costestimator (class in analysis.cost_analysis)": [[1, "analysis.cost_analysis.CostEstimator"]], "analysis": [[1, "module-analysis"]], "analysis.cost_analysis": [[1, "module-analysis.cost_analysis"]], "calculate_battery_cost() (analysis.cost_analysis.costestimator method)": [[1, "analysis.cost_analysis.CostEstimator.calculate_battery_cost"]], "calculate_electricity_cost_pgebev2s() (analysis.cost_analysis.costestimator method)": [[1, "analysis.cost_analysis.CostEstimator.calculate_electricity_cost_PGEBEV2s"]], "calculate_solar_cost() (analysis.cost_analysis.costestimator method)": [[1, "analysis.cost_analysis.CostEstimator.calculate_solar_cost"]], "calculate_trans_loss_of_life() (analysis.cost_analysis.costestimator method)": [[1, "analysis.cost_analysis.CostEstimator.calculate_trans_loss_of_life"]], "module": [[1, "module-analysis"], [1, "module-analysis.cost_analysis"], [3, "module-charging_sim"], [3, "module-charging_sim.battery"], [3, "module-charging_sim.batteryAgingSim"], [3, "module-charging_sim.batterypack"], [3, "module-charging_sim.capacitor"], [3, "module-charging_sim.chargingStation"], [3, "module-charging_sim.controller"], [3, "module-charging_sim.electricityPrices"], [3, "module-charging_sim.optimization"], [3, "module-charging_sim.orchestrator"], [3, "module-charging_sim.simulate"], [3, "module-charging_sim.solar"], [3, "module-charging_sim.utils"], [4, "module-feeder_population"], [4, "module-feeder_population.glm_mod_functions"], [8, "module-test_cases"], [9, "module-test_cases.base_case"], [10, "module-test_cases.battery"], [11, "module-test_cases.battery.feeder_population"], [11, "module-test_cases.battery.feeder_population.glm_mod_functions"]], "plot_loads() (analysis.cost_analysis.costestimator static method)": [[1, "analysis.cost_analysis.CostEstimator.plot_loads"]], "plot_power() (analysis.cost_analysis.costestimator static method)": [[1, "analysis.cost_analysis.CostEstimator.plot_power"]], "plot_soc() (analysis.cost_analysis.costestimator static method)": [[1, "analysis.cost_analysis.CostEstimator.plot_soc"]], "solar_cost() (analysis.cost_analysis.costestimator method)": [[1, "analysis.cost_analysis.CostEstimator.solar_cost"]], "transformer_cost() (analysis.cost_analysis.costestimator method)": [[1, "analysis.cost_analysis.CostEstimator.transformer_cost"]], "battery (class in charging_sim.battery)": [[3, "charging_sim.battery.Battery"]], "battery (class in charging_sim.batterypack)": [[3, "charging_sim.batterypack.Battery"]], "batteryaging (class in charging_sim.batteryagingsim)": [[3, "charging_sim.batteryAgingSim.BatteryAging"]], "capacitor (class in charging_sim.capacitor)": [[3, "charging_sim.capacitor.Capacitor"]], "chargingsim (class in charging_sim.orchestrator)": [[3, "charging_sim.orchestrator.ChargingSim"]], "chargingstation (class in charging_sim.chargingstation)": [[3, "charging_sim.chargingStation.ChargingStation"]], "lfp_cal_aging() (charging_sim.batteryagingsim.batteryaging static method)": [[3, "charging_sim.batteryAgingSim.BatteryAging.LFP_cal_aging"]], "lfp_cyc_aging() (charging_sim.batteryagingsim.batteryaging static method)": [[3, "charging_sim.batteryAgingSim.BatteryAging.LFP_cyc_aging"]], "mpc (class in charging_sim.controller)": [[3, "charging_sim.controller.MPC"]], "nmc_cal_aging() (charging_sim.batteryagingsim.batteryaging static method)": [[3, "charging_sim.batteryAgingSim.BatteryAging.NMC_cal_aging"]], "nmc_cyc_aging() (charging_sim.batteryagingsim.batteryaging static method)": [[3, "charging_sim.batteryAgingSim.BatteryAging.NMC_cyc_aging"]], "oneshot (class in charging_sim.controller)": [[3, "charging_sim.controller.Oneshot"]], "optimization (class in charging_sim.optimization)": [[3, "charging_sim.optimization.Optimization"]], "pge_bev2_s() (in module charging_sim.utils)": [[3, "charging_sim.utils.PGE_BEV2_S"]], "priceloader (class in charging_sim.electricityprices)": [[3, "charging_sim.electricityPrices.PriceLoader"]], "r_pack (charging_sim.batterypack.battery attribute)": [[3, "charging_sim.batterypack.Battery.R_pack"]], "solar (class in charging_sim.solar)": [[3, "charging_sim.solar.Solar"]], "add_demand_charge() (charging_sim.optimization.optimization method)": [[3, "charging_sim.optimization.Optimization.add_demand_charge"]], "add_power_profile_to_object() (in module charging_sim.utils)": [[3, "charging_sim.utils.add_power_profile_to_object"]], "aggregate_constraints() (charging_sim.optimization.optimization method)": [[3, "charging_sim.optimization.Optimization.aggregate_constraints"]], "battery_setup() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.battery_setup"]], "battery_setup() (charging_sim.batterypack.battery method)": [[3, "charging_sim.batterypack.Battery.battery_setup"]], "battery_setup_2() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.battery_setup_2"]], "battery_setup_2() (charging_sim.batterypack.battery method)": [[3, "charging_sim.batterypack.Battery.battery_setup_2"]], "battery_type (charging_sim.batterypack.battery attribute)": [[3, "charging_sim.batterypack.Battery.battery_type"]], "build_battery_cost() (charging_sim.optimization.optimization method)": [[3, "charging_sim.optimization.Optimization.build_battery_cost"]], "build_cost_pge_bev2s() (in module charging_sim.utils)": [[3, "charging_sim.utils.build_cost_PGE_BEV2S"]], "build_electricity_cost() (in module charging_sim.utils)": [[3, "charging_sim.utils.build_electricity_cost"]], "build_emissions_cost() (charging_sim.optimization.optimization method)": [[3, "charging_sim.optimization.Optimization.build_emissions_cost"]], "build_objective() (in module charging_sim.utils)": [[3, "charging_sim.utils.build_objective"]], "build_transformer_cost() (charging_sim.optimization.optimization method)": [[3, "charging_sim.optimization.Optimization.build_transformer_cost"]], "charging_sim": [[3, "module-charging_sim"]], "charging_sim.battery": [[3, "module-charging_sim.battery"]], "charging_sim.batteryagingsim": [[3, "module-charging_sim.batteryAgingSim"]], "charging_sim.batterypack": [[3, "module-charging_sim.batterypack"]], "charging_sim.capacitor": [[3, "module-charging_sim.capacitor"]], "charging_sim.chargingstation": [[3, "module-charging_sim.chargingStation"]], "charging_sim.controller": [[3, "module-charging_sim.controller"]], "charging_sim.electricityprices": [[3, "module-charging_sim.electricityPrices"]], "charging_sim.optimization": [[3, "module-charging_sim.optimization"]], "charging_sim.orchestrator": [[3, "module-charging_sim.orchestrator"]], "charging_sim.simulate": [[3, "module-charging_sim.simulate"]], "charging_sim.solar": [[3, "module-charging_sim.solar"]], "charging_sim.utils": [[3, "module-charging_sim.utils"]], "compute_control() (charging_sim.controller.mpc method)": [[3, "charging_sim.controller.MPC.compute_control"]], "compute_control() (charging_sim.controller.oneshot method)": [[3, "charging_sim.controller.Oneshot.compute_control"]], "config (charging_sim.batterypack.battery attribute)": [[3, "charging_sim.batterypack.Battery.config"]], "controller (charging_sim.batterypack.battery attribute)": [[3, "charging_sim.batterypack.Battery.controller"]], "create_battery_object() (charging_sim.orchestrator.chargingsim method)": [[3, "charging_sim.orchestrator.ChargingSim.create_battery_object"]], "create_charging_stations() (charging_sim.orchestrator.chargingsim method)": [[3, "charging_sim.orchestrator.ChargingSim.create_charging_stations"]], "create_charging_stations_oneshot() (charging_sim.orchestrator.chargingsim method)": [[3, "charging_sim.orchestrator.ChargingSim.create_charging_stations_oneshot"]], "create_solar_object() (charging_sim.orchestrator.chargingsim method)": [[3, "charging_sim.orchestrator.ChargingSim.create_solar_object"]], "downscale() (charging_sim.electricityprices.priceloader method)": [[3, "charging_sim.electricityPrices.PriceLoader.downscale"]], "downscale() (charging_sim.solar.solar method)": [[3, "charging_sim.solar.Solar.downscale"]], "dynamics() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.dynamics"]], "dynamics() (charging_sim.batterypack.battery method)": [[3, "charging_sim.batterypack.Battery.dynamics"]], "est_calendar_aging() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.est_calendar_aging"]], "est_calendar_aging() (charging_sim.batterypack.battery method)": [[3, "charging_sim.batterypack.Battery.est_calendar_aging"]], "est_cyc_aging() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.est_cyc_aging"]], "est_cyc_aging() (charging_sim.batterypack.battery method)": [[3, "charging_sim.batterypack.Battery.est_cyc_aging"]], "get_ocv() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.get_OCV"]], "get_ocv() (charging_sim.batterypack.battery method)": [[3, "charging_sim.batterypack.Battery.get_OCV"]], "get_ro() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.get_Ro"]], "get_action() (charging_sim.orchestrator.chargingsim static method)": [[3, "charging_sim.orchestrator.ChargingSim.get_action"]], "get_aging_value() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.get_aging_value"]], "get_aging_value() (charging_sim.batteryagingsim.batteryaging method)": [[3, "charging_sim.batteryAgingSim.BatteryAging.get_aging_value"]], "get_aging_value() (charging_sim.batterypack.battery method)": [[3, "charging_sim.batterypack.Battery.get_aging_value"]], "get_battery_constraint() (charging_sim.optimization.optimization method)": [[3, "charging_sim.optimization.Optimization.get_battery_constraint"]], "get_battery_constraints() (charging_sim.controller.mpc method)": [[3, "charging_sim.controller.MPC.get_battery_constraints"]], "get_battery_constraints() (charging_sim.controller.oneshot method)": [[3, "charging_sim.controller.Oneshot.get_battery_constraints"]], "get_calendar_aging() (charging_sim.batteryagingsim.batteryaging method)": [[3, "charging_sim.batteryAgingSim.BatteryAging.get_calendar_aging"]], "get_charger_obj_by_loc() (charging_sim.orchestrator.chargingsim method)": [[3, "charging_sim.orchestrator.ChargingSim.get_charger_obj_by_loc"]], "get_charging_sites() (charging_sim.orchestrator.chargingsim method)": [[3, "charging_sim.orchestrator.ChargingSim.get_charging_sites"]], "get_constraints() (charging_sim.optimization.optimization method)": [[3, "charging_sim.optimization.Optimization.get_constraints"]], "get_constraints() (charging_sim.solar.solar method)": [[3, "charging_sim.solar.Solar.get_constraints"]], "get_current_load() (charging_sim.chargingstation.chargingstation method)": [[3, "charging_sim.chargingStation.ChargingStation.get_current_load"]], "get_cyc_aging() (charging_sim.batteryagingsim.batteryaging method)": [[3, "charging_sim.batteryAgingSim.BatteryAging.get_cyc_aging"]], "get_power() (charging_sim.solar.solar method)": [[3, "charging_sim.solar.Solar.get_power"]], "get_power_profile() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.get_power_profile"]], "get_power_profile() (charging_sim.batterypack.battery method)": [[3, "charging_sim.batterypack.Battery.get_power_profile"]], "get_prices() (charging_sim.electricityprices.priceloader method)": [[3, "charging_sim.electricityPrices.PriceLoader.get_prices"]], "get_properties() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.get_properties"]], "get_roundtrip_efficiency() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.get_roundtrip_efficiency"]], "get_roundtrip_efficiency() (charging_sim.batterypack.battery method)": [[3, "charging_sim.batterypack.Battery.get_roundtrip_efficiency"]], "get_solar_output() (charging_sim.solar.solar method)": [[3, "charging_sim.solar.Solar.get_solar_output"]], "get_total_aging() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.get_total_aging"]], "get_total_aging() (charging_sim.batteryagingsim.batteryaging method)": [[3, "charging_sim.batteryAgingSim.BatteryAging.get_total_aging"]], "get_total_aging() (charging_sim.batterypack.battery method)": [[3, "charging_sim.batterypack.Battery.get_total_aging"]], "get_true_power() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.get_true_power"]], "get_true_power() (charging_sim.batterypack.battery method)": [[3, "charging_sim.batterypack.Battery.get_true_power"]], "initialize_aging_sim() (charging_sim.orchestrator.chargingsim method)": [[3, "charging_sim.orchestrator.ChargingSim.initialize_aging_sim"]], "initialize_controllers() (charging_sim.orchestrator.chargingsim method)": [[3, "charging_sim.orchestrator.ChargingSim.initialize_controllers"]], "initialize_forecast_data() (charging_sim.controller.mpc method)": [[3, "charging_sim.controller.MPC.initialize_forecast_data"]], "initialize_price_loader() (charging_sim.orchestrator.chargingsim method)": [[3, "charging_sim.orchestrator.ChargingSim.initialize_price_loader"]], "initialize_solar_module() (charging_sim.orchestrator.chargingsim method)": [[3, "charging_sim.orchestrator.ChargingSim.initialize_solar_module"]], "is_ev_arrived() (charging_sim.chargingstation.chargingstation method)": [[3, "charging_sim.chargingStation.ChargingStation.is_EV_arrived"]], "is_charging() (charging_sim.chargingstation.chargingstation method)": [[3, "charging_sim.chargingStation.ChargingStation.is_charging"]], "load_battery_ocv() (charging_sim.controller.mpc method)": [[3, "charging_sim.controller.MPC.load_battery_ocv"]], "load_battery_ocv() (charging_sim.controller.oneshot method)": [[3, "charging_sim.controller.Oneshot.load_battery_ocv"]], "load_battery_params() (charging_sim.orchestrator.chargingsim method)": [[3, "charging_sim.orchestrator.ChargingSim.load_battery_params"]], "load_config() (charging_sim.orchestrator.chargingsim method)": [[3, "charging_sim.orchestrator.ChargingSim.load_config"]], "load_pack_props() (charging_sim.batterypack.battery method)": [[3, "charging_sim.batterypack.Battery.load_pack_props"]], "load_prices() (in module charging_sim.utils)": [[3, "charging_sim.utils.load_prices"]], "load_results_summary() (charging_sim.orchestrator.chargingsim method)": [[3, "charging_sim.orchestrator.ChargingSim.load_results_summary"]], "main() (in module charging_sim.electricityprices)": [[3, "charging_sim.electricityPrices.main"]], "main() (in module charging_sim.solar)": [[3, "charging_sim.solar.main"]], "make_scenarios() (in module charging_sim.simulate)": [[3, "charging_sim.simulate.make_scenarios"]], "modify_res() (charging_sim.solar.solar method)": [[3, "charging_sim.solar.Solar.modify_res"]], "multistep() (charging_sim.orchestrator.chargingsim method)": [[3, "charging_sim.orchestrator.ChargingSim.multistep"]], "nominal_pack_cap (charging_sim.batterypack.battery attribute)": [[3, "charging_sim.batterypack.Battery.nominal_pack_cap"]], "reset_load() (charging_sim.controller.mpc method)": [[3, "charging_sim.controller.MPC.reset_load"]], "reset_load() (charging_sim.controller.oneshot method)": [[3, "charging_sim.controller.Oneshot.reset_load"]], "reset_loads() (charging_sim.orchestrator.chargingsim method)": [[3, "charging_sim.orchestrator.ChargingSim.reset_loads"]], "run() (charging_sim.batteryagingsim.batteryaging method)": [[3, "charging_sim.batteryAgingSim.BatteryAging.run"]], "run() (charging_sim.optimization.optimization method)": [[3, "charging_sim.optimization.Optimization.run"]], "run() (in module charging_sim.simulate)": [[3, "charging_sim.simulate.run"]], "run_scenario_single() (in module charging_sim.simulate)": [[3, "charging_sim.simulate.run_scenario_single"]], "run_scenarios_parallel() (in module charging_sim.simulate)": [[3, "charging_sim.simulate.run_scenarios_parallel"]], "run_scenarios_sequential() (in module charging_sim.simulate)": [[3, "charging_sim.simulate.run_scenarios_sequential"]], "save_sim_data() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.save_sim_data"]], "save_sim_data() (charging_sim.batterypack.battery method)": [[3, "charging_sim.batterypack.Battery.save_sim_data"]], "save_sim_data() (charging_sim.chargingstation.chargingstation method)": [[3, "charging_sim.chargingStation.ChargingStation.save_sim_data"]], "save_states() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.save_states"]], "set_current_load() (charging_sim.chargingstation.chargingstation method)": [[3, "charging_sim.chargingStation.ChargingStation.set_current_load"]], "set_month_data() (charging_sim.electricityprices.priceloader method)": [[3, "charging_sim.electricityPrices.PriceLoader.set_month_data"]], "setup() (charging_sim.orchestrator.chargingsim method)": [[3, "charging_sim.orchestrator.ChargingSim.setup"]], "state_eqn() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.state_eqn"]], "state_eqn() (charging_sim.batterypack.battery method)": [[3, "charging_sim.batterypack.Battery.state_eqn"]], "step() (charging_sim.orchestrator.chargingsim method)": [[3, "charging_sim.orchestrator.ChargingSim.step"]], "test() (in module charging_sim.battery)": [[3, "charging_sim.battery.test"]], "test() (in module charging_sim.batterypack)": [[3, "charging_sim.batterypack.test"]], "thermal_dynamics() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.thermal_dynamics"]], "thermal_dynamics() (charging_sim.batterypack.battery method)": [[3, "charging_sim.batterypack.Battery.thermal_dynamics"]], "track_soc() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.track_SOC"]], "track_soc() (charging_sim.batterypack.battery method)": [[3, "charging_sim.batterypack.Battery.track_SOC"]], "update_soc() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.update_SOC"]], "update_capacity() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.update_capacity"]], "update_capacity() (charging_sim.batteryagingsim.batteryaging method)": [[3, "charging_sim.batteryAgingSim.BatteryAging.update_capacity"]], "update_capacity() (charging_sim.batterypack.battery method)": [[3, "charging_sim.batterypack.Battery.update_capacity"]], "update_history() (charging_sim.solar.solar method)": [[3, "charging_sim.solar.Solar.update_history"]], "update_load() (charging_sim.chargingstation.chargingstation method)": [[3, "charging_sim.chargingStation.ChargingStation.update_load"]], "update_load_oneshot() (charging_sim.chargingstation.chargingstation method)": [[3, "charging_sim.chargingStation.ChargingStation.update_load_oneshot"]], "update_max_current() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.update_max_current"]], "update_max_current() (charging_sim.batterypack.battery method)": [[3, "charging_sim.batterypack.Battery.update_max_current"]], "update_params() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.update_params"]], "update_resistance() (charging_sim.batteryagingsim.batteryaging method)": [[3, "charging_sim.batteryAgingSim.BatteryAging.update_resistance"]], "update_scenario() (charging_sim.orchestrator.chargingsim method)": [[3, "charging_sim.orchestrator.ChargingSim.update_scenario"]], "update_status() (charging_sim.chargingstation.chargingstation method)": [[3, "charging_sim.chargingStation.ChargingStation.update_status"]], "update_steps() (charging_sim.orchestrator.chargingsim method)": [[3, "charging_sim.orchestrator.ChargingSim.update_steps"]], "update_voltage() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.update_voltage"]], "update_voltage() (charging_sim.batterypack.battery method)": [[3, "charging_sim.batterypack.Battery.update_voltage"]], "visualize() (charging_sim.battery.battery method)": [[3, "charging_sim.battery.Battery.visualize"]], "visualize() (charging_sim.batterypack.battery method)": [[3, "charging_sim.batterypack.Battery.visualize"]], "visualize() (charging_sim.chargingstation.chargingstation method)": [[3, "charging_sim.chargingStation.ChargingStation.visualize"]], "feeder_population": [[4, "module-feeder_population"]], "feeder_population.glm_mod_functions": [[4, "module-feeder_population.glm_mod_functions"]], "load_base_glm() (in module feeder_population.glm_mod_functions)": [[4, "feeder_population.glm_mod_functions.load_base_glm"]], "replace_load_w_meter() (in module feeder_population.glm_mod_functions)": [[4, "feeder_population.glm_mod_functions.replace_load_w_meter"]], "replace_load_w_meter_old() (in module feeder_population.glm_mod_functions)": [[4, "feeder_population.glm_mod_functions.replace_load_w_meter_old"]], "write_base_glm() (in module feeder_population.glm_mod_functions)": [[4, "feeder_population.glm_mod_functions.write_base_glm"]], "write_class_dict() (in module feeder_population.glm_mod_functions)": [[4, "feeder_population.glm_mod_functions.write_class_dict"]], "write_clock_dict() (in module feeder_population.glm_mod_functions)": [[4, "feeder_population.glm_mod_functions.write_clock_dict"]], "write_filter_dict() (in module feeder_population.glm_mod_functions)": [[4, "feeder_population.glm_mod_functions.write_filter_dict"]], "write_mod_dict() (in module feeder_population.glm_mod_functions)": [[4, "feeder_population.glm_mod_functions.write_mod_dict"]], "write_obj_dict() (in module feeder_population.glm_mod_functions)": [[4, "feeder_population.glm_mod_functions.write_obj_dict"]], "test_cases": [[8, "module-test_cases"]], "test_cases.base_case": [[9, "module-test_cases.base_case"]], "test_cases.battery": [[10, "module-test_cases.battery"]], "load_base_glm() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[11, "test_cases.battery.feeder_population.glm_mod_functions.load_base_glm"]], "replace_load_w_meter() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[11, "test_cases.battery.feeder_population.glm_mod_functions.replace_load_w_meter"]], "replace_load_w_meter_old() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[11, "test_cases.battery.feeder_population.glm_mod_functions.replace_load_w_meter_old"]], "test_cases.battery.feeder_population": [[11, "module-test_cases.battery.feeder_population"]], "test_cases.battery.feeder_population.glm_mod_functions": [[11, "module-test_cases.battery.feeder_population.glm_mod_functions"]], "write_base_glm() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[11, "test_cases.battery.feeder_population.glm_mod_functions.write_base_glm"]], "write_class_dict() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[11, "test_cases.battery.feeder_population.glm_mod_functions.write_class_dict"]], "write_clock_dict() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[11, "test_cases.battery.feeder_population.glm_mod_functions.write_clock_dict"]], "write_filter_dict() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[11, "test_cases.battery.feeder_population.glm_mod_functions.write_filter_dict"]], "write_mod_dict() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[11, "test_cases.battery.feeder_population.glm_mod_functions.write_mod_dict"]], "write_obj_dict() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[11, "test_cases.battery.feeder_population.glm_mod_functions.write_obj_dict"]]}}) \ No newline at end of file diff --git a/docs/build/html/test_cases.base_case.html b/docs/build/html/test_cases.base_case.html index 4a8fb8c2f..1e98ebf56 100644 --- a/docs/build/html/test_cases.base_case.html +++ b/docs/build/html/test_cases.base_case.html @@ -46,9 +46,9 @@
        • Readme
        • Packages diff --git a/docs/build/html/test_cases.battery.feeder_population.html b/docs/build/html/test_cases.battery.feeder_population.html index be2a55a10..caa27bffa 100644 --- a/docs/build/html/test_cases.battery.feeder_population.html +++ b/docs/build/html/test_cases.battery.feeder_population.html @@ -19,6 +19,7 @@ + @@ -45,9 +46,9 @@
          • Readme
          • Packages @@ -278,6 +280,7 @@

            test_cases.battery.feeder_population.feeder_population_old module +
            diff --git a/docs/build/html/test_cases.battery.html b/docs/build/html/test_cases.battery.html index 44956c56f..f2c91745f 100644 --- a/docs/build/html/test_cases.battery.html +++ b/docs/build/html/test_cases.battery.html @@ -46,9 +46,9 @@
            • Readme
            • Packages diff --git a/docs/build/html/test_cases.html b/docs/build/html/test_cases.html index 497a6a22b..038c6b95f 100644 --- a/docs/build/html/test_cases.html +++ b/docs/build/html/test_cases.html @@ -20,7 +20,7 @@ - + @@ -46,9 +46,9 @@
              • Readme
              • Packages @@ -141,7 +142,7 @@

                Subpackages - + diff --git a/docs/build/index.html b/docs/build/index.html new file mode 100644 index 000000000..ce48adb67 --- /dev/null +++ b/docs/build/index.html @@ -0,0 +1,137 @@ + + + + + + + Welcome to EV-Ecosim 1.0.0 — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + + +
                + + +
                + +
                +
                +
                +
                  +
                • + +
                • +
                • +
                +
                +
                +
                +
                + +
                +

                Welcome to EV-Ecosim 1.0.0

                +

                EV-Ecosim is a grid-aware python-based co-simulation platform for modeling and simulation of EV charging +stations integrated with Solar and Battery systems. This is a python based platform that interfaces with GridLAB-D, +a 3-phase unbalanced power flow solver, to estimate the impacts of EV (Fast) Charging Stations on power distribution +networks.

                +EV-Ecosim Simulation Framework +

                We have made a web-tool version available for public use. It runs most of the code shown in this documentation.

                +

                The project is accessible via Github and still under active development and improvements.

                +

                TODO - Link to tutorial. +TODO - Include information on the container.

                + +
                +
                +

                Indices and tables

                + +
                + + +
                +
                +
                + +
                + +
                +

                © Copyright 2023, Emmanuel Balogun, Stanford University S3L Lab.

                +
                + + Built with Sphinx using a + theme + provided by Read the Docs. + + +
                +
                +
                +
                +
                + + + + \ No newline at end of file diff --git a/docs/build/modules.html b/docs/build/modules.html new file mode 100644 index 000000000..3dcfd4c10 --- /dev/null +++ b/docs/build/modules.html @@ -0,0 +1,272 @@ + + + + + + + Packages — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + + + +
                + + +
                + +
                +
                +
                +
                  +
                • + +
                • +
                • +
                +
                +
                +
                +
                + +
                +

                Packages

                +
                + +
                +
                + + +
                +
                + +
                +
                +
                +
                + + + + \ No newline at end of file diff --git a/docs/build/objects.inv b/docs/build/objects.inv new file mode 100644 index 000000000..9913e1c89 Binary files /dev/null and b/docs/build/objects.inv differ diff --git a/docs/build/py-modindex.html b/docs/build/py-modindex.html new file mode 100644 index 000000000..d6bc2fb0f --- /dev/null +++ b/docs/build/py-modindex.html @@ -0,0 +1,211 @@ + + + + + + Python Module Index — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + + + + +
                + + +
                + +
                +
                +
                +
                  +
                • + +
                • +
                • +
                +
                +
                +
                +
                + + +

                Python Module Index

                + +
                + a | + c | + f | + t +
                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                 
                + a
                + analysis +
                    + analysis.cost_analysis +
                 
                + c
                + charging_sim +
                    + charging_sim.batteryAgingSim +
                    + charging_sim.capacitor +
                    + charging_sim.electricityPrices +
                    + charging_sim.optimization +
                    + charging_sim.solar +
                    + charging_sim.utils +
                 
                + f
                + feeder_population +
                    + feeder_population.glm_mod_functions +
                 
                + t
                + test_cases +
                    + test_cases.base_case +
                    + test_cases.battery +
                    + test_cases.battery.feeder_population +
                    + test_cases.battery.feeder_population.glm_mod_functions +
                + + +
                +
                +
                + +
                + +
                +

                © Copyright 2023, Emmanuel Balogun, Stanford University S3L Lab.

                +
                + + Built with Sphinx using a + theme + provided by Read the Docs. + + +
                +
                +
                +
                +
                + + + + \ No newline at end of file diff --git a/docs/build/search.html b/docs/build/search.html new file mode 100644 index 000000000..d3f0c31c3 --- /dev/null +++ b/docs/build/search.html @@ -0,0 +1,121 @@ + + + + + + Search — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + + + + +
                + + +
                + +
                +
                +
                +
                  +
                • + +
                • +
                • +
                +
                +
                +
                +
                + + + + +
                + +
                + +
                +
                +
                + +
                + +
                +

                © Copyright 2023, Emmanuel Balogun, Stanford University S3L Lab.

                +
                + + Built with Sphinx using a + theme + provided by Read the Docs. + + +
                +
                +
                +
                +
                + + + + + + + + + \ No newline at end of file diff --git a/docs/build/searchindex.js b/docs/build/searchindex.js new file mode 100644 index 000000000..c6d7fd318 --- /dev/null +++ b/docs/build/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({"docnames": ["README", "analysis", "charging_sim", "feeder_population", "index", "modules", "readme", "test_cases", "test_cases.base_case", "test_cases.battery", "test_cases.battery.feeder_population"], "filenames": ["README.md", "analysis.rst", "charging_sim.rst", "feeder_population.rst", "index.rst", "modules.rst", "readme.rst", "test_cases.rst", "test_cases.base_case.rst", "test_cases.battery.rst", "test_cases.battery.feeder_population.rst"], "titles": ["EV-Ecosim platform", "Post-simulation analysis", "Charging simulator", "Feeder population", "Welcome to EV-Ecosim 1.0.0", "Packages", "Readme", "Test cases", "test_cases.base_case package", "test_cases.battery package", "test_cases.battery.feeder_population package"], "terms": {"A": [0, 1, 2], "grid": [0, 1, 4], "awar": [0, 4], "design": [0, 2], "vehicl": 0, "paper": [0, 2], "http": [0, 1, 2], "doi": 0, "org": 0, "10": 0, "36227": 0, "techrxiv": 0, "23596725": 0, "v2": 0, "emmanuel": 0, "balogun": 0, "ebalogun": 0, "stanford": 0, "edu": 0, "lili": 0, "buechler": 0, "ebuech": 0, "gismo": 0, "slac": 0, "gridlab": [0, 3, 4, 10], "d": [0, 3, 4, 10], "instal": [0, 2], "master": 0, "branch": 0, "github": [0, 4], "com": [0, 2], "arra": 0, "energi": [0, 2], "gridlabd": 0, "version": [0, 2, 4], "python": [0, 4], "recommend": 0, "aw": 0, "ec2": 0, "hipa": 0, "ami": 0, "beauharnoi": 0, "x": 0, "ambient": 0, "_": 0, "data": [0, 1, 2], "temperatur": [0, 2], "captur": 0, "effect": 0, "environment": 0, "condit": 0, "subsystem": 0, "transform": [0, 1, 2], "base": [0, 1, 2, 4, 10], "load": [0, 1, 2, 3, 10], "includ": [0, 1, 2, 4], "exist": 0, "build": [0, 1, 2], "home": [0, 2], "usual": 0, "uncontrol": 0, "within": [0, 1, 2], "distribut": [0, 1, 4], "work": [0, 2], "proprietari": 0, "pecan": 0, "street": 0, "below": 0, "an": [0, 2], "exmapl": 0, "prototyp": 0, "note": [0, 2], "column": 0, "field": 0, "ar": [0, 1, 2], "sensit": 0, "The": [0, 1, 2, 4], "origin": 0, "ha": 0, "minut": 0, "resolut": [0, 2], "power": [0, 1, 2, 3, 4, 10], "system": [0, 1, 2, 3, 4, 10], "batt": [0, 2], "sy": 0, "identif": 0, "class": [0, 1, 2, 3, 10], "gener": [0, 2], "paramet": [0, 1, 2, 3, 10], "from": [0, 1, 2, 3], "experiment": 0, "leverag": 0, "genet": 0, "algorithm": 0, "model": [0, 2, 3, 4, 10], "2nd": 0, "order": 0, "rc": 0, "equival": 0, "circuit": 0, "ecm": 0, "One": 0, "can": [0, 1, 2], "custom": 0, "nmc": [0, 2], "upload": 0, "csv": [0, 2], "file": [0, 1, 2, 3, 10], "param": [0, 2], "shown": [0, 4], "save": [0, 1, 2], "new": [0, 2], "addit": 0, "correct": [0, 2], "open": 0, "voltag": [0, 1], "ocv": 0, "valu": [0, 1, 2], "label": [0, 1], "ocv_corr": 0, "abov": 0, "onc": [0, 2], "thei": 0, "battery_data": 0, "config": [0, 2], "json": [0, 2], "modifi": [0, 2, 3, 10], "so": 0, "sim": [0, 5, 7], "contain": [0, 1, 2, 4, 10], "which": [0, 1, 2], "configur": [0, 2], "all": [0, 1, 2, 3], "relev": 0, "implement": [0, 1, 2], "physic": 0, "legaci": 0, "forecast": 0, "develop": [0, 4], "need": [0, 2], "elec": 0, "rate": [0, 2], "time": [0, 2], "tou": [0, 2], "input": [0, 2], "user": [0, 2], "must": [0, 2], "normal": [0, 1], "full": 0, "year": [0, 2], "size": 0, "365": 0, "dai": [0, 1, 2], "avoid": 0, "ani": 0, "error": 0, "format": 0, "read": 0, "sampl": [0, 2], "dure": [0, 2], "should": 0, "one": [0, 2], "15": [0, 2], "also": [0, 1, 2], "help": 0, "downscal": [0, 2, 5], "much": 0, "coarser": 0, "librari": 0, "ieee": [0, 1], "test": [0, 2, 4, 5], "pnnl": 0, "taxonomi": 0, "glm": [0, 3, 10], "have": [0, 4], "spot": 0, "specifi": 0, "primari": 0, "level": [0, 1], "secondari": 0, "popul": [0, 4, 5], "script": 0, "vari": 0, "resourc": [0, 1], "necessari": 0, "txt": 0, "residenti": 0, "repo": 0, "limit": [0, 2], "access": [0, 4], "irradi": [0, 2], "overal": [0, 1, 2], "default": [0, 2], "nation": 0, "radiat": 0, "databas": 0, "nsrdb": 0, "san": 0, "francisco": 0, "bai": 0, "area": [0, 2], "renew": 0, "laboratori": 0, "nrel": [0, 1], "month": [0, 2], "index": [0, 2, 4], "1": [0, 2], "12": [0, 1, 2], "inclus": 0, "januari": 0, "decemb": [0, 2], "hourli": 0, "interv": 0, "oversampl": 0, "4": 0, "dataset": [0, 2], "ghi": [0, 2], "repres": 0, "global": [0, 2], "horizont": [0, 2], "w": 0, "m": 0, "2": 0, "total": [0, 2], "amount": [0, 1], "shortwav": 0, "receiv": 0, "surfac": 0, "ground": 0, "base_cas": [0, 5, 7], "write": [0, 3, 10], "inject": 0, "each": [0, 1, 2], "timestep": 0, "rlsf": 0, "plu": 0, "recurs": 0, "least": 0, "squar": 0, "filter": [0, 3, 10], "estim": [0, 1, 2, 4], "network": [0, 1, 4], "onlin": 0, "thermal": 0, "integr": [0, 4], "plot": [0, 1], "result": [0, 1], "calcul": [0, 1, 2], "impact": [0, 4], "plot_result": [0, 5], "pars": 0, "percentag": 0, "violat": [0, 1], "per": 0, "ansi": 0, "c84": 0, "variabl": [0, 2], "string": [0, 2], "path": [0, 2], "where": [0, 2], "powerflow": 0, "output": [0, 2, 3], "node": [0, 1], "load_post_opt_cost": [0, 5], "tabl": 0, "matric": 0, "respect": 0, "cost_analysi": [0, 5], "costestim": [0, 1, 5], "differ": [0, 1], "compon": [0, 1], "creat": [0, 1], "environ": 0, "conda": 0, "env": 0, "name": [0, 2], "your": [0, 2], "f": 0, "yml": 0, "OR": 0, "packag": [0, 4, 7], "list": [0, 1, 2, 3], "manual": 0, "ensur": 0, "follow": [0, 2], "method": [0, 2], "For": 0, "navig": 0, "set": [0, 2], "prepar": 0, "confirm": 0, "successfulli": 0, "ieee123_secondari": 0, "ieee123_popul": 0, "you": 0, "done": 0, "initi": [0, 2], "pre": [0, 2], "prep": 0, "now": [0, 2], "out": 0, "scenario": [0, 1, 5, 7], "python3": 0, "ev50_cosimul": 0, "master_sim": [0, 5, 7], "pleas": 0, "see": 0, "section": 0, "more": [0, 2], "detail": 0, "thi": [1, 2, 4], "cost": [1, 2], "der": 1, "num_dai": 1, "sourc": [1, 2, 3, 10], "object": [1, 2, 3, 10], "i": [1, 2, 4], "us": [1, 2, 4], "asset": 1, "ev": 1, "ecosim": 1, "number": [1, 2], "run": [1, 2, 4, 5], "calculate_battery_cost": [1, 5], "result_dir": 1, "batteri": [1, 4, 5, 7], "updat": [1, 2], "lcoe": 1, "directori": 1, "dictionari": [1, 2, 3, 10], "return": [1, 2, 3, 10], "dict": [1, 2, 3], "result_dict": 1, "calculate_electricity_cost_pgebev2": [1, 5], "pge_separate_fil": 1, "true": [1, 2], "electr": [1, 2], "pgebev2": 1, "given": [1, 2], "str": [1, 2], "compris": 1, "dollar": 1, "calculate_solar_cost": [1, 5], "pull": 1, "solar": [1, 4, 5], "ref": 1, "www": [1, 2], "gov": 1, "market": 1, "research": 1, "html": 1, "To": 1, "deprec": [1, 2], "soon": 1, "none": [1, 2], "calculate_trans_loss_of_lif": [1, 5], "expect": 1, "loss": 1, "life": 1, "refer": 1, "5": 1, "11": 1, "3": [1, 4], "std": 1, "c57": 1, "00": 1, "2010": 1, "minimum": 1, "insul": 1, "180": 1, "000": 1, "hour": [1, 2], "static": [1, 2], "plot_load": [1, 5], "total_load": 1, "net_load": 1, "prefix": [1, 2], "overlai": 1, "net": 1, "visual": 1, "demand": [1, 2], "control": [1, 5], "minu": 1, "buffer": 1, "legend": 1, "curv": 1, "plot_pow": [1, 5], "power_pr": 1, "predict": 1, "plot_soc": [1, 5], "soc": 1, "soc_pr": 1, "state": 1, "charg": [1, 4, 5], "solar_cost": [1, 5], "capit": 1, "Not": 1, "fulli": 1, "locat": [1, 2], "pv": 1, "transformer_cost": [1, 2, 5], "cannot": 1, "find": 1, "good": 1, "yet": [1, 2], "ag": [1, 2], "batteryag": [2, 5], "enact": 2, "capac": 2, "resist": 2, "step": 2, "datetim": 2, "num_step": 2, "re": 2, "current": 2, "linimncoo2": 2, "cell": 2, "ad": 2, "futur": 2, "link": [2, 4], "sciencedirect": 2, "scienc": 2, "articl": 2, "pii": 2, "s0378775314001876": 2, "beta_cap": 2, "fade": 2, "factor": 2, "cycl": 2, "alpha_cap": 2, "calendar": 2, "beta_r": 2, "growth": 2, "alpha_r": 2, "assumpt": 2, "homogen": 2, "dynam": 2, "uniform": 2, "across": 2, "constant": 2, "profil": 2, "vicin": 2, "lfp_cal_ag": [2, 5], "lfp_cyc_ag": [2, 5], "nmc_cal_ag": [2, 5], "nmc_cyc_ag": [2, 5], "get_aging_valu": [2, 5], "pack": 2, "get_calendar_ag": [2, 5], "tupl": 2, "due": 2, "get_cyc_ag": [2, 5], "THe": 2, "get_total_ag": [2, 5], "both": 2, "update_capac": [2, 5], "adopt": 2, "schmalsteig": 2, "et": 2, "al": 2, "update_resist": [2, 5], "host": 2, "price": 2, "structur": [2, 3, 10], "desir": 2, "problem": 2, "pge_bev2_": [2, 5], "valid": 2, "california": 2, "howev": 2, "own": 2, "numpi": 2, "arrai": 2, "priceload": [2, 5], "path_prefix": 2, "evs": 2, "profit": 2, "loader": 2, "obtain": 2, "first": 2, "repositori": 2, "input_r": 2, "output_r": 2, "finer": 2, "similar": 2, "panda": 2, "typic": 2, "onli": 2, "get_pric": [2, 5], "start_idx": 2, "7": 2, "assum": 2, "do": 2, "chang": 2, "int": 2, "start": 2, "vector": 2, "cardin": 2, "being": 2, "exampl": 2, "jan": 2, "ndarrai": 2, "price_vector": 2, "set_month_data": [2, 5], "main": [2, 5], "solv": 2, "objective_typ": 2, "power_demand": 2, "time_r": 2, "0": 2, "solver": [2, 4], "gurobi": 2, "constructor": 2, "function": [2, 3, 10], "degrad": 2, "convex": 2, "mix": 2, "integ": 2, "program": 2, "depend": 2, "select": 2, "separ": 2, "": 2, "pc": 2, "success": 2, "type": 2, "cvxpy": 2, "station": [2, 4], "option": 2, "counter": 2, "identifi": 2, "avail": [2, 4], "backend": 2, "invok": 2, "eco": 2, "mosek": 2, "etc": 2, "add_demand_charg": [2, 5], "kw": 2, "aggregate_constraint": [2, 5], "aggreg": 2, "constraint": 2, "build_battery_cost": [2, 5], "build_emissions_cost": [2, 5], "emiss": 2, "build_transformer_cost": [2, 5], "get_battery_constraint": [2, 5], "get_constraint": [2, 5], "instanc": [2, 3], "float": 2, "site": 2, "namepl": 2, "its": 2, "It": [2, 4], "equat": 2, "p_": 2, "min": 2, "eta": 2, "effici": 2, "panel": 2, "right": 2, "make": 2, "decis": 2, "flow": [2, 4], "devic": 2, "get_pow": [2, 5], "desired_shap": 2, "96": 2, "get_solar_output": [2, 5], "modify_r": [2, 5], "new_r": 2, "update_histori": [2, 5], "mainli": 2, "purpos": 2, "mayb": 2, "store": 2, "schedul": 2, "pge": 2, "doc": 2, "found": 2, "here": 2, "add_power_profile_to_object": [2, 5], "battery_power_profil": 2, "build_cost_pge_bev2": [2, 5], "energy_prices_t": 2, "penalize_max_pow": 2, "max_power_pen": 2, "1000": 2, "heurist": 2, "take": 2, "averag": 2, "conserv": 2, "gamma": 2, "build_electricity_cost": [2, 5], "demand_charg": 2, "fals": 2, "opt": 2, "build_object": [2, 5], "mode": 2, "electricity_cost": 2, "battery_degradation_cost": 2, "we": [2, 4], "minim": 2, "load_pric": [2, 5], "time_interv": 2, "simul": [3, 4, 5, 10], "load_base_glm": [3, 5, 9, 10], "base_file_dir": [3, 10], "base_glm_fil": [3, 10], "replace_load_w_met": [3, 5, 9, 10], "glm_dict": [3, 10], "match_str": [3, 10], "rep_str": [3, 10], "obj_typ": [3, 10], "replac": [3, 10], "meter": [3, 10], "replace_load_w_meter_old": [3, 5, 9, 10], "write_base_glm": [3, 5, 9, 10], "globals_list": [3, 10], "include_list": [3, 10], "out_dir": [3, 10], "file_nam": [3, 10], "sync_list": [3, 10], "write_class_dict": [3, 5, 9, 10], "gld_dict": [3, 10], "class_nam": [3, 10], "correspond": [3, 10], "gld": [3, 10], "write_clock_dict": [3, 5, 9, 10], "clock": [3, 10], "write_filter_dict": [3, 5, 9, 10], "write_mod_dict": [3, 5, 9, 10], "mod_nam": [3, 10], "write_obj_dict": [3, 5, 9, 10], "dict_kei": [3, 10], "co": 4, "platform": 4, "interfac": 4, "phase": 4, "unbalanc": 4, "fast": 4, "made": 4, "web": 4, "tool": 4, "public": 4, "most": 4, "code": 4, "document": 4, "project": 4, "via": 4, "still": 4, "under": 4, "activ": 4, "improv": 4, "todo": 4, "tutori": 4, "inform": 4, "readm": 4, "post": [4, 5], "analysi": [4, 5], "feeder": [4, 5], "case": [4, 5], "modul": [4, 5], "search": 4, "page": 4, "submodul": [5, 7], "content": 5, "charging_sim": 5, "batteryagingsim": 5, "batterypack": 5, "batterytest": 5, "capacitor": 5, "chargingst": 5, "electricitypric": 5, "optim": 5, "orchestr": 5, "util": 5, "feeder_popul": [5, 7, 9], "glm_mod_funct": [5, 7, 9], "subpackag": 5, "test_cas": [5, 7], "event_handl": [5, 7], "gblvar": [5, 7], "glmptime": [5, 7], "voltdump2": [5, 7], "data_analysi": [5, 7], "event_handlers_oneshot": [5, 7], "parse_voltag": [5, 7], "feeder_population_old": [7, 9]}, "objects": {"": [[1, 0, 0, "-", "analysis"], [2, 0, 0, "-", "charging_sim"], [3, 0, 0, "-", "feeder_population"], [7, 0, 0, "-", "test_cases"]], "analysis": [[1, 0, 0, "-", "cost_analysis"]], "analysis.cost_analysis": [[1, 1, 1, "", "CostEstimator"]], "analysis.cost_analysis.CostEstimator": [[1, 2, 1, "", "calculate_battery_cost"], [1, 2, 1, "", "calculate_electricity_cost_PGEBEV2s"], [1, 2, 1, "", "calculate_solar_cost"], [1, 2, 1, "", "calculate_trans_loss_of_life"], [1, 2, 1, "", "plot_loads"], [1, 2, 1, "", "plot_power"], [1, 2, 1, "", "plot_soc"], [1, 2, 1, "", "solar_cost"], [1, 2, 1, "", "transformer_cost"]], "charging_sim": [[2, 0, 0, "-", "batteryAgingSim"], [2, 0, 0, "-", "capacitor"], [2, 0, 0, "-", "electricityPrices"], [2, 0, 0, "-", "optimization"], [2, 0, 0, "-", "solar"], [2, 0, 0, "-", "utils"]], "charging_sim.batteryAgingSim": [[2, 1, 1, "", "BatteryAging"]], "charging_sim.batteryAgingSim.BatteryAging": [[2, 2, 1, "", "LFP_cal_aging"], [2, 2, 1, "", "LFP_cyc_aging"], [2, 2, 1, "", "NMC_cal_aging"], [2, 2, 1, "", "NMC_cyc_aging"], [2, 2, 1, "", "get_aging_value"], [2, 2, 1, "", "get_calendar_aging"], [2, 2, 1, "", "get_cyc_aging"], [2, 2, 1, "", "get_total_aging"], [2, 2, 1, "", "run"], [2, 2, 1, "", "update_capacity"], [2, 2, 1, "", "update_resistance"]], "charging_sim.capacitor": [[2, 1, 1, "", "Capacitor"]], "charging_sim.electricityPrices": [[2, 1, 1, "", "PriceLoader"], [2, 3, 1, "", "main"]], "charging_sim.electricityPrices.PriceLoader": [[2, 2, 1, "", "downscale"], [2, 2, 1, "", "get_prices"], [2, 2, 1, "", "set_month_data"]], "charging_sim.optimization": [[2, 1, 1, "", "Optimization"]], "charging_sim.optimization.Optimization": [[2, 2, 1, "", "add_demand_charge"], [2, 2, 1, "", "aggregate_constraints"], [2, 2, 1, "", "build_battery_cost"], [2, 2, 1, "", "build_emissions_cost"], [2, 2, 1, "", "build_transformer_cost"], [2, 2, 1, "", "get_battery_constraint"], [2, 2, 1, "", "get_constraints"], [2, 2, 1, "", "run"]], "charging_sim.solar": [[2, 1, 1, "", "Solar"], [2, 3, 1, "", "main"]], "charging_sim.solar.Solar": [[2, 2, 1, "", "downscale"], [2, 2, 1, "", "get_constraints"], [2, 2, 1, "", "get_power"], [2, 2, 1, "", "get_solar_output"], [2, 2, 1, "", "modify_res"], [2, 2, 1, "", "update_history"]], "charging_sim.utils": [[2, 3, 1, "", "PGE_BEV2_S"], [2, 3, 1, "", "add_power_profile_to_object"], [2, 3, 1, "", "build_cost_PGE_BEV2S"], [2, 3, 1, "", "build_electricity_cost"], [2, 3, 1, "", "build_objective"], [2, 3, 1, "", "load_prices"]], "feeder_population": [[3, 0, 0, "-", "glm_mod_functions"]], "feeder_population.glm_mod_functions": [[3, 3, 1, "", "load_base_glm"], [3, 3, 1, "", "replace_load_w_meter"], [3, 3, 1, "", "replace_load_w_meter_old"], [3, 3, 1, "", "write_base_glm"], [3, 3, 1, "", "write_class_dict"], [3, 3, 1, "", "write_clock_dict"], [3, 3, 1, "", "write_filter_dict"], [3, 3, 1, "", "write_mod_dict"], [3, 3, 1, "", "write_obj_dict"]], "test_cases": [[8, 0, 0, "-", "base_case"], [9, 0, 0, "-", "battery"]], "test_cases.battery": [[10, 0, 0, "-", "feeder_population"]], "test_cases.battery.feeder_population": [[10, 0, 0, "-", "glm_mod_functions"]], "test_cases.battery.feeder_population.glm_mod_functions": [[10, 3, 1, "", "load_base_glm"], [10, 3, 1, "", "replace_load_w_meter"], [10, 3, 1, "", "replace_load_w_meter_old"], [10, 3, 1, "", "write_base_glm"], [10, 3, 1, "", "write_class_dict"], [10, 3, 1, "", "write_clock_dict"], [10, 3, 1, "", "write_filter_dict"], [10, 3, 1, "", "write_mod_dict"], [10, 3, 1, "", "write_obj_dict"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:method", "3": "py:function"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"], "3": ["py", "function", "Python function"]}, "titleterms": {"ev": [0, 4], "ecosim": [0, 4], "platform": 0, "author": 0, "requir": 0, "folder": 0, "descript": 0, "ambient_data": 0, "base_load_data": 0, "batt_sys_identif": 0, "charging_sim": [0, 2], "batteri": [0, 2, 9, 10], "py": 0, "cell": 0, "modul": [0, 1, 2, 3, 7, 8, 9, 10], "batterypack": [0, 2], "pack": 0, "batteryagingsim": [0, 2], "ag": 0, "control": [0, 2], "chargingst": [0, 2], "charg": [0, 2], "station": 0, "electricitypric": [0, 2], "electr": 0, "price": 0, "optim": [0, 2], "orchestr": [0, 2], "simul": [0, 1, 2], "solar": [0, 2], "pv": 0, "util": [0, 2], "host": 0, "function": 0, "us": 0, "some": 0, "offlin": 0, "der": 0, "cost": 0, "minim": 0, "thi": 0, "i": 0, "run": 0, "mode": 0, "state": 0, "feedback": 0, "dlmodel": 0, "elec_r": 0, "feeder": [0, 3], "feeder_popul": [0, 3, 10], "solar_data": 0, "test_cas": [0, 8, 9, 10], "co": 0, "case": [0, 7], "analysi": [0, 1], "how": 0, "post": [0, 1], "submodul": [1, 2, 3, 8, 9, 10], "cost_analysi": 1, "load_post_opt_cost": 1, "plot_result": 1, "content": [1, 2, 3, 4, 7, 8, 9, 10], "batterytest": 2, "capacitor": 2, "popul": 3, "glm_mod_funct": [3, 10], "welcom": 4, "1": 4, "0": 4, "indic": 4, "tabl": 4, "packag": [5, 8, 9, 10], "readm": 6, "test": 7, "subpackag": [7, 9], "base_cas": 8, "event_handl": [8, 9], "gblvar": [8, 9], "glmptime": [8, 9], "master_sim": [8, 9], "sim": [8, 9], "voltdump2": [8, 9], "data_analysi": 9, "event_handlers_oneshot": 9, "parse_voltag": 9, "scenario": 9, "feeder_population_old": 10}, "envversion": {"sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.todo": 2, "sphinx.ext.viewcode": 1, "sphinx": 60}, "alltitles": {"EV-Ecosim platform": [[0, "ev-ecosim-platform"]], "Authors": [[0, "authors"]], "Requirements": [[0, "requirements"]], "Folder descriptions": [[0, "folder-descriptions"]], "ambient_data": [[0, "ambient-data"]], "base_load_data": [[0, "base-load-data"]], "batt_sys_identification": [[0, "batt-sys-identification"]], "charging_sim": [[0, "charging-sim"]], "battery.py - Battery cell module.": [[0, "battery-py-battery-cell-module"]], "batterypack.py - Battery pack module.": [[0, "batterypack-py-battery-pack-module"]], "batteryAgingSim.py - Battery aging module.": [[0, "batteryagingsim-py-battery-aging-module"]], "controller.py - Controller module.": [[0, "controller-py-controller-module"]], "chargingStation.py - Charging station module.": [[0, "chargingstation-py-charging-station-module"]], "electricityPrices.py - Electricity prices module.": [[0, "electricityprices-py-electricity-prices-module"]], "optimization.py - Optimization module.": [[0, "optimization-py-optimization-module"]], "orchestrator.py - Simulation orchestrator module.": [[0, "orchestrator-py-simulation-orchestrator-module"]], "solar.py - Solar PV module.": [[0, "solar-py-solar-pv-module"]], "utils.py - Hosts utility functions used by some modules.": [[0, "utils-py-hosts-utility-functions-used-by-some-modules"]], "simulate.py - Offline DER control optimization for cost minimization (this is run for offline mode (no state feedback)).": [[0, "simulate-py-offline-der-control-optimization-for-cost-minimization-this-is-run-for-offline-mode-no-state-feedback"]], "DLMODELS": [[0, "dlmodels"]], "elec_rates": [[0, "elec-rates"]], "feeders": [[0, "feeders"]], "feeder_population": [[0, "feeder-population"]], "solar_data": [[0, "solar-data"]], "test_cases": [[0, "test-cases"]], "Co-simulation cases.": [[0, "co-simulation-cases"]], "analysis": [[0, "analysis"]], "How to run": [[0, "how-to-run"]], "Post-simulation analysis": [[0, "post-simulation-analysis"], [1, "post-simulation-analysis"]], "Submodules": [[1, "submodules"], [2, "submodules"], [3, "submodules"], [8, "submodules"], [9, "submodules"], [10, "submodules"]], "cost_analysis module": [[1, "module-analysis.cost_analysis"]], "load_post_opt_costs module": [[1, "load-post-opt-costs-module"]], "plot_results module": [[1, "plot-results-module"]], "Module contents": [[1, "module-analysis"], [2, "module-charging_sim"], [3, "module-feeder_population"], [7, "module-test_cases"], [8, "module-test_cases.base_case"], [9, "module-test_cases.battery"], [10, "module-test_cases.battery.feeder_population"]], "Charging simulator": [[2, "charging-simulator"]], "charging_sim.battery module": [[2, "charging-sim-battery-module"]], "charging_sim.batteryAgingSim module": [[2, "module-charging_sim.batteryAgingSim"]], "charging_sim.batterypack module": [[2, "charging-sim-batterypack-module"]], "charging_sim.batterytest module": [[2, "charging-sim-batterytest-module"]], "charging_sim.capacitor module": [[2, "module-charging_sim.capacitor"]], "charging_sim.chargingStation module": [[2, "charging-sim-chargingstation-module"]], "charging_sim.controller module": [[2, "charging-sim-controller-module"]], "charging_sim.electricityPrices module": [[2, "module-charging_sim.electricityPrices"]], "charging_sim.optimization module": [[2, "module-charging_sim.optimization"]], "charging_sim.orchestrator module": [[2, "charging-sim-orchestrator-module"]], "charging_sim.simulate module": [[2, "charging-sim-simulate-module"]], "charging_sim.solar module": [[2, "module-charging_sim.solar"]], "charging_sim.utils module": [[2, "module-charging_sim.utils"]], "Feeder population": [[3, "feeder-population"]], "feeder_population.feeder_population module": [[3, "feeder-population-feeder-population-module"]], "feeder_population.glm_mod_functions module": [[3, "module-feeder_population.glm_mod_functions"]], "Welcome to EV-Ecosim 1.0.0": [[4, "welcome-to-ev-ecosim-1-0-0"]], "Contents:": [[4, null]], "Indices and tables": [[4, "indices-and-tables"]], "Packages": [[5, "packages"]], "Readme": [[6, "readme"]], "Test cases": [[7, "test-cases"]], "Subpackages": [[7, "subpackages"], [9, "subpackages"]], "test_cases.base_case package": [[8, "test-cases-base-case-package"]], "test_cases.base_case.event_handlers module": [[8, "test-cases-base-case-event-handlers-module"]], "test_cases.base_case.gblvar module": [[8, "test-cases-base-case-gblvar-module"]], "test_cases.base_case.glmptime module": [[8, "test-cases-base-case-glmptime-module"]], "test_cases.base_case.master_sim module": [[8, "test-cases-base-case-master-sim-module"]], "test_cases.base_case.sim module": [[8, "test-cases-base-case-sim-module"]], "test_cases.base_case.voltdump2 module": [[8, "test-cases-base-case-voltdump2-module"]], "test_cases.battery package": [[9, "test-cases-battery-package"]], "test_cases.battery.data_analysis module": [[9, "test-cases-battery-data-analysis-module"]], "test_cases.battery.event_handlers module": [[9, "test-cases-battery-event-handlers-module"]], "test_cases.battery.event_handlers_oneshot module": [[9, "test-cases-battery-event-handlers-oneshot-module"]], "test_cases.battery.gblvar module": [[9, "test-cases-battery-gblvar-module"]], "test_cases.battery.glmptime module": [[9, "test-cases-battery-glmptime-module"]], "test_cases.battery.master_sim module": [[9, "test-cases-battery-master-sim-module"]], "test_cases.battery.parse_voltages module": [[9, "test-cases-battery-parse-voltages-module"]], "test_cases.battery.scenarios module": [[9, "test-cases-battery-scenarios-module"]], "test_cases.battery.sim module": [[9, "test-cases-battery-sim-module"]], "test_cases.battery.voltdump2 module": [[9, "test-cases-battery-voltdump2-module"]], "test_cases.battery.feeder_population package": [[10, "test-cases-battery-feeder-population-package"]], "test_cases.battery.feeder_population.feeder_population module": [[10, "test-cases-battery-feeder-population-feeder-population-module"]], "test_cases.battery.feeder_population.feeder_population_old module": [[10, "test-cases-battery-feeder-population-feeder-population-old-module"]], "test_cases.battery.feeder_population.glm_mod_functions module": [[10, "module-test_cases.battery.feeder_population.glm_mod_functions"]]}, "indexentries": {"costestimator (class in analysis.cost_analysis)": [[1, "analysis.cost_analysis.CostEstimator"]], "analysis": [[1, "module-analysis"]], "analysis.cost_analysis": [[1, "module-analysis.cost_analysis"]], "calculate_battery_cost() (analysis.cost_analysis.costestimator method)": [[1, "analysis.cost_analysis.CostEstimator.calculate_battery_cost"]], "calculate_electricity_cost_pgebev2s() (analysis.cost_analysis.costestimator method)": [[1, "analysis.cost_analysis.CostEstimator.calculate_electricity_cost_PGEBEV2s"]], "calculate_solar_cost() (analysis.cost_analysis.costestimator method)": [[1, "analysis.cost_analysis.CostEstimator.calculate_solar_cost"]], "calculate_trans_loss_of_life() (analysis.cost_analysis.costestimator method)": [[1, "analysis.cost_analysis.CostEstimator.calculate_trans_loss_of_life"]], "module": [[1, "module-analysis"], [1, "module-analysis.cost_analysis"], [2, "module-charging_sim"], [2, "module-charging_sim.batteryAgingSim"], [2, "module-charging_sim.capacitor"], [2, "module-charging_sim.electricityPrices"], [2, "module-charging_sim.optimization"], [2, "module-charging_sim.solar"], [2, "module-charging_sim.utils"], [3, "module-feeder_population"], [3, "module-feeder_population.glm_mod_functions"], [7, "module-test_cases"], [8, "module-test_cases.base_case"], [9, "module-test_cases.battery"], [10, "module-test_cases.battery.feeder_population"], [10, "module-test_cases.battery.feeder_population.glm_mod_functions"]], "plot_loads() (analysis.cost_analysis.costestimator static method)": [[1, "analysis.cost_analysis.CostEstimator.plot_loads"]], "plot_power() (analysis.cost_analysis.costestimator static method)": [[1, "analysis.cost_analysis.CostEstimator.plot_power"]], "plot_soc() (analysis.cost_analysis.costestimator static method)": [[1, "analysis.cost_analysis.CostEstimator.plot_soc"]], "solar_cost() (analysis.cost_analysis.costestimator method)": [[1, "analysis.cost_analysis.CostEstimator.solar_cost"]], "transformer_cost() (analysis.cost_analysis.costestimator method)": [[1, "analysis.cost_analysis.CostEstimator.transformer_cost"]], "batteryaging (class in charging_sim.batteryagingsim)": [[2, "charging_sim.batteryAgingSim.BatteryAging"]], "capacitor (class in charging_sim.capacitor)": [[2, "charging_sim.capacitor.Capacitor"]], "lfp_cal_aging() (charging_sim.batteryagingsim.batteryaging static method)": [[2, "charging_sim.batteryAgingSim.BatteryAging.LFP_cal_aging"]], "lfp_cyc_aging() (charging_sim.batteryagingsim.batteryaging static method)": [[2, "charging_sim.batteryAgingSim.BatteryAging.LFP_cyc_aging"]], "nmc_cal_aging() (charging_sim.batteryagingsim.batteryaging static method)": [[2, "charging_sim.batteryAgingSim.BatteryAging.NMC_cal_aging"]], "nmc_cyc_aging() (charging_sim.batteryagingsim.batteryaging static method)": [[2, "charging_sim.batteryAgingSim.BatteryAging.NMC_cyc_aging"]], "optimization (class in charging_sim.optimization)": [[2, "charging_sim.optimization.Optimization"]], "pge_bev2_s() (in module charging_sim.utils)": [[2, "charging_sim.utils.PGE_BEV2_S"]], "priceloader (class in charging_sim.electricityprices)": [[2, "charging_sim.electricityPrices.PriceLoader"]], "solar (class in charging_sim.solar)": [[2, "charging_sim.solar.Solar"]], "add_demand_charge() (charging_sim.optimization.optimization method)": [[2, "charging_sim.optimization.Optimization.add_demand_charge"]], "add_power_profile_to_object() (in module charging_sim.utils)": [[2, "charging_sim.utils.add_power_profile_to_object"]], "aggregate_constraints() (charging_sim.optimization.optimization method)": [[2, "charging_sim.optimization.Optimization.aggregate_constraints"]], "build_battery_cost() (charging_sim.optimization.optimization method)": [[2, "charging_sim.optimization.Optimization.build_battery_cost"]], "build_cost_pge_bev2s() (in module charging_sim.utils)": [[2, "charging_sim.utils.build_cost_PGE_BEV2S"]], "build_electricity_cost() (in module charging_sim.utils)": [[2, "charging_sim.utils.build_electricity_cost"]], "build_emissions_cost() (charging_sim.optimization.optimization method)": [[2, "charging_sim.optimization.Optimization.build_emissions_cost"]], "build_objective() (in module charging_sim.utils)": [[2, "charging_sim.utils.build_objective"]], "build_transformer_cost() (charging_sim.optimization.optimization method)": [[2, "charging_sim.optimization.Optimization.build_transformer_cost"]], "charging_sim": [[2, "module-charging_sim"]], "charging_sim.batteryagingsim": [[2, "module-charging_sim.batteryAgingSim"]], "charging_sim.capacitor": [[2, "module-charging_sim.capacitor"]], "charging_sim.electricityprices": [[2, "module-charging_sim.electricityPrices"]], "charging_sim.optimization": [[2, "module-charging_sim.optimization"]], "charging_sim.solar": [[2, "module-charging_sim.solar"]], "charging_sim.utils": [[2, "module-charging_sim.utils"]], "downscale() (charging_sim.electricityprices.priceloader method)": [[2, "charging_sim.electricityPrices.PriceLoader.downscale"]], "downscale() (charging_sim.solar.solar method)": [[2, "charging_sim.solar.Solar.downscale"]], "get_aging_value() (charging_sim.batteryagingsim.batteryaging method)": [[2, "charging_sim.batteryAgingSim.BatteryAging.get_aging_value"]], "get_battery_constraint() (charging_sim.optimization.optimization method)": [[2, "charging_sim.optimization.Optimization.get_battery_constraint"]], "get_calendar_aging() (charging_sim.batteryagingsim.batteryaging method)": [[2, "charging_sim.batteryAgingSim.BatteryAging.get_calendar_aging"]], "get_constraints() (charging_sim.optimization.optimization method)": [[2, "charging_sim.optimization.Optimization.get_constraints"]], "get_constraints() (charging_sim.solar.solar method)": [[2, "charging_sim.solar.Solar.get_constraints"]], "get_cyc_aging() (charging_sim.batteryagingsim.batteryaging method)": [[2, "charging_sim.batteryAgingSim.BatteryAging.get_cyc_aging"]], "get_power() (charging_sim.solar.solar method)": [[2, "charging_sim.solar.Solar.get_power"]], "get_prices() (charging_sim.electricityprices.priceloader method)": [[2, "charging_sim.electricityPrices.PriceLoader.get_prices"]], "get_solar_output() (charging_sim.solar.solar method)": [[2, "charging_sim.solar.Solar.get_solar_output"]], "get_total_aging() (charging_sim.batteryagingsim.batteryaging method)": [[2, "charging_sim.batteryAgingSim.BatteryAging.get_total_aging"]], "load_prices() (in module charging_sim.utils)": [[2, "charging_sim.utils.load_prices"]], "main() (in module charging_sim.electricityprices)": [[2, "charging_sim.electricityPrices.main"]], "main() (in module charging_sim.solar)": [[2, "charging_sim.solar.main"]], "modify_res() (charging_sim.solar.solar method)": [[2, "charging_sim.solar.Solar.modify_res"]], "run() (charging_sim.batteryagingsim.batteryaging method)": [[2, "charging_sim.batteryAgingSim.BatteryAging.run"]], "run() (charging_sim.optimization.optimization method)": [[2, "charging_sim.optimization.Optimization.run"]], "set_month_data() (charging_sim.electricityprices.priceloader method)": [[2, "charging_sim.electricityPrices.PriceLoader.set_month_data"]], "update_capacity() (charging_sim.batteryagingsim.batteryaging method)": [[2, "charging_sim.batteryAgingSim.BatteryAging.update_capacity"]], "update_history() (charging_sim.solar.solar method)": [[2, "charging_sim.solar.Solar.update_history"]], "update_resistance() (charging_sim.batteryagingsim.batteryaging method)": [[2, "charging_sim.batteryAgingSim.BatteryAging.update_resistance"]], "feeder_population": [[3, "module-feeder_population"]], "feeder_population.glm_mod_functions": [[3, "module-feeder_population.glm_mod_functions"]], "load_base_glm() (in module feeder_population.glm_mod_functions)": [[3, "feeder_population.glm_mod_functions.load_base_glm"]], "replace_load_w_meter() (in module feeder_population.glm_mod_functions)": [[3, "feeder_population.glm_mod_functions.replace_load_w_meter"]], "replace_load_w_meter_old() (in module feeder_population.glm_mod_functions)": [[3, "feeder_population.glm_mod_functions.replace_load_w_meter_old"]], "write_base_glm() (in module feeder_population.glm_mod_functions)": [[3, "feeder_population.glm_mod_functions.write_base_glm"]], "write_class_dict() (in module feeder_population.glm_mod_functions)": [[3, "feeder_population.glm_mod_functions.write_class_dict"]], "write_clock_dict() (in module feeder_population.glm_mod_functions)": [[3, "feeder_population.glm_mod_functions.write_clock_dict"]], "write_filter_dict() (in module feeder_population.glm_mod_functions)": [[3, "feeder_population.glm_mod_functions.write_filter_dict"]], "write_mod_dict() (in module feeder_population.glm_mod_functions)": [[3, "feeder_population.glm_mod_functions.write_mod_dict"]], "write_obj_dict() (in module feeder_population.glm_mod_functions)": [[3, "feeder_population.glm_mod_functions.write_obj_dict"]], "test_cases": [[7, "module-test_cases"]], "test_cases.base_case": [[8, "module-test_cases.base_case"]], "test_cases.battery": [[9, "module-test_cases.battery"]], "load_base_glm() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[10, "test_cases.battery.feeder_population.glm_mod_functions.load_base_glm"]], "replace_load_w_meter() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[10, "test_cases.battery.feeder_population.glm_mod_functions.replace_load_w_meter"]], "replace_load_w_meter_old() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[10, "test_cases.battery.feeder_population.glm_mod_functions.replace_load_w_meter_old"]], "test_cases.battery.feeder_population": [[10, "module-test_cases.battery.feeder_population"]], "test_cases.battery.feeder_population.glm_mod_functions": [[10, "module-test_cases.battery.feeder_population.glm_mod_functions"]], "write_base_glm() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[10, "test_cases.battery.feeder_population.glm_mod_functions.write_base_glm"]], "write_class_dict() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[10, "test_cases.battery.feeder_population.glm_mod_functions.write_class_dict"]], "write_clock_dict() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[10, "test_cases.battery.feeder_population.glm_mod_functions.write_clock_dict"]], "write_filter_dict() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[10, "test_cases.battery.feeder_population.glm_mod_functions.write_filter_dict"]], "write_mod_dict() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[10, "test_cases.battery.feeder_population.glm_mod_functions.write_mod_dict"]], "write_obj_dict() (in module test_cases.battery.feeder_population.glm_mod_functions)": [[10, "test_cases.battery.feeder_population.glm_mod_functions.write_obj_dict"]]}}) \ No newline at end of file diff --git a/docs/build/test_cases.base_case.html b/docs/build/test_cases.base_case.html new file mode 100644 index 000000000..4a8fb8c2f --- /dev/null +++ b/docs/build/test_cases.base_case.html @@ -0,0 +1,149 @@ + + + + + + + test_cases.base_case package — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + + + +
                + + +
                + +
                +
                +
                + +
                +
                +
                +
                + +
                +

                test_cases.base_case package

                +
                +

                Submodules

                +
                +
                +

                test_cases.base_case.event_handlers module

                +
                +
                +

                test_cases.base_case.gblvar module

                +
                +
                +

                test_cases.base_case.glmptime module

                +
                +
                +

                test_cases.base_case.master_sim module

                +
                +
                +

                test_cases.base_case.sim module

                +
                +
                +

                test_cases.base_case.voltdump2 module

                +
                +
                +

                Module contents

                +
                +
                + + +
                +
                + +
                +
                +
                +
                + + + + \ No newline at end of file diff --git a/docs/build/test_cases.battery.feeder_population.html b/docs/build/test_cases.battery.feeder_population.html new file mode 100644 index 000000000..be2a55a10 --- /dev/null +++ b/docs/build/test_cases.battery.feeder_population.html @@ -0,0 +1,306 @@ + + + + + + + test_cases.battery.feeder_population package — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + + +
                + + +
                + +
                +
                +
                + +
                +
                +
                +
                + +
                +

                test_cases.battery.feeder_population package

                +
                +

                Submodules

                +
                +
                +

                test_cases.battery.feeder_population.feeder_population module

                +
                +
                +

                test_cases.battery.feeder_population.feeder_population_old module

                +
                +
                +

                test_cases.battery.feeder_population.glm_mod_functions module

                +

                Module contains functions for modifying GridLAB-D power system simulation models

                +
                +
                +test_cases.battery.feeder_population.glm_mod_functions.load_base_glm(base_file_dir, base_glm_file)[source]
                +

                Loads base glm file into a dictionary structure.

                +
                +
                Parameters:
                +
                  +
                • base_file_dir

                • +
                • base_glm_file

                • +
                +
                +
                Returns:
                +

                +
                +
                +
                + +
                +
                +test_cases.battery.feeder_population.glm_mod_functions.replace_load_w_meter(glm_dict, match_str, rep_str, obj_type)[source]
                +

                Replace load with meter in GLM dictionary.

                +
                +
                Parameters:
                +
                  +
                • glm_dict

                • +
                • match_str

                • +
                • rep_str

                • +
                • obj_type

                • +
                +
                +
                Returns:
                +

                +
                +
                +
                + +
                +
                +test_cases.battery.feeder_population.glm_mod_functions.replace_load_w_meter_old(glm_dict, match_str, rep_str, obj_type)[source]
                +

                Replace load with meter in GLM dictionary.

                +
                +
                Parameters:
                +
                  +
                • glm_dict

                • +
                • match_str

                • +
                • rep_str

                • +
                • obj_type

                • +
                +
                +
                Returns:
                +

                +
                +
                +
                + +
                +
                +test_cases.battery.feeder_population.glm_mod_functions.write_base_glm(glm_dict, obj_type, globals_list, include_list, out_dir, file_name, sync_list)[source]
                +
                +
                Parameters:
                +
                  +
                • glm_dict

                • +
                • obj_type

                • +
                • globals_list

                • +
                • include_list

                • +
                • out_dir

                • +
                • file_name

                • +
                • sync_list

                • +
                +
                +
                Returns:
                +

                +
                +
                +
                + +
                +
                +test_cases.battery.feeder_population.glm_mod_functions.write_class_dict(file, gld_dict, class_name)[source]
                +

                Write dictionary corresponding to GLD class to .glm file.

                +
                +
                Parameters:
                +
                  +
                • file

                • +
                • gld_dict

                • +
                • class_name

                • +
                +
                +
                Returns:
                +

                +
                +
                +
                + +
                +
                +test_cases.battery.feeder_population.glm_mod_functions.write_clock_dict(file, gld_dict)[source]
                +

                Write dictionary corresponding to GLD clock to .glm file.

                +
                +
                Parameters:
                +
                  +
                • file

                • +
                • gld_dict

                • +
                +
                +
                Returns:
                +

                +
                +
                +
                + +
                +
                +test_cases.battery.feeder_population.glm_mod_functions.write_filter_dict(file, gld_dict, class_name)[source]
                +

                Write dictionary corresponding to GLD filter to .glm file.

                +
                +
                Parameters:
                +
                  +
                • file

                • +
                • gld_dict

                • +
                • class_name

                • +
                +
                +
                Returns:
                +

                +
                +
                +
                + +
                +
                +test_cases.battery.feeder_population.glm_mod_functions.write_mod_dict(file, gld_dict, mod_name)[source]
                +

                Write dictionary corresponding to GLD module to .glm file’

                +
                +
                Parameters:
                +
                  +
                • file

                • +
                • gld_dict

                • +
                • mod_name

                • +
                +
                +
                Returns:
                +

                +
                +
                +
                + +
                +
                +test_cases.battery.feeder_population.glm_mod_functions.write_obj_dict(file, gld_dict, dict_key, obj_type)[source]
                +

                Write dictionary corresponding to GLD objects to .glm file

                +
                +
                Parameters:
                +
                  +
                • file

                • +
                • gld_dict

                • +
                • dict_key

                • +
                • obj_type

                • +
                +
                +
                Returns:
                +

                +
                +
                +
                + +
                +
                +

                Module contents

                +
                +
                + + +
                +
                + +
                +
                +
                +
                + + + + \ No newline at end of file diff --git a/docs/build/test_cases.battery.html b/docs/build/test_cases.battery.html new file mode 100644 index 000000000..44956c56f --- /dev/null +++ b/docs/build/test_cases.battery.html @@ -0,0 +1,187 @@ + + + + + + + test_cases.battery package — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + + + +
                + + +
                + +
                +
                +
                + +
                +
                +
                +
                + +
                +

                test_cases.battery package

                +
                +

                Subpackages

                + +
                +
                +

                Submodules

                +
                +
                +

                test_cases.battery.data_analysis module

                +
                +
                +

                test_cases.battery.event_handlers module

                +
                +
                +

                test_cases.battery.event_handlers_oneshot module

                +
                +
                +

                test_cases.battery.gblvar module

                +
                +
                +

                test_cases.battery.glmptime module

                +
                +
                +

                test_cases.battery.master_sim module

                +
                +
                +

                test_cases.battery.parse_voltages module

                +
                +
                +

                test_cases.battery.scenarios module

                +
                +
                +

                test_cases.battery.sim module

                +
                +
                +

                test_cases.battery.voltdump2 module

                +
                +
                +

                Module contents

                +
                +
                + + +
                +
                + +
                +
                +
                +
                + + + + \ No newline at end of file diff --git a/docs/build/test_cases.html b/docs/build/test_cases.html new file mode 100644 index 000000000..497a6a22b --- /dev/null +++ b/docs/build/test_cases.html @@ -0,0 +1,171 @@ + + + + + + + Test cases — EV-Ecosim 1.0.0 documentation + + + + + + + + + + + + + + + + + +
                + + +
                + + +
                +
                + + + + \ No newline at end of file diff --git a/docs/source/batt_sys_identification.rst b/docs/source/batt_sys_identification.rst new file mode 100644 index 000000000..7f758d41c --- /dev/null +++ b/docs/source/batt_sys_identification.rst @@ -0,0 +1,12 @@ +Battery System Identification +================ + +Submodules +---------- + +Battery system identification +------------------------------ +.. automodule:: batt_sys_identification.battery_identification + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/modules.rst b/docs/source/modules.rst index a328dd802..d1aadf509 100644 --- a/docs/source/modules.rst +++ b/docs/source/modules.rst @@ -3,9 +3,11 @@ Packages .. toctree:: :maxdepth: 4 - analysis - charging_sim feeder_population + batt_sys_identification + charging_sim test_cases + analysis +