def _getFncsBusMessages(simulationId): '''publish a message received from the GOSS bus to the FNCS bus. Function arguments: simulationId -- Type: string. Description: The simulation id. It must not be an empty string. Default: None. Function returns: fncsOutput -- Type: string. Description: The json structured output from the simulation. If no output was sent from the simulation then it returns None. Function exceptions: ValueError() ''' try: simulatorMessageOutput = None if simulationId == None or simulationId == '' or type( simulationId) != str: raise ValueError('simulationId must be a nonempty string.\n' + 'simulationId = {0}'.format(simulationId)) logger.debug('about to get fncs events') messageEvents = fncs.get_events() logger.debug('fncs events ' + str(messageEvents)) if simulationId in messageEvents: simulatorMessageOutput = fncs.get_value(simulationId) logger.debug('simulatorMessageOutput ' + str(simulatorMessageOutput)) return simulatorMessageOutput except Exception as e: logger.error('Error on get FncsBusMessages for ' + str(simulationId) + ' ' + str(e))
def get_messages_from_fncs(self): """publish a message received from the GOSS bus to the FNCS bus. Function arguments: simulation_id -- Type: string. Description: The simulation id. It must not be an empty string. Default: None. Function returns: fncs_output -- Type: string. Description: The json structured output from the simulation. If no output was sent from the simulation then it returns None. Function exceptions: ValueError() """ try: fncs_output = None if not self.simulation_id or type(self.simulation_id) != str: raise ValueError( 'self.simulation_id must be a nonempty string.\n' + 'simulation_id = {0}'.format(self.simulation_id)) message_str = 'about to get fncs events' self._gridappsd.send_simulation_status('RUNNING', message_str, DEBUG) message_events = fncs.get_events() message_str = 'fncs events ' + str(message_events) self._gridappsd.send_simulation_status('RUNNING', message_str, DEBUG) if self.simulation_id in message_events: fncs_output = fncs.get_value(self.simulation_id) message_str = 'fncs_output ' + str(fncs_output) self._gridappsd.send_simulation_status('RUNNING', message_str, DEBUG) return fncs_output except Exception as e: message_str = 'Error on get FncsBusMessages for ' + str(self.simulation_id) + ' ' + str(e) self._gridappsd.send_simulation_status('ERROR', message_str, ERROR)
def launch_all(): print('launching all simulators') if sys.platform == 'win32': subprocess.Popen('call run30.bat', shell=True) else: subprocess.Popen( '(export FNCS_BROKER="tcp://*:5570" && exec fncs_broker 36 &> broker.log &)', shell=True) subprocess.Popen( '(export FNCS_CONFIG_FILE=eplus.yaml && exec EnergyPlus -w ../energyplus/USA_AZ_Tucson.Intl.AP.722740_TMY3.epw -d output -r ../energyplus/SchoolDualController.idf &> eplus.log &)', shell=True) subprocess.Popen( '(export FNCS_CONFIG_FILE=eplus_json.yaml && exec eplus_json 2d 5m School_DualController eplus_TE_Challenge_metrics.json &> eplus_json.log &)', shell=True) subprocess.Popen('(exec ./launch_TE_Challenge_agents.sh &)', shell=True) subprocess.Popen( '(export FNCS_CONFIG_FILE=pypower30.yaml && export FNCS_FATAL=NO && export FNCS_LOG_STDOUT=yes && exec python fncsPYPOWER.py TE_Challenge &> pypower.log &)', shell=True) print('launched all simulators') root.update() os.environ['FNCS_CONFIG_FILE'] = 'tesp.yaml' os.environ['FNCS_FATAL'] = 'NO' print('config file =', os.environ['FNCS_CONFIG_FILE']) fncs.initialize() time_granted = 0 time_stop = 2 * 24 * 60 yaml_delta = 5 nsteps = int(time_stop / yaml_delta) hrs = np.linspace(0.0, 48.0, nsteps + 1) idxlast = -1 x0 = np.empty(nsteps + 1) x1 = np.zeros(nsteps + 1) x2 = np.zeros(nsteps + 1) x3 = np.zeros(nsteps + 1) while time_granted < time_stop: time_granted = fncs.time_request(time_stop) events = fncs.get_events() idx = int(time_granted / yaml_delta) if idx <= idxlast: continue idxlast = idx bWantX0 = True bWantX1 = True bWantX2 = True bWantX3 = True for key in events: tok = key.decode() if bWantX1 and tok == 'power_A': val = 3.0 * float( fncs.get_value(key).decode().strip('+ degFkW')) / 1000.0 x1[idx] = val ax[1].plot(hrs[1:idx], x1[1:idx], color='red') bWantX1 = False elif bWantX3 and tok == 'house_air_temperature': val = float(fncs.get_value(key).decode().strip('+ degFkW')) x3[idx] = val ax[3].plot(hrs[1:idx], x3[1:idx], color='magenta') bWantX3 = False elif bWantX0 and tok == 'vpos7': val = float( fncs.get_value(key).decode().strip('+ degFkW')) / 133000.0 x0[idx] = val ax[0].plot(hrs[1:idx], x0[1:idx], color='green') bWantX0 = False elif bWantX2 and tok == 'clear_price': val = float(fncs.get_value(key).decode().strip('+ degFkW')) x2[idx] = val ax[2].plot(hrs[1:idx], x2[1:idx], color='blue') bWantX2 = False elif bWantX2 and tok == 'LMP7': val = float(fncs.get_value(key).decode().strip('+ degFkW')) x2[idx] = val ax[2].plot(hrs[1:idx], x2[1:idx], color='blue') bWantX2 = False elif bWantX1 and tok == 'SUBSTATION7': val = float(fncs.get_value(key).decode().strip( '+ degFkW')) # already in kW x1[idx] = val ax[1].plot(hrs[1:idx], x1[1:idx], color='red') bWantX1 = False # print (time_granted, key.decode(), fncs.get_value(key).decode()) root.update() fig.canvas.draw() fncs.finalize()
print('time_granted:', time_granted, flush=True) controller_obj.day = int(time_granted / day_len) # Initialization when time = 0 if time_granted == 0: controller_obj.initController() if time_granted % deltaT == 0: flag1 = 1 #Subscribe values from GLD if time_granted != 0: events = fncs.get_events() for key in events: title = key.decode() value = fncs.get_value(key).decode() controller_obj.subscribeGLD(title, value, time_granted) if flag1 == 1: flag2 = 1 # calculating pistar if flag1 == 1 and flag2 == 1: print('', flush=True) print('time:', time_granted, 'calculating pistar...', flush=True) controller_obj.CalPiStar(time_granted) flag1 = 0 flag2 = 0 # Subscrib values from FNCS broker (or csv file here) if time_granted != 0: fncs_sub_value_String = ''
op = open(sys.argv[2], "w") # requires the zpl/yaml file fncs.initialize() print('*****FNCS HAS INITIALIZED******') print("# time key value", file=op) while time_granted < time_stop: time_granted = fncs.time_request(time_stop) events = fncs.get_events() SubKeys = [] SubKeyVals = [] for key in events: print(time_granted, key.decode(), fncs.get_value(key).decode(), file=op) Temp = str(key.decode()) SubKeys.append(Temp) Temp = str(fncs.get_value(key).decode()) SubKeyVals.append(Temp) keys, key_val = fncs_parser.synch(SubKeys, SubKeyVals) for i in range(len(keys)): print(str(keys[i])) print(str(key_val[i])) fncs.publish(str(keys[i]), str(key_val[i])) time.sleep(5) fncs.finalize() op.close()
row[7], row[11], row[12] ] gen_metrics[str(ts)] = {} for i in range(gen.shape[0]): row = gen[i].tolist() busidx = int(row[0] - 1) gen_metrics[str(ts)][str(i + 1)] = [ row[1], row[2], float(bus[busidx, 13]) * 0.001 ] tnext += dt ts = fncs.time_request(tnext) events = fncs.get_events() for key in events: substation = key.decode() GLDload = parse_mva(fncs.get_value(key).decode()) print(' **', ts, substation, GLDload) for row in fncsBus: if substation == row[1]: print(' assigning', substation, GLDload) row[3] = GLDload[0] # summarize_opf(res) fncs.finalize() print(json.dumps(bus_metrics), file=bus_mp) print(json.dumps(gen_metrics), file=gen_mp) print(json.dumps(sys_metrics), file=sys_mp) bus_mp.close() gen_mp.close() sys_mp.close() op.close()
def launch_all(): print('launching all simulators') if sys.platform == 'win32': subprocess.Popen ('call run30.bat', shell=True) else: subprocess.Popen ('(export simNum=36 && ./runVisualTE30ChallengeDocker.sh &)', shell=True) print('launched all simulators') root.update() os.environ['FNCS_CONFIG_FILE'] = 'tespTE30.yaml' os.environ['FNCS_FATAL'] = 'NO' print('config file =', os.environ['FNCS_CONFIG_FILE']) fncs.initialize() time_granted = 0 time_stop = 2 * 24 * 60 yaml_delta = 5 nsteps = int (time_stop / yaml_delta) hrs=np.linspace(0.0, 48.0, nsteps+1) idxlast = -1 x0 = np.empty(nsteps+1) x1 = np.zeros(nsteps+1) x2 = np.zeros(nsteps+1) x3 = np.zeros(nsteps+1) while time_granted < time_stop: time_granted = fncs.time_request(time_stop) events = fncs.get_events() idx = int (time_granted / yaml_delta) if idx <= idxlast: continue idxlast = idx bWantX0 = True bWantX1 = True bWantX2 = True bWantX3 = True for key in events: tok = key.decode() if bWantX1 and tok == 'power_A': val = 3.0 * float (fncs.get_value(key).decode().strip('+ degFkW')) / 1000.0 x1[idx] = val ax[1].plot(hrs[1:idx],x1[1:idx],color='red') bWantX1 = False elif bWantX3 and tok == 'house_air_temperature': val = float (fncs.get_value(key).decode().strip('+ degFkW')) x3[idx] = val ax[3].plot(hrs[1:idx],x3[1:idx],color='magenta') bWantX3 = False elif bWantX0 and tok == 'vpos7': val = float (fncs.get_value(key).decode().strip('+ degFkW')) / 133000.0 x0[idx] = val ax[0].plot(hrs[1:idx],x0[1:idx],color='green') bWantX0 = False elif bWantX2 and tok == 'clear_price': val = float (fncs.get_value(key).decode().strip('+ degFkW')) x2[idx] = val ax[2].plot(hrs[1:idx],x2[1:idx],color='blue') bWantX2 = False elif bWantX2 and tok == 'LMP7': val = float (fncs.get_value(key).decode().strip('+ degFkW')) x2[idx] = val ax[2].plot(hrs[1:idx],x2[1:idx],color='blue') bWantX2 = False elif bWantX1 and tok == 'SUBSTATION7': val = float (fncs.get_value(key).decode().strip('+ degFkW')) # already in kW x1[idx] = val ax[1].plot(hrs[1:idx],x1[1:idx],color='red') bWantX1 = False # print (time_granted, key.decode(), fncs.get_value(key).decode()) root.update() fig.canvas.draw() fncs.finalize()
sub_time = 0 while (time_granted < tf * 3600): # =================Simulation for each time step ============================================ # Initialization when time = 0 if time_granted == 0: fncs.initialize() sub_time = 0 if time_granted != 0: events = fncs.get_events() for key in events: topic = key.decode() for i in range(15): for j in range(12): if topic == houseID[i][j] + '_bidding_curves_pistar': value = float(fncs.get_value(key).decode()) list_pistar[i][j] = value if topic == houseID[i][j] + '_power_level': value = float(fncs.get_value(key).decode()) list_power_level[i][j] = value if topic == houseID[i][j] + '_rt_power': value = float(fncs.get_value(key).decode()) list_rt_power[i][j] = value if topic == 'base_line': value = float(fncs.get_value(key).decode()) base_line = value if topic == 'distribution_load': value = fncs.get_value(key).decode() value = value.replace('VA', '') distribution_load = np.real(complex(value))
def publish_heartbeat(self): '''Send heartbeat message every HEARTBEAT_PERIOD seconds. HEARTBEAT_PERIOD is set and can be adjusted in the settings module. ''' now = datetime.utcnow().isoformat(' ') + 'Z' nowdate = datetime.utcnow() print "publish_heartbeat", now timeDiff = nowdate - self.simStart valMap = defaultdict(dict) metaMap = defaultdict(dict) headers = {headers_mod.TIMESTAMP: now, headers_mod.DATE: now} #Tell FNCS we are at our next timestep if not fncs.is_initialized(): raise RuntimeError("FNCS connection was terminated. Killing Bridge.") elif self.simtime > self.simlength: fncs.finalize() self.core.stop() elif timeDiff.seconds >= 1: self.simtime+=self.heartbeat_period*self.heartbeat_multiplier print "fncs.time_request(",self.simtime,") request" self.simtime = fncs.time_request(self.simtime) print "fncs.time_request() response", self.simtime #Grab Subscriptions from FNCS to publish to Volttron message bus subKeys = fncs.get_events() if len(subKeys) > 0: for x in subKeys: valStr = fncs.get_value(x) #parse message to split value and unit valList = valStr.split(' ') if len(valList) == 1: val = valList[0] valUnit = ''; try: val = float(val) except: pass elif len(valList) == 2: val = valList[0] valUnit = valList[1] if 'int' in self.fncs_zpl['values'][x]['type']: val = int(val) elif 'double' in self.fncs_zpl['values'][x]['type']: val = float(val) elif 'complex' in self.fncs_zpl['values'][x]['type']: raise RuntimeError("complex data type is currently not supported in Volttron.") #TODO: come up with a better way to handle all types that can come in from fncs else: warnings.warn("FNCS message could not be parsed into value and unit. The message will be farwarded to Volttron message bus as is.") val = valStr valUnit = '' fncsmessage = [val, {'units' : '{0}'.format(valUnit), 'tz' : 'UTC', 'type': '{0[type]}'.format(self.fncs_zpl['values'][x])}] fncsTopic = common.FNCS_OUTPUT_PATH(path = 'devices/{0[topic]}'.format(self.fncs_zpl['values'][x])) #fncs/output/devices/topic self.vip.pubsub.publish('pubsub', fncsTopic, headers, fncsmessage).get(timeout=5) _log.debug('FNCS->Volttron:\nTopic:%s\n:Message:%s\n'%(fncsTopic, str(fncsmessage))) device, point = self.fncs_zpl['values'][x]['topic'].rsplit('/', 1) deviceAllTopic = common.FNCS_OUTPUT_PATH(path = 'devices/' + device + '/all') valMap[deviceAllTopic][point] = val metaMap[deviceAllTopic][point] = fncsmessage[1] for k in valMap.keys(): allMessage = [valMap[k], metaMap[k]] self.vip.pubsub.publish('pubsub', k, headers, allMessage).get(timeout=5) _log.debug('FNCS->Volttron:\nTopic:%s\n:Message:%s\n'%(k, str(allMessage))) #Publish heartbeat message to voltron bus self.vip.pubsub.publish( 'pubsub', '{0[name]}/heartbeat'.format(self.fncs_zpl), headers, now).get(timeout=5)
def mainLoop(self): if(self.RIAPS): self.context = zmq.Context(1) self.server = self.context.socket(zmq.REP) self.server.bind("tcp://*:5555") while self.time_granted < self.time_stop: events = fncs.get_events() for topic in events: value = fncs.get_value(topic) #Collect Most recent charge data if('batt_charge' in topic): self.batt_charges[topic] = float(value.split(" ")[0][1:]) if('solar_power' in topic): if topic in self.solar_power: self.solar_power[topic].append(float(value.split(' ')[0])) else: self.solar_power[topic] = [float(value.split(' ')[0])] if('batt_power' in topic): if topic in self.batt_power: self.batt_power[topic].append(float(value.split(' ')[0])) else: self.batt_power[topic] = [float(value.split(' ')[0])] if('step' in events): self.request = '' while(self.request != 'step'): self.msg = self.server.recv_pyobj() self.request = self.msg['request'] if (self.request == 'postTrade'): self.tradeResp() if (self.request == 'charge'): self.chargeResp() print(self.time_granted, self.request, flush=True) print("solar_power: ", self.solar_power) print("batt_power: ", self.batt_power) self.solar_power = {} self.batt_power = {} self.time_granted = fncs.time_request(self.time_stop) self.server.send_pyobj('Step Granted') else: self.time_granted = fncs.time_request(self.time_stop) print("Simulation Continue, new time_granted:", str(self.time_granted)) self.server.close() self.context.term() print('zmq Closed', flush=True) else: while self.time_granted < self.time_stop: self.time_granted = fncs.time_request(self.time_stop) events = fncs.get_events() for topic in events: value = fncs.get_value(topic) #Collect Most recent charge data if('batt_charge' in topic): self.batt_charges[topic] = value if('solar_power' in topic): self.solar_power[topic] = value print('End of Simulation', flush=True) fncs.finalize() if sys.platform != 'win32': usage = resource.getrusage(resource.RUSAGE_SELF) RESOURCES = [ ('ru_utime', 'User time'), ('ru_stime', 'System time'), ('ru_maxrss', 'Max. Resident Set Size'), ('ru_ixrss', 'Shared Memory Size'), ('ru_idrss', 'Unshared Memory Size'), ('ru_isrss', 'Stack Size'), ('ru_inblock', 'Block inputs'), ('ru_oublock', 'Block outputs')] print('Resource usage:') for name, desc in RESOURCES: print(' {:<25} ({:<10}) = {}'.format(desc, name, getattr(usage, name)))
op = open (sys.argv[2], "a") # requires the yaml file fncs.initialize() print("# time key value", file=op) events = fncs.get_events() while time_granted < time_stop: time_granted = fncs.time_request(time_stop) events = fncs.get_events() SubKeys = [] SubKeyVals = [] for key in events: print(time_granted, key.decode(), fncs.get_value(key).decode(), file=op) #for key in range( len(events) ): Temp = str( key.decode() ) + " " + str( fncs.get_value(key).decode() ) SubKeys.append( Temp ) #Temp2 = str( fncs.get_value(key).decode() ) #SubKeyVals.append( Temp2 ) #SubKey = matlab.char(SubKeys) #SubKeyVal = matlab.char( SubKeysVals ) #eng.eval('[keys, KeyVal] = DummyMAT( SubKey , SubKeyVal );',nargout=0) #key_val = eng.workspace['KeyVal'] #keys = eng.workspace['keys'] #print(key_val[0][121]) #print(keys[121]) a = eng.DummyMAT(SubKeys, nargout=2) key_val = a[1][0] keys = a[0]
import sys; import fncs; if sys.platform != 'win32': import resource time_stop = int(sys.argv[1]) time_granted = 0 # requires yaml specificied in an envar fncs.initialize() while time_granted < time_stop: time_granted = fncs.time_request(time_stop) events = fncs.get_events() for topic in events: value = fncs.get_value(topic) print (time_granted, topic, value, flush=True) if topic == 'sw_status': fncs.publish('sw_status', value) fncs.finalize() if sys.platform != 'win32': usage = resource.getrusage(resource.RUSAGE_SELF) RESOURCES = [ ('ru_utime', 'User time'), ('ru_stime', 'System time'), ('ru_maxrss', 'Max. Resident Set Size'), ('ru_ixrss', 'Shared Memory Size'), ('ru_idrss', 'Unshared Memory Size'), ('ru_isrss', 'Stack Size'),
def main_loop(): if len(sys.argv) == 2: rootname = sys.argv[1] else: print('usage: python fncsPYPOWER.py rootname') sys.exit() ppc = ppcasefile() StartTime = ppc['StartTime'] tmax = int(ppc['Tmax']) period = int(ppc['Period']) dt = int(ppc['dt']) make_dictionary(ppc, rootname) bus_mp = open("bus_" + rootname + "_metrics.json", "w") gen_mp = open("gen_" + rootname + "_metrics.json", "w") sys_mp = open("sys_" + rootname + "_metrics.json", "w") bus_meta = { 'LMP_P': { 'units': 'USD/kwh', 'index': 0 }, 'LMP_Q': { 'units': 'USD/kvarh', 'index': 1 }, 'PD': { 'units': 'MW', 'index': 2 }, 'QD': { 'units': 'MVAR', 'index': 3 }, 'Vang': { 'units': 'deg', 'index': 4 }, 'Vmag': { 'units': 'pu', 'index': 5 }, 'Vmax': { 'units': 'pu', 'index': 6 }, 'Vmin': { 'units': 'pu', 'index': 7 } } gen_meta = { 'Pgen': { 'units': 'MW', 'index': 0 }, 'Qgen': { 'units': 'MVAR', 'index': 1 }, 'LMP_P': { 'units': 'USD/kwh', 'index': 2 } } sys_meta = { 'Ploss': { 'units': 'MW', 'index': 0 }, 'Converged': { 'units': 'true/false', 'index': 1 } } bus_metrics = {'Metadata': bus_meta, 'StartTime': StartTime} gen_metrics = {'Metadata': gen_meta, 'StartTime': StartTime} sys_metrics = {'Metadata': sys_meta, 'StartTime': StartTime} gencost = ppc['gencost'] fncsBus = ppc['FNCS'] gen = ppc['gen'] ppopt_market = pp.ppoption(VERBOSE=0, OUT_ALL=0, PF_DC=1) ppopt_regular = pp.ppoption(VERBOSE=0, OUT_ALL=0, PF_DC=1) loads = np.loadtxt('NonGLDLoad.txt', delimiter=',') for row in ppc['UnitsOut']: print('unit ', row[0], 'off from', row[1], 'to', row[2], flush=True) for row in ppc['BranchesOut']: print('branch', row[0], 'out from', row[1], 'to', row[2], flush=True) nloads = loads.shape[0] ts = 0 tnext_opf = -dt # initializing for metrics collection tnext_metrics = 0 loss_accum = 0 conv_accum = True n_accum = 0 bus_accum = {} gen_accum = {} for i in range(fncsBus.shape[0]): busnum = int(fncsBus[i, 0]) bus_accum[str(busnum)] = [0, 0, 0, 0, 0, 0, 0, 99999.0] for i in range(gen.shape[0]): gen_accum[str(i + 1)] = [0, 0, 0] op = open(rootname + '.csv', 'w') print( 't[s],Converged,Pload,P7 (csv),Unresp (opf),P7 (rpf),Resp (opf),GLD Pub,BID?,P7 Min,V7,LMP_P7,LMP_Q7,Pgen1,Pgen2,Pgen3,Pgen4,Pdisp,Deg,c2,c1', file=op, flush=True) fncs.initialize() # transactive load components csv_load = 0 # from the file unresp = 0 # unresponsive load estimate from the auction agent resp = 0 # will be the responsive load as dispatched by OPF resp_deg = 0 # RESPONSIVE_DEG from FNCS resp_c1 = 0 # RESPONSIVE_C1 from FNCS resp_c2 = 0 # RESPONSIVE_C2 from FNCS resp_max = 0 # RESPONSIVE_MAX_MW from FNCS feeder_load = 0 # amplified feeder MW while ts <= tmax: # start by getting the latest inputs from GridLAB-D and the auction events = fncs.get_events() new_bid = False load_scale = float(fncsBus[0][2]) for key in events: topic = key.decode() if topic == 'UNRESPONSIVE_MW': unresp = load_scale * float(fncs.get_value(key).decode()) fncsBus[0][ 3] = unresp # to poke unresponsive estimate into the bus load slot new_bid = True elif topic == 'RESPONSIVE_MAX_MW': resp_max = load_scale * float(fncs.get_value(key).decode()) new_bid = True elif topic == 'RESPONSIVE_C2': resp_c2 = float(fncs.get_value(key).decode()) / load_scale new_bid = True elif topic == 'RESPONSIVE_C1': resp_c1 = float(fncs.get_value(key).decode()) new_bid = True elif topic == 'RESPONSIVE_DEG': resp_deg = int(fncs.get_value(key).decode()) new_bid = True else: gld_load = parse_mva(fncs.get_value(key).decode( )) # actual value, may not match unresp + resp load feeder_load = float(gld_load[0]) * load_scale if new_bid == True: dummy = 2 # print('**Bid', ts, unresp, resp_max, resp_deg, resp_c2, resp_c1) # update the case for bids, outages and CSV loads idx = int((ts + dt) / period) % nloads bus = ppc['bus'] gen = ppc['gen'] branch = ppc['branch'] gencost = ppc['gencost'] csv_load = loads[idx, 0] bus[4, 2] = loads[idx, 1] bus[8, 2] = loads[idx, 2] # process the generator and branch outages for row in ppc['UnitsOut']: if ts >= row[1] and ts <= row[2]: gen[row[0], 7] = 0 else: gen[row[0], 7] = 1 for row in ppc['BranchesOut']: if ts >= row[1] and ts <= row[2]: branch[row[0], 10] = 0 else: branch[row[0], 10] = 1 if resp_deg == 2: gencost[4][3] = 3 gencost[4][4] = -resp_c2 gencost[4][5] = resp_c1 elif resp_deg == 1: gencost[4][3] = 2 gencost[4][4] = resp_c1 gencost[4][5] = 0.0 else: gencost[4][3] = 1 gencost[4][4] = 999.0 gencost[4][5] = 0.0 gencost[4][6] = 0.0 if ts >= tnext_opf: # expecting to solve opf one dt before the market clearing period ends, so GridLAB-D has time to use it # for OPF, the FNCS bus load is CSV + Unresponsive estimate, with Responsive separately dispatchable bus = ppc['bus'] gen = ppc['gen'] bus[6, 2] = csv_load for row in ppc['FNCS']: unresp = float(row[3]) newidx = int(row[0]) - 1 if unresp >= feeder_load: bus[newidx, 2] += unresp else: bus[newidx, 2] += unresp # feeder_load gen[4][9] = -resp_max res = pp.runopf(ppc, ppopt_market) if res['success'] == False: conv_accum = False opf_bus = deepcopy(res['bus']) opf_gen = deepcopy(res['gen']) lmp = opf_bus[6, 13] resp = -1.0 * opf_gen[4, 1] fncs.publish('LMP_B7', 0.001 * lmp) # publishing $/kwh print(' OPF', ts, csv_load, '{:.3f}'.format(unresp), '{:.3f}'.format(resp), '{:.3f}'.format(feeder_load), '{:.3f}'.format(opf_bus[6, 2]), '{:.3f}'.format(opf_gen[0, 1]), '{:.3f}'.format(opf_gen[1, 1]), '{:.3f}'.format(opf_gen[2, 1]), '{:.3f}'.format(opf_gen[3, 1]), '{:.3f}'.format(opf_gen[4, 1]), '{:.3f}'.format(lmp)) # if unit 2 (the normal swing bus) is dispatched at max, change the swing bus to 9 if opf_gen[1, 1] >= 191.0: ppc['bus'][1, 1] = 2 ppc['bus'][8, 1] = 3 print(' SWING Bus 9') else: ppc['bus'][1, 1] = 3 ppc['bus'][8, 1] = 1 print(' SWING Bus 2') tnext_opf += period # always update the electrical quantities with a regular power flow bus = ppc['bus'] gen = ppc['gen'] bus[6, 13] = lmp gen[0, 1] = opf_gen[0, 1] gen[1, 1] = opf_gen[1, 1] gen[2, 1] = opf_gen[2, 1] gen[3, 1] = opf_gen[3, 1] # during regular power flow, we use the actual CSV + feeder load, ignore dispatchable load and use actual bus[6, 2] = csv_load + feeder_load gen[4, 1] = 0 # opf_gen[4, 1] gen[4, 9] = 0 rpf = pp.runpf(ppc, ppopt_regular) if rpf[0]['success'] == False: conv_accum = False bus = rpf[0]['bus'] gen = rpf[0]['gen'] Pload = bus[:, 2].sum() Pgen = gen[:, 1].sum() Ploss = Pgen - Pload # update the metrics n_accum += 1 loss_accum += Ploss for i in range(fncsBus.shape[0]): busnum = int(fncsBus[i, 0]) busidx = busnum - 1 row = bus[busidx].tolist() # LMP_P, LMP_Q, PD, QD, Vang, Vmag, Vmax, Vmin: row[11] and row[12] are Vmax and Vmin constraints PD = row[ 2] + resp # TODO, if more than one FNCS bus, track scaled_resp separately Vpu = row[7] bus_accum[str(busnum)][0] += row[13] * 0.001 bus_accum[str(busnum)][1] += row[14] * 0.001 bus_accum[str(busnum)][2] += PD bus_accum[str(busnum)][3] += row[3] bus_accum[str(busnum)][4] += row[8] bus_accum[str(busnum)][5] += Vpu if Vpu > bus_accum[str(busnum)][6]: bus_accum[str(busnum)][6] = Vpu if Vpu < bus_accum[str(busnum)][7]: bus_accum[str(busnum)][7] = Vpu for i in range(gen.shape[0]): row = gen[i].tolist() busidx = int(row[0] - 1) # Pgen, Qgen, LMP_P (includes the responsive load as dispatched by OPF) gen_accum[str(i + 1)][0] += row[1] gen_accum[str(i + 1)][1] += row[2] gen_accum[str(i + 1)][2] += float(opf_bus[busidx, 13]) * 0.001 # write the metrics if ts >= tnext_metrics: sys_metrics[str(ts)] = { rootname: [loss_accum / n_accum, conv_accum] } bus_metrics[str(ts)] = {} for i in range(fncsBus.shape[0]): busnum = int(fncsBus[i, 0]) busidx = busnum - 1 row = bus[busidx].tolist() met = bus_accum[str(busnum)] bus_metrics[str(ts)][str(busnum)] = [ met[0] / n_accum, met[1] / n_accum, met[2] / n_accum, met[3] / n_accum, met[4] / n_accum, met[5] / n_accum, met[6], met[7] ] bus_accum[str(busnum)] = [0, 0, 0, 0, 0, 0, 0, 99999.0] gen_metrics[str(ts)] = {} for i in range(gen.shape[0]): met = gen_accum[str(i + 1)] gen_metrics[str(ts)][str(i + 1)] = [ met[0] / n_accum, met[1] / n_accum, met[2] / n_accum ] gen_accum[str(i + 1)] = [0, 0, 0] tnext_metrics += period n_accum = 0 loss_accum = 0 conv_accum = True volts = 1000.0 * bus[6, 7] * bus[6, 9] fncs.publish('three_phase_voltage_B7', volts) # CSV file output print( ts, res['success'], '{:.3f}'.format(Pload), # Pload '{:.3f}'.format(csv_load), # P7 (csv) '{:.3f}'.format(unresp), # GLD Unresp '{:.3f}'.format(bus[6, 2]), # P7 (rpf) '{:.3f}'.format(resp), # Resp (opf) '{:.3f}'.format(feeder_load), # GLD Pub new_bid, '{:.3f}'.format(gen[4, 9]), # P7 Min '{:.3f}'.format(bus[6, 7]), # V7 '{:.3f}'.format(bus[6, 13]), # LMP_P7 '{:.3f}'.format(bus[6, 14]), # LMP_Q7 '{:.2f}'.format(gen[0, 1]), # Pgen1 '{:.2f}'.format(gen[1, 1]), # Pgen2 '{:.2f}'.format(gen[2, 1]), # Pgen3 '{:.2f}'.format(gen[3, 1]), # Pgen4 '{:.2f}'.format(res['gen'][4, 1]), # Pdisp '{:.4f}'.format(resp_deg), # degree '{:.8f}'.format(ppc['gencost'][4, 4]), # c2 '{:.8f}'.format(ppc['gencost'][4, 5]), # c1 sep=',', file=op, flush=True) # request the next time step ts = fncs.time_request(ts + dt) if ts > tmax: print('breaking out at', ts, flush=True) break # spio.savemat('matFile.mat', saveDataDict) # =================================== print('writing metrics', flush=True) print(json.dumps(sys_metrics), file=sys_mp, flush=True) print(json.dumps(bus_metrics), file=bus_mp, flush=True) print(json.dumps(gen_metrics), file=gen_mp, flush=True) print('closing files', flush=True) bus_mp.close() gen_mp.close() sys_mp.close() op.close() print('finalizing FNCS', flush=True) fncs.finalize()
if sig_name in item: signalValues=signalValues+(item[6],) i=0 for voltage in voltages_topic: Voltage_real=signalValues[2*i] Voltage_imag=signalValues[2*i+1] if Voltage_imag<0: Voltage_str=str(Voltage_real) + str(Voltage_imag) + "j" else: Voltage_str=str(Voltage_real) + "+" + str(Voltage_imag) + "j" fncs.publish(voltage,Voltage_str) i+=1 #Get P&Q values P_val=() for P in load_p_topic: P_val=P_val+(round((float(fncs.get_value(P))/10000),2),) print P_val Q_val=() for Q in load_q_topic: Q_val=Q_val+(round((float(fncs.get_value(Q))/10000),2),) print Q_val # Get control to send parameters RtlabApi.GetParameterControl(1) # Send control signals after getting control timetest=time.time() RtlabApi.SetParametersByName(parameterNames_Q+parameterNames_P,Q_val+P_val) print time.time()-timetest RtlabApi.GetParameterControl(0) if (time.time()-current_time<1): print "Sleep time was", time.time()-current_time
def main_loop(): if len(sys.argv) == 2: rootname = sys.argv[1] else: print('usage: python fncsPYPOWER.py rootname') sys.exit() ppc = ppcasefile() StartTime = ppc['StartTime'] tmax = int(ppc['Tmax']) period = int(ppc['Period']) dt = int(ppc['dt']) make_dictionary(ppc, rootname) bus_mp = open("bus_" + rootname + "_metrics.json", "w") gen_mp = open("gen_" + rootname + "_metrics.json", "w") sys_mp = open("sys_" + rootname + "_metrics.json", "w") bus_meta = { 'LMP_P': { 'units': 'USD/kwh', 'index': 0 }, 'LMP_Q': { 'units': 'USD/kvarh', 'index': 1 }, 'PD': { 'units': 'MW', 'index': 2 }, 'QD': { 'units': 'MVAR', 'index': 3 }, 'Vang': { 'units': 'deg', 'index': 4 }, 'Vmag': { 'units': 'pu', 'index': 5 }, 'Vmax': { 'units': 'pu', 'index': 6 }, 'Vmin': { 'units': 'pu', 'index': 7 } } gen_meta = { 'Pgen': { 'units': 'MW', 'index': 0 }, 'Qgen': { 'units': 'MVAR', 'index': 1 }, 'LMP_P': { 'units': 'USD/kwh', 'index': 2 } } sys_meta = { 'Ploss': { 'units': 'MW', 'index': 0 }, 'Converged': { 'units': 'true/false', 'index': 1 } } bus_metrics = {'Metadata': bus_meta, 'StartTime': StartTime} gen_metrics = {'Metadata': gen_meta, 'StartTime': StartTime} sys_metrics = {'Metadata': sys_meta, 'StartTime': StartTime} gencost = ppc['gencost'] fncsBus = ppc['FNCS'] ppopt = pp.ppoption(VERBOSE=0, OUT_ALL=0, PF_DC=1) loads = np.loadtxt('NonGLDLoad.txt', delimiter=',') for row in ppc['UnitsOut']: print('unit ', row[0], 'off from', row[1], 'to', row[2], flush=True) for row in ppc['BranchesOut']: print('branch', row[0], 'out from', row[1], 'to', row[2], flush=True) nloads = loads.shape[0] ts = 0 tnext_opf = -dt op = open(rootname + '.csv', 'w') print( 't[s],Converged,Pload,P7 (csv), GLD Unresp, P7 (opf), Resp (opf), GLD Pub, BID?, P7 Min, V7,LMP_P7,LMP_Q7,Pgen1,Pgen2,Pgen3,Pgen4,Pdisp, gencost2, gencost1, gencost0', file=op, flush=True) # print ('t[s], ppc-Pd5, ppc-Pd9, ppc-Pd7, bus-Pd7, ppc-Pg1, gen-Pg1, ppc-Pg2, gen-Pg2, ppc-Pg3, gen-Pg3, ppc-Pg4, gen-Pg4, ppc-Pg5, gen-Pg5, ppc-Cost2, gencost-Cost2, ppc-Cost1, gencost-Cost1, ppc-Cost0, gencost-Cost0', file=op, flush=True) fncs.initialize() # transactive load components csv_load = 0 scaled_unresp = 0 scaled_resp = 0 resp_c0 = 0 resp_c1 = 0 resp_c2 = 0 resp_max = 0 gld_load = 0 # this is the actual # ================================== # Laurentiu Marinovici - 2017-12-14 actual_load = 0 new_bid = False # saveInd = 0 # saveDataDict = {} # =================================== while ts <= tmax: if ts >= tnext_opf: # expecting to solve opf one dt before the market clearing period ends, so GridLAB-D has time to use it idx = int((ts + dt) / period) % nloads bus = ppc['bus'] print( '<<<<< ts = {}, ppc-Pd5 = {}, bus-Pd5 = {}, ppc-Pd7 = {}, bus-Pd7 = {}, ppc-Pd9 = {}, bus-Pd9 = {} >>>>>>>' .format(ts, ppc["bus"][4, 2], bus[4, 2], ppc["bus"][6, 2], bus[6, 2], ppc["bus"][8, 2], bus[8, 2])) gen = ppc['gen'] branch = ppc['branch'] gencost = ppc['gencost'] csv_load = loads[idx, 0] bus[4, 2] = loads[idx, 1] bus[8, 2] = loads[idx, 2] print( '<<<<< ts = {}, ppc-Pd5 = {}, bus-Pd5 = {}, ppc-Pd7 = {}, bus-Pd7 = {}, ppc-Pd9 = {}, bus-Pd9 = {} >>>>>>>' .format(ts, ppc["bus"][4, 2], bus[4, 2], ppc["bus"][6, 2], bus[6, 2], ppc["bus"][8, 2], bus[8, 2])) # process the generator and branch outages for row in ppc['UnitsOut']: if ts >= row[1] and ts <= row[2]: gen[row[0], 7] = 0 else: gen[row[0], 7] = 1 for row in ppc['BranchesOut']: if ts >= row[1] and ts <= row[2]: branch[row[0], 10] = 0 else: branch[row[0], 10] = 1 bus[6, 2] = csv_load # ================================= # Laurentiu Marinovici - 2017-12-14 # bus[6,2] = csv_load + actual_load # ================================= for row in ppc['FNCS']: scaled_unresp = float(row[2]) * float(row[3]) newidx = int(row[0]) - 1 bus[newidx, 2] += scaled_unresp print( '<<<<< ts = {}, ppc-Pd5 = {}, bus-Pd5 = {}, ppc-Pd7 = {}, bus-Pd7 = {}, ppc-Pd9 = {}, bus-Pd9 = {} >>>>>>>' .format(ts, ppc["bus"][4, 2], bus[4, 2], ppc["bus"][6, 2], bus[6, 2], ppc["bus"][8, 2], bus[8, 2])) gen[4][9] = -resp_max * float(fncsBus[0][2]) gencost[4][3] = 3 gencost[4][4] = resp_c2 gencost[4][5] = resp_c1 gencost[4][6] = resp_c0 # ================================= # Laurentiu Marinovici - 2017-12-14 # print('Before running OPF:') # print('Disp load/neg gen: Pg = ', gen[4][1], ', Pmax = ', gen[4][8], ', Pmin = ', gen[4][9], ', status = ', gen[4][7]) # print('Disp load/neg gen cost coefficients: ', gencost[4][4], ', ', gencost[4][5], ', ', gencost[4][6]) # gen[4, 7] = 1 # turn on dispatchable load #ppc['gen'] = gen #ppc['bus'] = bus #ppc['branch'] = branch #ppc['gencost'] = gencost # print (ts, ppc["bus"][4, 2], ppc["bus"][8, 2], ppc["bus"][6, 2], bus[6, 2], ppc["gen"][0, 1], gen[0, 1], ppc["gen"][1, 1], gen[1, 1], ppc["gen"][2, 1], gen[2, 1], ppc["gen"][3, 1], gen[3, 1], ppc["gen"][4, 1], gen[4, 1], ppc["gencost"][4, 4], gencost[4, 4], ppc["gencost"][4, 5], gencost[4, 5], ppc["gencost"][4, 6], gencost[4, 6], sep=',', file=op, flush=True) # ===================================================================================================================== res = pp.runopf(ppc, ppopt) # ================================= # Laurentiu Marinovici - 2017-12-21 # mpcKey = 'mpc' + str(saveInd) # resKey = 'res' + str(saveInd) # saveDataDict[mpcKey] = copy.deepcopy(ppc) # saveDataDict[resKey] = copy.deepcopy(res) # saveInd += 1 # ================================= bus = res['bus'] gen = res['gen'] Pload = bus[:, 2].sum() Pgen = gen[:, 1].sum() Ploss = Pgen - Pload scaled_resp = -1.0 * gen[4, 1] # CSV file output print(ts, res['success'], '{:.3f}'.format(bus[:, 2].sum()), '{:.3f}'.format(csv_load), '{:.3f}'.format(scaled_unresp), '{:.3f}'.format(bus[6, 2]), '{:.3f}'.format(scaled_resp), '{:.3f}'.format(actual_load), new_bid, '{:.3f}'.format(gen[4, 9]), '{:.3f}'.format(bus[6, 7]), '{:.3f}'.format(bus[6, 13]), '{:.3f}'.format(bus[6, 14]), '{:.2f}'.format(gen[0, 1]), '{:.2f}'.format(gen[1, 1]), '{:.2f}'.format(gen[2, 1]), '{:.2f}'.format(gen[3, 1]), '{:.2f}'.format(res['gen'][4, 1]), '{:.6f}'.format(ppc['gencost'][4, 4]), '{:.4f}'.format(ppc['gencost'][4, 5]), '{:.4f}'.format(ppc['gencost'][4, 6]), sep=',', file=op, flush=True) fncs.publish('LMP_B7', 0.001 * bus[6, 13]) fncs.publish('three_phase_voltage_B7', 1000.0 * bus[6, 7] * bus[6, 9]) print('**OPF', ts, csv_load, scaled_unresp, gen[4][9], scaled_resp, bus[6, 2], 'LMP', 0.001 * bus[6, 13]) # update the metrics sys_metrics[str(ts)] = {rootname: [Ploss, res['success']]} bus_metrics[str(ts)] = {} for i in range(fncsBus.shape[0]): busnum = int(fncsBus[i, 0]) busidx = busnum - 1 row = bus[busidx].tolist() bus_metrics[str(ts)][str(busnum)] = [ row[13] * 0.001, row[14] * 0.001, row[2], row[3], row[8], row[7], row[11], row[12] ] gen_metrics[str(ts)] = {} for i in range(gen.shape[0]): row = gen[i].tolist() busidx = int(row[0] - 1) gen_metrics[str(ts)][str(i + 1)] = [ row[1], row[2], float(bus[busidx, 13]) * 0.001 ] tnext_opf += period if tnext_opf > tmax: print('breaking out at', tnext_opf, flush=True) break # apart from the OPF, keep loads updated ts = fncs.time_request(ts + dt) events = fncs.get_events() new_bid = False for key in events: topic = key.decode() # ================================== # Laurentiu Marinovici - 2017-12-14l # print('The event is: ........ ', key) # print('The topic is: ........ ', topic) # print('The value is: ........ ', fncs.get_value(key).decode()) # ============================================================= if topic == 'UNRESPONSIVE_KW': unresp_load = 0.001 * float(fncs.get_value(key).decode()) fncsBus[0][ 3] = unresp_load # poke unresponsive estimate into the bus load slot new_bid = True elif topic == 'RESPONSIVE_MAX_KW': resp_max = 0.001 * float(fncs.get_value(key).decode()) # in MW new_bid = True elif topic == 'RESPONSIVE_M': # resp_c2 = 1000.0 * 0.5 * float(fncs.get_value(key).decode()) resp_c2 = -1e6 * float(fncs.get_value(key).decode()) new_bid = True elif topic == 'RESPONSIVE_B': # resp_c1 = 1000.0 * float(fncs.get_value(key).decode()) resp_c1 = 1e3 * float(fncs.get_value(key).decode()) new_bid = True # ============================================ # Laurentiu Marinovici elif topic == 'RESPONSIVE_BB': resp_c0 = -float(fncs.get_value(key).decode()) new_bid = True # ============================================ elif topic == 'UNRESPONSIVE_PRICE': # not actually used unresp_price = float(fncs.get_value(key).decode()) new_bid = True else: gld_load = parse_mva(fncs.get_value(key).decode( )) # actual value, may not match unresp + resp load # ================================== # Laurentiu Marinovici - 2017-12-14 # print('GLD real = ', float(gld_load[0]), '; GLD imag = ', float(gld_load[1])) # print('Amp factor = ', float(fncsBus[0][2])) # ================================================================== actual_load = float(gld_load[0]) * float(fncsBus[0][2]) print(' Time = ', ts, '; actual load real = ', actual_load) if new_bid == True: print('**Bid', ts, unresp_load, resp_max, resp_c2, resp_c1, resp_c0) # Laurentiu Marinovici - 2017-12-21 # spio.savemat('matFile.mat', saveDataDict) # =================================== print('writing metrics', flush=True) print(json.dumps(bus_metrics), file=bus_mp, flush=True) print(json.dumps(gen_metrics), file=gen_mp, flush=True) print(json.dumps(sys_metrics), file=sys_mp, flush=True) print('closing files', flush=True) bus_mp.close() gen_mp.close() sys_mp.close() op.close() print('finalizing FNCS', flush=True) fncs.finalize()
import string import sys import fncs time_stop = int(sys.argv[1]) time_granted = 0 time_next = 1 # requires the yaml file fncs.initialize() print('# time key value till', time_stop, flush=True) while time_granted < time_stop: time_granted = fncs.time_request(time_stop) # time_next # print('**', time_granted) events = fncs.get_events() for key in events: topic = key.decode() print(time_granted, key, topic, fncs.get_value(key), flush=True) value = fncs.get_value(key).decode() if topic == 'sw_status': fncs.publish('sw_status', value) time_next = time_granted + 1 print('finalizing FNCS', flush=True) fncs.finalize() print('done', flush=True)
def run(self): time_granted = 0 fncs.initialize() time_stop = self.conf.time_stop time_pace = self.conf.time_pace while time_granted < time_stop: time1 = time.perf_counter() time_prev = time_granted time_granted = fncs.time_request(time_stop) time_advance = datetime.timedelta(seconds=(time_granted - time_prev)) self.time = self.time + time_advance events = fncs.get_events() for topic in events: value = fncs.get_value(topic) print((time_granted, topic, value)) key = topic.decode('utf-8') resp = value.decode('utf-8') result = None drop = None with self.lock: if key in self.logSpec: drop = self.logSpec[key].unit elif key in self.subs: drop = self.subs[key][0].unit else: pass resp = drop.sub('', resp) if drop != None else resp try: result = float(resp) except: try: c_resp = resp[0:-1] + 'j' if resp[ -1] == 'i' else resp result = complex(c_resp) except: try: result = str(resp) except: pass obj, attr = key.split('.') self.results[key] = (obj, attr, result, time_granted) if key in self.subs: for sub in self.subs[key]: sub.client.sendClient(sub.obj, sub.attr, result, time_granted) if key in self.logSpec: self.dbase.log(self.time, self.logSpec[key], resp) with self.lock: for pub in self.pubs: topic = pub.topic.encode('utf-8') value = pub.value.encode('utf-8') print((time_granted, topic, value)) fncs.publish(topic, value) if pub.topic in self.logSpec: self.dbase.log(self.time, self.logSpec[pub.topic], pub.value) self.pubs = [] self.dbase.flush() time2 = time.perf_counter() delta = time2 - time1 sleep = time_pace - delta if sleep > 0: time.sleep(sleep)