def update_CP_state(CP_name, dt_sim_time): #Check if EV is there CP_obj = gridlabd.get_object(CP_name) EV_name = 'EV_' + CP_name.split('_')[-1] EV_obj = gridlabd.get_object(EV_name) #New car arrived #import pdb; pdb.set_trace() #print(int(CP_obj['EV_connected'])) if int( CP_obj['EV_connected'] ) == 1: #This should be whatever signal which pushes the new that a car arrived/disconnected #import pdb; pdb.set_trace() Kev = float(EV_obj['Kev']) tdep = pandas.to_datetime(EV_obj['tdep']) Emax = float(EV_obj['battery_capacity']) DeltaE = float(EV_obj['DeltaE']) #Write to database parameter_string = '(timedate, Kev, tdep, Emax, DeltaE)' value_tuple = ( str(dt_sim_time), str(Kev), str(tdep), Emax, DeltaE, ) myfct.set_values(EV_name + '_state_in', parameter_string, value_tuple) #Reset action pointer gridlabd.set_value(CP_name, 'EV_connected', str(0)) elif int(CP_obj['EV_connected']) == -1: gridlabd.set_value(CP_name, 'EV_connected', str(0))
def simulate_EVs(house_name, dt_sim_time): EV_name = 'EV' + house_name[5:] EV_obj = gridlabd.get_object(EV_name) online_t = EV_obj['generator_status'] CP_inv_name = 'EV_inverter' + house_name[5:] if dt_sim_time.hour >= 0 and dt_sim_time.hour <= 19: if online_t == 'OFFLINE': arrival = numpy.random.choice([True, False], p=[10 / 60., 1. - 10 / 60.]) if arrival: #Actual physical parameters gridlabd.set_value(EV_name, 'generator_status', 'ONLINE') soc = numpy.random.uniform(0.2, 0.8) gridlabd.set_value(EV_name, 'state_of_charge', str(soc)) #Unknow in TESS #Settings through User App Kev = numpy.random.uniform(0.5, 1.5) gridlabd.set_value(EV_name, 'Kev', str(Kev)) tdep = dt_sim_time + pandas.Timedelta( hours=7) + pandas.Timedelta( minutes=random.randint(0, 60 * 1)) gridlabd.set_value(EV_name, 'tdep', str(tdep)) DeltaE = max( numpy.random.choice(numpy.arange(5., 30., 5.), p=[1 / 5.] * 5), (1. - soc) * 100.) gridlabd.set_value(EV_name, 'DeltaE', str(DeltaE)) gridlabd.set_value(CP_inv_name, 'EV_connected', str(1)) if online_t == 'ONLINE': #EV_obj = gridlabd.get_object(EV_name) #get new departure time if pandas.to_datetime(EV_obj['tdep']) < dt_sim_time: gridlabd.set_value(EV_name, 'generator_status', 'OFFLINE') gridlabd.set_value(CP_inv_name, 'EV_connected', str(-1))
def get_settings_EVs_rnd(EVlist, interval, mysql=False): cols_EV = [ 'EV_name', 'house_name', 'SOC_max', 'i_max', 'v_max', 'u_max', 'efficiency', 'charging_type', 'k', 'soc_t', 'SOC_t', 'connected', 'next_event', 'active_t-1', 'active_t' ] df_EV = pandas.DataFrame(columns=cols_EV) start_time = dt_sim_time = parser.parse( gridlabd.get_global('clock')).replace(tzinfo=None) for EV in EVlist: house_name = 'GLD_' + EV[3:] EV_obj = gridlabd.get_object(EV) #Determine some values v_max = float(EV_obj['V_Max']) #keep v_max constant for now SOC_max = np.random.choice(list_SOC) #in kWh gridlabd.set_value(EV, 'battery_capacity', str(SOC_max * 1000)) u_max = np.random.choice(list_u) #in kW i_max = 1000 * u_max / v_max gridlabd.set_value(EV, 'I_Max', str(i_max)) eff = float(EV_obj['base_efficiency']) charging_type = EV_obj['charging_type'] k = float(EV_obj['k']) #no market: always highest wllingsness to pay #Randomly generate SOC at midnight soc_t = np.random.uniform(0.2, 0.8) #relative soc soc_t = soc_t + ( 1. - soc_t ) / 2. #No EV connected yet - at midnight, initialize with 50% charged already gridlabd.set_value(EV, 'state_of_charge', str(soc_t)) SOC_t = soc_t * SOC_max connected = 1 #Set EV gridlabd.set_value(EV, 'generator_status', 'ONLINE') #gridlabd.set_value(EV,'state_of_charge',str(next_soc)) #gridlabd.set_value(EV,'battery_capacity',str(next_socmax*1000)) #i_max = 1000*next_u/df_EV_state['v_max'].loc[EV] #gridlabd.set_value(EV,'I_Max',str(i_max)) gridlabd.set_value(EV, 'P_Max', str(u_max * 1000)) gridlabd.set_value(EV, 'E_Max', str(u_max * 1000 * 1)) EV_inv = 'EV_inverter' + EV[2:] #import pdb; pdb.set_trace() gridlabd.set_value(EV_inv, 'rated_power', str(1.2 * u_max * 1000)) gridlabd.set_value(EV_inv, 'rated_battery_power', str(1.2 * u_max * 1000)) #import pdb; pdb.set_trace() next_event = start_time + pandas.Timedelta( hours=np.random.choice(dep_hours), minutes=np.random.choice(range(60))) #Next event: disconnection #Save df_EV = df_EV.append(pandas.Series([ EV, house_name, SOC_max, i_max, v_max, u_max, eff, charging_type, k, soc_t, SOC_t, connected, next_event, 0, 0 ], index=cols_EV), ignore_index=True) df_EV.set_index('EV_name', inplace=True) #Maybe drop all columns which are not used in this glm #import pdb; pdb.set_trace() return df_EV
def get_houseobjects(house_name, time): #Get information from physical representation house_obj = gridlabd.get_object(house_name) #GUSTAVO: API implementation #Switch off default control gridlabd.set_value(house_name, 'thermostat_control', 'NONE') gridlabd.set_value(house_name, 'system_mode', 'OFF') #Read out settings k = float(house_obj['k']) T_max = float(house_obj['T_max']) cooling_setpoint = float(house_obj['cooling_setpoint']) cooling_demand = float( house_obj['cooling_demand']) #cooling_demand is in kW T_min = float(house_obj['T_min']) heating_setpoint = float(house_obj['heating_setpoint']) heating_demand = float( house_obj['heating_demand']) #heating_demand is in kW #Save in long-term memory (in the db) - accessible for market code parameter_string = '(timedate, k, T_min, heating_setpoint, T_max, cooling_setpoint)' #timedate TIMESTAMP PRIMARY KEY, value_tuple = ( time, k, T_min, heating_setpoint, T_max, cooling_setpoint, ) myfct.set_values(house_name + '_settings', parameter_string, value_tuple) return
def update_house_state(house_name, dt_sim_time): #Get information from physical representation house_obj = gridlabd.get_object(house_name) #Determine principal mode #DAVE: this is a heuristic T_air = float(house_obj['air_temperature']) if T_air >= (float(house_obj['heating_setpoint']) + float(house_obj['cooling_setpoint'])) / 2: mode = 'COOL' else: mode = 'HEAT' actual_mode = house_obj['system_mode'] #Save in long-term memory (in the db) - accessible for market code parameter_string = '(timedate, mode, actual_mode, T_air, q_heat, q_cool)' #timedate TIMESTAMP PRIMARY KEY, value_tuple = ( dt_sim_time, mode, actual_mode, T_air, float(house_obj['heating_demand']), float(house_obj['cooling_demand']), ) myfct.set_values(house_name + '_state_in', parameter_string, value_tuple) return
def get_settings_batteries(batterylist, interval, mysql=False): dt = parser.parse(gridlabd.get_global('clock')) #Better: getstart time! #prev_timedate = dt - timedelta(minutes=interval/60) #Prepare dataframe to save settings and current state cols_battery = [ 'battery_name', 'house_name', 'SOC_min', 'SOC_max', 'i_max', 'u_max', 'efficiency', 'SOC_t', 'active_t-1', 'active_t', 'threshold_sell', 'threshold_buy' ] df_battery = pandas.DataFrame(columns=cols_battery) for battery in batterylist: battery_obj = gridlabd.get_object(battery) house_name = 'GLD_' + battery[8:] #Fills TABLE market_appliances SOC_min = float(battery_obj['reserve_state_of_charge']) #in % SOC_max = float( battery_obj['battery_capacity']) / 1000 #Wh in Gridlabd -> kWh str_i_max = battery_obj['I_Max'].replace('-', '+') i_max = str_i_max.split('+')[1] u_max = float(battery_obj['V_Max']) * float( i_max) / 1000 #W -> kW #better inverter? eff = float(battery_obj['base_efficiency']) #Fills TABLE market_appliance_meter SOC_0 = float(battery_obj['state_of_charge']) * SOC_max df_battery = df_battery.append(pandas.Series([ battery, house_name, SOC_min, SOC_max, i_max, u_max, eff, SOC_0, 0, 0, 0.0, 0.0 ], index=cols_battery), ignore_index=True) df_battery.set_index('battery_name', inplace=True) return df_battery
def get_settings_houses(houselist,interval,mysql=False): dt = parser.parse(gridlabd.get_global('clock')) #Better: getstart time! prev_timedate = dt - timedelta(minutes=interval/60) #Prepare dataframe to save settings and current state cols_market_hvac = ['house_name','appliance_name','k','T_min','T_max','P_heat','P_cool','heating_setpoint','cooling_setpoint','air_temperature','active'] df_market_hvac = pandas.DataFrame(columns=cols_market_hvac) #cols_market_hvac_meter = ['system_mode','av_power','active','timedate','appliance_id'] #df_market_hvac_meter = pandas.DataFrame(columns=cols_market_hvac_meter) #Iterate through all houses and collect characteristics relevant for bidding for house in houselist: #Table with all relevant settings house_obj = gridlabd.get_object(house) k = float(house_obj['k']) T_min = float(house_obj['T_min']) T_max = float(house_obj['T_max']) heat_q = float(house_obj['heating_demand']) #heating_demand is in kW hvac_q = float(house_obj['cooling_demand']) #cooling_demand is in kW heating_setpoint = float(house_obj['heating_setpoint']) cooling_setpoint = float(house_obj['cooling_setpoint']) T_air = float(house_obj['air_temperature']) df_market_hvac = df_market_hvac.append(pandas.Series([house,'HVAC_'+house[4:],k,T_min,T_max,heat_q,hvac_q,heating_setpoint,cooling_setpoint,T_air,0],index=cols_market_hvac),ignore_index=True) #DB structure according to AWS structure #if mysql: # mysql_functions.set_values('market_houses', '(house_name)',(house,)) # mysql_functions.set_values('market_HVAC', '(house_name,appliance_name,k,T_min,T_max,P_heat,P_cool)',(house,'HVAC_'+house[4:],k,T_min,T_max,heat_q,hvac_q,)) # mysql_functions.set_values('market_HVAC_meter', '(system_mode,av_power,heating_setpoint,cooling_setpoint,active,timedate,appliance_id)',('OFF',0.0,heating_setpoint,cooling_setpoint,0,prev_timedate,int(house.split('_')[-1]),)) #df_market_hvac.to_sql('market_HVAC',mycursor,if_exists='append') #, flavor='mysql') #Index = house_number df_market_hvac.index = df_market_hvac.index + 1 return df_market_hvac
def update_PV(dt_sim_time, df_PV_state): for PV in df_PV_state.index: #directly frmom mysql P_Out = float( gridlabd.get_object(df_PV_state['inverter_name'].loc[PV]) ['P_Out']) / 1000 #PV production in kW df_PV_state.at[PV, 'P_Out'] = P_Out return df_PV_state
def get_batteries(house_name, time): battery_name = 'Battery' + house_name[5:] battery_obj = gridlabd.get_object(battery_name) #Read out settings SOC_max = float(battery_obj['E_Max']) / 1000. #kWh soc_min = 0.2 #could be part of user settings soc_des = 0.5 i_max = float(battery_obj['I_Max'].split('+')[1]) u_max = float(battery_obj['rated_power']) / 1000. #kVA efficiency = float(battery_obj['round_trip_efficiency']) Kes = float(battery_obj['Kes']) #Save in long-term memory (in the db) - accessible for market code parameter_string = '(timedate, soc_des, soc_min, SOC_max, i_max, u_max, efficiency, Kes)' value_tuple = ( time, soc_des, soc_min, SOC_max, i_max, u_max, efficiency, Kes, ) myfct.set_values(battery_name + '_settings', parameter_string, value_tuple)
def update_battery(df_battery_state): #-1: discharging, 0 no activity, 1 charging #history is saved by battery recorder (P_out) df_battery_state['active_t-1'] = df_battery_state['active_t'] df_battery_state['active_t'] = 0 for batt in df_battery_state.index: #directly from mysql battery_obj = gridlabd.get_object(batt) SOC_t = float(battery_obj['state_of_charge'])*df_battery_state['SOC_max'].loc[batt] #In Wh #Losses updated by GridlabD ? df_battery_state.at[batt,'SOC_t'] = SOC_t return df_battery_state
def get_slackload( dt_sim_time): #GUSTAVO: this information comes from HCE systems load_SLACK = float(gridlabd.get_object('node_149')['measured_real_power'] ) / 1000. #measured_real_power in [W] #C - can also come from HCE setting myfct.set_values('system_load', '(timedate, C, slack_load)', ( dt_sim_time, C, load_SLACK, )) return
def update_battery_state(battery_name, dt_sim_time): #Get information from physical representation batt_obj = gridlabd.get_object(battery_name) #Save in long-term memory (in the db) - accessible for market code parameter_string = '(timedate, soc_rel)' #timedate TIMESTAMP PRIMARY KEY, value_tuple = ( dt_sim_time, float(batt_obj['state_of_charge']), ) myfct.set_values(battery_name + '_state_in', parameter_string, value_tuple)
def get_systemstate(dt_sim_time): # Simulate and save available capacity if C == 'random': available_capacity = 1000. + numpy.random.uniform( -100., 100.) # Should be an INPUT from control room else: available_capacity = C data = { 'transformer_id': transformer_id, 'feeder': 'IEEE123', 'capacity': available_capacity } requests.put(db_address + 'transformer/' + str(transformer_id), json=data) # Used capacity load_SLACK = float( gridlabd.get_object('node_149')['measured_real_power'] [:-2]) / 1000. # measured_real_power in [W] --> [kW] data = { 'transformer_id': transformer_id, 'import_capacity': available_capacity, 'export_capacity': 0., 'q': load_SLACK, 'unresp_load': load_SLACK, 'start_time': str(dt_sim_time), 'end_time': str(dt_sim_time + pandas.Timedelta(seconds=interval)) } requests.post(db_address + 'transformer_interval', json=data) # Supply cost : from WECS/control room if market_data == 'random': p = numpy.random.uniform() if p > 1.0 / 20.0: supply_cost = 0.05 else: supply_cost = 0.2 else: import sys sys.exit('External market data not implemented yet') data = { 'start_time': str(dt_sim_time), 'end_time': str(dt_sim_time + pandas.Timedelta(seconds=interval)), 'p_bid': p, 'q_bid': available_capacity, 'is_supply': True, 'comment': '', 'market_id': market_id } requests.post(db_address + 'bids', json=data) return
def update_house(dt_sim_time, df_market_hvac): #rec_obj = gridlabd.get_object('rec_T') for i in df_market_hvac.index: #directly from mysql #house_obj = gridlabd.get_object(df_market_hvac['house_name'].loc[i]) #df_market_hvac.at[i,'air_temperature'] = float(house_obj['air_temperature']) # This measures the temperature - but it's actually the temperature from -5min bec it's not synchronized yet !!! #df_market_hvac.at[i,'air_temperature_measured'] = float(gridlabd.get_value(df_market_hvac['house_name'].loc[i],'air_temperature')[:-5]) df_market_hvac.at[i, 'air_temperature'] = float( gridlabd.get_value(df_market_hvac['house_name'].loc[i], 'air_temperature')[:-5]) #Update bidding q to latest demand values #if house_obj['system_mode'] == 'HEAT': if df_market_hvac.at[ i, 'active'] == 1: #Only update if it was active before if gridlabd.get_value(df_market_hvac['house_name'].loc[i], 'system_mode') == 'HEAT': if not df_market_hvac.at[i, 'heating_system'] == 'GAS': df_market_hvac.at[i, 'P_heat'] = float( gridlabd.get_value(df_market_hvac['house_name'].loc[i], 'hvac_load')[:-3]) # else: # import pdb; pdb.set_trace() #elif house_obj['system_mode'] == 'COOL': elif gridlabd.get_value(df_market_hvac['house_name'].loc[i], 'system_mode') == 'COOL': #df_market_hvac.at[i,'P_cool'] = float(house_obj['hvac_load']) #print(gridlabd.get_value(df_market_hvac['house_name'].loc[i],'hvac_load')) df_market_hvac.at[i, 'P_cool'] = float( gridlabd.get_value(df_market_hvac['house_name'].loc[i], 'hvac_load')[:-3]) # This makes a forecast of the actual temperature in t (i.e. g(theta_t-1) = est_theta_t ) T_out = float(gridlabd.get_object('tmy_file')['temperature']) #ind_off = df_market_hvac.loc[(df_market_hvac['active'] == 0)].index df_market_hvac['air_temperature'] = df_market_hvac[ 'beta'] * df_market_hvac['air_temperature'] + ( 1. - df_market_hvac['beta']) * T_out ind_cool = df_market_hvac.loc[(df_market_hvac['active'] == 1) & ( df_market_hvac['system_mode'] == 'COOL')].index df_market_hvac['air_temperature'].loc[ ind_cool] = df_market_hvac['air_temperature'].loc[ind_cool] - ( df_market_hvac['P_cool'] * df_market_hvac['gamma_cool'] * share_t).loc[ind_cool] ind_heat = df_market_hvac.loc[(df_market_hvac['active'] == 1) & ( df_market_hvac['system_mode'] == 'HEAT')].index df_market_hvac['air_temperature'].loc[ ind_heat] = df_market_hvac['air_temperature'].loc[ind_heat] + ( df_market_hvac['P_heat'] * df_market_hvac['gamma_heat'] * share_t).loc[ind_heat] return df_market_hvac
def update_PV(dt_sim_time, df_PV_state): # Check if initialization was successful if pandas.to_datetime(start_time_str) == dt_sim_time: #import pdb; pdb.set_trace() for ind in df_PV_state.index: rated_power_inv = float( gridlabd.get_object(df_PV_state['inverter_name'].loc[ind]) ['rated_power'][:-3]) / 1000 rated_power_PV = float( gridlabd.get_object(df_PV_state['PV_name'].loc[ind]) ['rated_power'][:-3]) / 1000 df_PV_state.at[ind, 'rated_power'] = min(rated_power_inv, rated_power_PV) # Update P_Out for PV in df_PV_state.index: #directly frmom mysql P_Out = float( gridlabd.get_object(df_PV_state['inverter_name'].loc[PV])['P_Out'] [:-3]) / 1000 #PV production in kW df_PV_state.at[PV, 'P_Out'] = P_Out df_PV_state['inv_ON_t-1'] = df_PV_state['inv_ON_t'] df_PV_state['inv_ON_t'] = 1.0 # in general, the inverter is active! return df_PV_state
def get_settings(pvlist, interval, mysql=False): cols_PV = [ 'PV_name', 'house_name', 'inverter_name', 'rated_power', 'P_Out' ] df_PV = pandas.DataFrame(columns=cols_PV) for PV in pvlist: house_name = 'GLD_' + PV[3:] inverter_name = 'PV_inverter_' + PV[3:] rated_power = float( gridlabd.get_object(inverter_name)['rated_power']) / 1000 df_PV = df_PV.append(pandas.Series( [PV, house_name, inverter_name, rated_power, 0.0], index=cols_PV), ignore_index=True) return df_PV
def find_objects(criteria): finder = criteria.split("=") if len(finder) < 2: raise Exception("find(criteria='key=value'): criteria syntax error") objects = gridlabd.get("objects") result = [] for name in objects: try: item = gridlabd.get_object(name) if finder[0] in item.keys() and item[finder[0]] == finder[1]: result.append(name) except: pass return result
def get_PVs(house_name, time): #import pdb; pdb.set_trace() PV_name = 'PV' + house_name[5:] PV_obj = gridlabd.get_object(PV_name) #Read out settings Q_rated = float(PV_obj['rated_power']) / 1000. #kWh #Save in long-term memory (in the db) - accessible for market code parameter_string = '(timedate, Q_rated)' value_tuple = ( time, Q_rated, )
def update_PV_state(PV_name, dt_sim_time): #Get information from physical representation PV_obj = gridlabd.get_object(PV_name) Qmtp = float(PV_obj['P_Out'][1:].split('+')[0]) / 1000. #kW E = Qmtp / (3600. / interval) #Save in long-term memory (in the db) - accessible for market code parameter_string = '(timedate, E, Qmtp)' #timedate TIMESTAMP PRIMARY KEY, value_tuple = ( dt_sim_time, E, Qmtp, ) myfct.set_values(PV_name + '_state_in', parameter_string, value_tuple)
def get_chargers(house_name, time): #Get charger object CP_inv_name = 'EV_inverter' + house_name[5:] CP_inv_obj = gridlabd.get_object(CP_inv_name) #Save in long-term memory (in the db) - accessible for market code Qmax = float(CP_inv_obj['rated_power']) parameter_string = '(timedate, Qmax, Qset)' value_tuple = ( time, Qmax, Qmax, ) #assume that maximum is allowed myfct.set_values('CP' + house_name[5:] + '_settings', parameter_string, value_tuple)
def include_unresp_load(dt_sim_time,retail,df_prices,df_buy_bids,df_awarded_bids): load_SLACK = float(gridlabd.get_object('node_149')['measured_real_power'])/1000 #measured_real_power in [W] print('Slack '+str(load_SLACK)) #Alternatively: All loads which have been bidding and active in prev period dt = datetime.timedelta(seconds=interval) if len(df_prices) == 0: active_prev = inel_prev = unresp_load = 0.0 else: prev_loc_supply = df_awarded_bids['bid_quantity'].loc[(df_awarded_bids['timestamp'] == (pandas.Timestamp(dt_sim_time) - pandas.Timedelta(str(int(interval/60))+' min'))) & (df_awarded_bids['S_D'] == 'S')].sum() prev_loc_demand = df_awarded_bids['bid_quantity'].loc[(df_awarded_bids['timestamp'] == (pandas.Timestamp(dt_sim_time) - pandas.Timedelta(str(int(interval/60))+' min'))) & (df_awarded_bids['S_D'] == 'D')].sum() #For baseload calculation #unresp_load = 0 #Myopic if load_forecast == 'myopic': active_prev = df_prices['clearing_quantity'].loc[dt_sim_time - dt] inel_prev = df_prices['unresponsive_loads'].loc[dt_sim_time - dt] unresp_load = (load_SLACK - max(active_prev - inel_prev,0)) * unresp_factor #Myopic based on awarded bids #Works only if no WS market bids or unresp load in df_awarded! unresp_load = (load_SLACK - prev_loc_demand + prev_loc_supply)*unresp_factor #Perfect max forecast elif load_forecast == 'perfect': df_baseload = pandas.read_csv('glm_generation_'+city+'/perfect_baseload_forecast_'+month+'.csv') df_baseload['# timestamp'] = df_baseload['# timestamp'].str.replace(r' UTC$', '') df_baseload['# timestamp'] = pandas.to_datetime(df_baseload['# timestamp']) df_baseload.set_index('# timestamp',inplace=True) last_baseload = df_baseload['baseload'].loc[dt_sim_time - pandas.Timedelta('1 min')] max_baseload = df_baseload['baseload'].loc[(df_baseload.index >= dt_sim_time) & (df_baseload.index < dt_sim_time + pandas.Timedelta(str(int(interval/60))+' min'))].max() unresp_load = load_SLACK - prev_loc_demand + prev_loc_supply - last_baseload + max_baseload if unresp_factor > 1.0: import pdb; pdb.set_trace() import sys sys.exit('Add noise through unresp_factor') else: import sys; sys.exit('No such load forecast') print('Unresp load: '+str(unresp_load)) retail.buy(unresp_load,appliance_name='unresp') df_buy_bids = df_buy_bids.append(pandas.DataFrame(columns=df_buy_bids.columns,data=[[dt_sim_time,'unresponsive_loads',p_max,round(float(unresp_load),prec)]]),ignore_index=True) #mysql_functions.set_values('buy_bids', '(bid_price,bid_quantity,timedate,appliance_name)',(p_max,round(float(unresp_load),prec),dt_sim_time,'unresponsive_loads',)) return retail, load_SLACK, unresp_load, df_buy_bids
def initialize_EVs(house_name, time): #Check if EV is connected EV_name = 'EV' + house_name[5:] try: EV_obj = gridlabd.get_object(EV_name) status = True except: status = False if status: parameter_string = '(timedate, Kev, tdep, Emax, DeltaE)' try: Kev = float(EV_obj['Kev']) except: Kev = 1.0 try: tdep = pandas.to_datetime(EV_obj['tdep']) except: #Assuming that departure is in the morning t0 = pandas.to_datetime(time) t0.hours = 0 tdep = t0 + pandas.Timedelta(hours=0) + pandas.Timedelta( minutes=random.randint(0, 60 * 1)) gridlabd.set_value(EV_name, 'tdep', str(tdep)) try: Emax = float(EV_obj['battery_capacity']) except: Emax = 1000.0 #Set very large try: DeltaE = float(EV_obj['DeltaE']) except: DeltaE = 100.0 #100% / full charge if DeltaE == 0.0: DeltaE = 100.0 value_tuple = ( time, str(Kev), str(tdep), Emax, DeltaE, ) myfct.set_values(EV_name + '_state_in', parameter_string, value_tuple)
def update_PV_state(PV, dt_sim_time): PV_obj = gridlabd.get_object('PV_' + str( PV.id)) # In GLD, this is actually the state from one interval before Qmtp = float(PV_obj['P_Out'][1:].split('+')[0]) / 1000. # W -> kW E = Qmtp / (3600. / interval) #Post state to TESS DB (simulation time) - should have an alpha_t data = { 'rate_id': 1, 'meter_id': PV.meter, 'start_time': str(dt_sim_time), 'end_time': str(dt_sim_time + pandas.Timedelta(minutes=5)), 'e': E, 'qmtp': Qmtp, 'p_bid': -1000., 'q_bid': -1000., 'is_bid': True } requests.post(db_address + 'meter_interval', json=data) #with dummy bid
def update_EV_state(battery_name, dt_sim_time): #Get information from physical representation EV_obj = gridlabd.get_object(EV_name) #Save in long-term memory (in the db) - accessible for market code E = float(EV_obj['state_of_charge']) # treq = # trem # Eest # Qset # Qobs parameter_string = '(timedate, E, treq, trem, Qset, Qobs)' #timedate TIMESTAMP PRIMARY KEY, value_tuple = ( dt_sim_time, E, treq, trem, Qset, Qobs, ) myfct.set_values(battery_name + '_state_in', parameter_string, value_tuple)
def update_EV(dt_sim_time, df_EV_state): print('Update EV') df_EV_state['active_t-1'] = df_EV_state['active_t'] df_EV_state['active_t'] = 0 df_events = pandas.read_csv('EV_events_pop.csv', index_col=[0], parse_dates=df_EV_state.index.tolist()) for EV in df_EV_state.index: EV_number = int(EV.split('_')[-1]) next_event, next_u, next_soc, next_socmax = df_events[[ EV, EV + '_u', EV + '_SOC', EV + '_SOCmax' ]].iloc[0] next_event = next_event.to_pydatetime() #Event change if next_event <= dt_sim_time: #event change in the last period -> change in status of battery #prev_event, prev_soc = df_events[[EV,EV+'_SOC']].iloc[0] df_events[[EV, EV + '_u', EV + '_SOC', EV + '_SOCmax']] = df_events[[ EV, EV + '_u', EV + '_SOC', EV + '_SOCmax' ]].shift(-1) #Randomly choose for fast-charging if EV_speed == 'fast': energy_refuel = (1. - next_soc) * next_socmax list_EVs = [(24., 22.), (50., 32.), (50., 60.), (120., 90.)] EV_type = np.random.choice(len(list_EVs), 1)[0] next_u, next_socmax = list_EVs[EV_type] next_soc = max(next_socmax - energy_refuel, 0.0) / next_socmax #next_event, next_soc = df_events[[EV,EV+'_SOC']].iloc[0] if not np.isnan(next_soc): #Set EV gridlabd.set_value(EV, 'generator_status', 'ONLINE') gridlabd.set_value(EV, 'state_of_charge', str(next_soc)) gridlabd.set_value(EV, 'battery_capacity', str(next_socmax * 1000)) i_max = 1000 * next_u / df_EV_state['v_max'].loc[EV] gridlabd.set_value(EV, 'I_Max', str(i_max)) gridlabd.set_value(EV, 'P_Max', str(next_u * 1000)) gridlabd.set_value(EV, 'E_Max', str(next_u * 1000 * 1)) EV_inv = 'EV_inverter' + EV[2:] gridlabd.set_value(EV_inv, 'rated_power', str(1.2 * next_u * 1000)) gridlabd.set_value(EV_inv, 'rated_battery_power', str(1.2 * next_u * 1000)) #import pdb; pdb.set_trace() #Set df_EV_state df_EV_state.at[EV, 'SOC_max'] = next_socmax df_EV_state.at[EV, 'i_max'] = i_max df_EV_state.at[EV, 'u_max'] = next_u df_EV_state.at[ EV, 'connected'] = 1 #Does this one not work such that delay in connection? df_EV_state.at[EV, 'soc_t'] = next_soc df_EV_state.at[EV, 'SOC_t'] = next_soc * next_socmax df_EV_state.at[EV, 'next_event'] = next_event else: #if next event associated with non-NaN SOC - now connected and pot. charging #Set EV (only switch off) gridlabd.set_value(EV, 'generator_status', 'OFFLINE') gridlabd.set_value(EV, 'state_of_charge', str(0.0)) #Set df_EV_state df_EV_state.at[EV, 'SOC_max'] = 0.0 df_EV_state.at[EV, 'i_max'] = 0.0 df_EV_state.at[EV, 'u_max'] = 0.0 df_EV_state.at[ EV, 'connected'] = 0 #Does this one not work such that delay in connection? df_EV_state.at[EV, 'soc_t'] = 0.0 df_EV_state.at[EV, 'SOC_t'] = 0.0 df_EV_state.at[EV, 'next_event'] = next_event #After last event (no upcoming events) elif pandas.isnull(next_event): #Set EV (only switch off) gridlabd.set_value(EV, 'generator_status', 'OFFLINE') #Set df_EV_state df_EV_state.at[EV, 'SOC_max'] = 0.0 df_EV_state.at[EV, 'i_max'] = 0.0 df_EV_state.at[EV, 'u_max'] = 0.0 df_EV_state.at[ EV, 'connected'] = 0 #Does this one not work such that delay in connection? df_EV_state.at[EV, 'soc_t'] = 0.0 df_EV_state.at[EV, 'SOC_t'] = 0.0 df_EV_state.at[EV, 'next_event'] = next_event #During charging event: Update EV state (SOC) elif pandas.isnull(next_socmax): # Updating through GridlabD model EV_obj = gridlabd.get_object(EV) soc_t = float(EV_obj['state_of_charge']) df_EV_state.at[EV, 'soc_t'] = soc_t SOC_t = soc_t * float( EV_obj['battery_capacity'] ) / 1000 #In Wh #Losses updated by GridlabD ? df_EV_state.at[EV, 'SOC_t'] = SOC_t # Updating using df #print('GLD battery model is not used, manual updating!') #gridlabd.set_value(EV,'state_of_charge',str(df_EV_state['soc_t'].loc[EV])) #in p.u. else: pass df_events.to_csv('EV_events_pop.csv') return df_EV_state
def get_houseobjects(house_name, time): #Get information from physical representation house_obj = gridlabd.get_object(house_name) return
def compute_bill(gridlabd, **kwargs): global csvwriter verbose = gridlabd.get_global("verbose") == "TRUE" global csvfile # get data classname = kwargs['classname'] id = kwargs['id'] data = kwargs['data'] bill_name = f"{classname}:{id}" bill = gridlabd.get_object(bill_name) bill_name = bill["name"] baseline = to_float(bill["baseline_demand"]) tariff = gridlabd.get_object(bill["tariff"]) meter = gridlabd.get_object(bill["meter"]) energy = to_float(meter["measured_real_energy"]) / 1000 # units in kW # get duration clock = to_datetime(gridlabd.get_global('clock'), '%Y-%m-%d %H:%M:%S %Z') if not "lastreading" in data.keys(): duration = timedelta(0) else: duration = clock - data["lastreading"] data["lastreading"] = clock billing_days = (duration.total_seconds() / 86400) # seconds in a day # compute energy usage if not "lastenergy" in data.keys(): usage = 0.0 else: usage = energy - data["lastenergy"] data["lastenergy"] = energy # calculate bill tariff_name = tariff["name"] meter_name = meter["name"] if verbose: gridlabd.output( f"Bill '{bill_name}' for meter '{meter_name}' on tariff '{tariff_name}' at time '{clock}':" ) gridlabd.output(f" Billing days..... %5.0f days" % (billing_days)) gridlabd.output(f" Meter reading.... %7.1f kWh" % (energy)) if baseline == 0.0: if verbose: gridlabd.output(f" Energy usage..... %7.1f kWh" % (usage)) charges = usage * to_float(tariff["energy_charge_base"]) else: tier1 = min(usage, baseline * billing_days) tier2 = min(usage - tier1, baseline * billing_days * 4) tier3 = usage - tier1 - tier2 if verbose: gridlabd.output(f" Tier 1 usage..... %7.1f kWh" % (tier1)) if tier2 > 0: gridlabd.output(f" Tier 2 usage..... %7.1f kWh" % (tier2)) if tier3 > 0: gridlabd.output(f" Tier 3 usage..... %7.1f kWh" % (tier3)) charges = tier1 * to_float( tariff["energy_charge_base"]) + tier2 * to_float( tariff["energy_charge_100"]) + tier3 * to_float( tariff["energy_charge_400"]) # apply discount, if any discount = to_float(tariff["discount"]) if discount > 0: charges -= usage * discount # apply daily minimum minimum = to_float(tariff["minimum_daily_charge"]) if charges < minimum * billing_days: charges = minimum * billing_days if verbose: gridlabd.output(f" Energy charges... %8.2f US$" % (charges)) # output billing record only if charges are non-zero if charges > 0: csvwriter.writerow([ clock.strftime('%Y-%m-%d'), meter_name, tariff_name, int(billing_days), round(usage, 1), 0, round(charges, 2) ]) csvfile.flush() # update billing data gridlabd.set_value(bill_name, "total_bill", str(to_float(bill["total_bill"]) + charges)) gridlabd.set_value(bill_name, "billing_days", str(billing_days)) gridlabd.set_value(bill_name, "energy_charges", str(to_float(bill["energy_charges"]) + charges)) gridlabd.set_value(bill_name, "total_charges", str(to_float(bill["total_charges"]) + charges))
def on_init(t): """GridLAB-D initialization event handler Parameter: t (int): initial timestamp Return: bool: success (True) or failure (False) """ global output_folder global object_list global target_properties # get the output folder name from the global variable list output_folder = gridlabd.get_global("OUTPUT") # if none is defined if not output_folder: # use the current working direction output_folder = "." # if objects to consider are not specified if not object_list: # use list of all objects object_list = gridlabd.get("objects") # for each object in the object list for objname in object_list: # the object's class classname = gridlabd.get_value(objname,"class") # if the class is listed among the targets for classname, target_list in target_properties.items(): # get the object's data objdata = gridlabd.get_object(objname) # if the object has phase data if "phases" in objdata.keys(): # get the object's class structure classdata = gridlabd.get_class(classname) # for each property in the class's target property list for property_name, limittype in target_list.items(): # get the property pattern to use, and replace phase information pattern, if any pattern = property_name.replace("{phases}",f"[{objdata['phases']}]") # for each property in the class for propname in classdata.keys(): # if the property matches the pattern if re.match(pattern,propname): # add the property to the list of properties to consider add_property(objname,propname,limittype,nonzero=False) # successfully initialized return True
def calc_bids_HVAC_stationary(dt_sim_time, df_house_state, retail, mean_p, var_p): T_out = float(gridlabd.get_object('tmy_file')['temperature']) #duty_cycle = pandas.read_csv('glm_generation_Austin/HVAC_dutycycle.csv',index_col=[0])[str(dt_sim_time.hour)].loc[dt_sim_time.month] #p_min = scipy.stats.norm.ppf(duty_cycle,loc=mean_p,scale=var_p) #var_p is std #offset = 1.0 df_house_state['active'] = 0 #Reset from last period df_bids = df_house_state.copy() #Calculate bid prices df_bids['bid_p'] = 0.0 #default df_bids['system_mode'] = 'OFF' #default df_bids['m'] = 0.0 #default df_bids['air_temperature_t+1'] = 0.0 #import pdb; pdb.set_trace() #print(str(dt_sim_time)+ ': ' + str(df_bids.loc[df_bids['appliance_name'] == 'HVAC_B1_N30_A_0334']['air_temperature'].iloc[0])) #determine mode : # original #df_bids['T_h0'] = df_bids['T_min'] + (df_bids['T_max'] - df_bids['T_min'])/2 - delta/2 #df_bids['T_c0'] = df_bids['T_min'] + (df_bids['T_max'] - df_bids['T_min'])/2 + delta/2 # test 2021/01/16 #import pdb; pdb.set_trace() df_bids['T_h0'] = df_bids['comf_temperature'] - delta * ( df_bids['comf_temperature'] - df_bids['heating_setpoint']) / ( df_bids['cooling_setpoint'] - df_bids['heating_setpoint']) df_bids['T_c0'] = df_bids['comf_temperature'] + delta * ( df_bids['cooling_setpoint'] - df_bids['comf_temperature']) / ( df_bids['cooling_setpoint'] - df_bids['heating_setpoint']) #if dt_sim_time >= pandas.Timestamp(2016,8,2,1): # import pdb; pdb.set_trace() #heating df_bids['system_mode'].loc[ df_bids['air_temperature'] <= df_bids['T_h0']] = 'HEAT' df_bids['m'].loc[df_bids['air_temperature'] <= df_bids['T_h0']] = 1. heat_ind = df_bids.loc[df_bids['system_mode'] == 'HEAT'].index #import pdb; pdb.set_trace() #VZ testen (m) #df_bids['air_temperature_t+1'] = df_bids['beta']*df_bids['air_temperature'] + (1. - df_bids['beta'])*T_out + df_bids['m']*df_bids['P_heat']*df_bids['gamma_heat'] df_bids['air_temperature_t+1'] = df_bids['beta'] * df_bids[ 'air_temperature'] + (1. - df_bids['beta']) * T_out + df_bids[ 'm'] * df_bids['P_heat'] * df_bids['gamma_heat'] * share_t df_bids['air_temperature_mean'] = (df_bids['air_temperature'] + df_bids['air_temperature_t+1']) / 2. #df_bids['air_temperature_mean'] = df_bids['air_temperature'] #import pdb; pdb.set_trace() df_bids['bid_p'].loc[heat_ind] = ( 2 * df_bids['alpha'] * df_bids['gamma_heat'] * (df_bids['comf_temperature'] - df_bids['air_temperature_mean']) / (1. - df_bids['beta'])).loc[heat_ind] df_bids['bid_p'].loc[ heat_ind] = df_bids['bid_p'].loc[heat_ind] * 1000. #USD/MWh #df_bids['bid_p'].loc[df_bids['air_temperature'] <= df_bids['T_min']] = retail.Pmax #cooling df_bids['system_mode'].loc[ df_bids['air_temperature'] >= df_bids['T_c0']] = 'COOL' df_bids['m'].loc[df_bids['air_temperature'] >= df_bids['T_c0']] = -1. cool_ind = df_bids.loc[df_bids['system_mode'] == 'COOL'].index #df_bids['air_temperature_t+1'] = df_bids['beta']*df_bids['air_temperature'] + (1. - df_bids['beta'])*T_out + df_bids['m']*df_bids['P_cool']*df_bids['gamma_cool'] #import pdb; pdb.set_trace() # check gamma_cool <0 und Virzeichen df_bids['air_temperature_t+1'] = df_bids['beta'] * df_bids[ 'air_temperature'] + (1. - df_bids['beta']) * T_out + df_bids[ 'm'] * df_bids['P_cool'] * df_bids['gamma_cool'] * share_t df_bids['air_temperature_mean'] = (df_bids['air_temperature'] + df_bids['air_temperature_t+1']) / 2. #df_bids['air_temperature_mean'] = df_bids['air_temperature'] df_bids['bid_p'].loc[cool_ind] = ( 2 * df_bids['alpha'] * df_bids['gamma_cool'] * (df_bids['air_temperature_mean'] - df_bids['comf_temperature']) / (1. - df_bids['beta'])).loc[cool_ind] df_bids['bid_p'].loc[ cool_ind] = df_bids['bid_p'].loc[cool_ind] * 1000. #USD/MWh #df_bids['bid_p'].loc[df_bids['air_temperature'] >= df_bids['T_max']] = retail.Pmax """Should we enable negative prices?""" df_bids['lower_bound'] = 0.0 df_bids['upper_bound'] = retail.Pmax df_bids['bid_p'] = df_bids[['bid_p', 'lower_bound']].max(axis=1) df_bids['bid_p'] = df_bids[['bid_p', 'upper_bound']].min( axis=1 ) #just below the price cap; set upper bound according to global! #DO MERGE INSTEAD!!! df_house_state['bid_p'] = df_bids['bid_p'] df_house_state['system_mode'] = df_bids['system_mode'] return df_house_state
def get_settings_EVs(EVlist, interval, mysql=False): cols_EV = [ 'EV_name', 'house_name', 'SOC_max', 'i_max', 'v_max', 'u_max', 'efficiency', 'charging_type', 'k', 'soc_t', 'SOC_t', 'connected', 'next_event', 'active_t-1', 'active_t' ] df_EV = pandas.DataFrame(columns=cols_EV) #Read in charging events #df_events = pandas.read_csv('EV_events_2016_july_Austin.csv',index_col=[0],parse_dates=True) #'EV_events_2015_july.csv' df_events = pandas.read_csv(EV_data, index_col=[0], parse_dates=True) first_time = pandas.Timestamp.today() first_time = first_time.replace(year=first_time.year + 4) #to ensure working with RT data for EV in EVlist: df_events[EV] = pandas.to_datetime(df_events[EV]) if df_events[EV].min() < first_time: first_time = df_events[EV].min() first_time = first_time.replace(hour=0, minute=0, second=0) start_time = pandas.to_datetime(start_time_str) delta = start_time - first_time for EV in EVlist: df_events[EV] = df_events[EV] + delta EV_obj = gridlabd.get_object(EV) #gridlabd.set_value(EV,'use_internal_battery_model','FALSE') house_name = 'GLD_' + EV[3:] #Use GridLABD default values v_max = float(EV_obj['V_Max']) #keep v_max constant for now eff = float(EV_obj['base_efficiency']) #Fills TABLE market_appliances #SOC_min = float(EV_obj['reserve_state_of_charge']) #in % - 20% #SOC_max = float(EV_obj['battery_capacity'])/1000 #Wh in Gridlabd -> kWh #str_i_max = EV_obj['I_Max'] #i_max = str_i_max.split('+')[1] #u_max = float(EV_obj['V_Max'])*float(i_max)/1000 #W -> kW #better inverter? charging_type = EV_obj['charging_type'] k = float(EV_obj['k']) #no market: always highest wllingsness to pay #Gets next event cols = [EV, EV + '_u', EV + '_SOC', EV + '_SOCmax'] df_events_EV = df_events[cols] discard_events = True while discard_events: if (df_events_EV[EV].iloc[0] < pandas.to_datetime(start_time_str) ) and (df_events_EV[EV].iloc[1] < pandas.to_datetime(start_time_str)): df_events_EV = df_events_EV.iloc[2:] elif (df_events_EV[EV].iloc[0] < pandas.to_datetime(start_time_str) ) and (df_events_EV[EV].iloc[1] > pandas.to_datetime(start_time_str)): #Get information from EV events table soc_t = df_events_EV[EV + '_SOC'].iloc[0] #relative soc u_max = df_events_EV[EV + '_u'].iloc[0] #in kW SOC_max = df_events_EV[EV + '_SOCmax'].iloc[0] #in kWh #For start of the simulation soc_t = soc_t + ( 1. - soc_t ) / 2. #No EV connected yet - at midnight, initialize with 50% charged already SOC_t = soc_t * SOC_max gridlabd.set_value(EV, 'state_of_charge', str(soc_t)) gridlabd.set_value(EV, 'battery_capacity', str(SOC_max * 1000)) i_max = 1000 * u_max / v_max gridlabd.set_value(EV, 'I_Max', str(i_max)) gridlabd.set_value(EV, 'generator_status', 'ONLINE') next_event = df_events_EV[EV].iloc[ 1] #Next event: disconnection df_events_EV = df_events_EV.iloc[ 1:] #Only discard connection event connected = 1 discard_events = False elif (df_events_EV[EV].iloc[0] > pandas.to_datetime(start_time_str) ) and (df_events_EV[EV].iloc[1] > pandas.to_datetime(start_time_str)): soc_t = 0.0 u_max = 0.0 SOC_max = 0.0 soc_t = 0.0 SOC_t = 0.0 i_max = 0.0 next_event = df_events_EV[EV].iloc[0] #Next event: connection connected = 0 gridlabd.set_value(EV, 'generator_status', 'OFFLINE') discard_events = False else: print( 'Unclear or no EV events at that charging station during that time' ) soc_t = 0.0 i_max = 0.0 next_event = pandas.to_datetime( end_time_str) #Next event: none / end_time connected = 0 gridlabd.set_value(EV, 'generator_status', 'OFFLINE') discard_events = False df_EV = df_EV.append(pandas.Series([ EV, house_name, SOC_max, i_max, v_max, u_max, eff, charging_type, k, soc_t, SOC_t, connected, next_event, 0, 0 ], index=cols_EV), ignore_index=True) df_events_EV.index = df_events_EV.index - df_events_EV.index[ 0] #reset index to range() df_events[cols] = df_events_EV[cols] df_events.to_csv('EV_events_pop.csv') df_EV.set_index('EV_name', inplace=True) #Maybe drop all columns which are not used in this glm return df_EV