def _read_dyr_dict(file): """ Parse dyr file into a dict where keys are model names and values are dataframes. """ input_list = andes.io.read_file_like(file) # concatenate multi-line device data input_concat_dict = defaultdict(list) multi_line = list() for line in input_list: if line == '': continue if '/' not in line: multi_line.append(line) else: multi_line.append(line.split('/')[0]) single_line = ' '.join(multi_line) if single_line.strip() == '': continue single_list = single_line.split("'") psse_model = single_list[1].strip() input_concat_dict[psse_model].append(single_list[0] + single_list[2]) multi_line = list() # construct pandas dataframe for all models dyr_dict = dict() # input data from dyr file for psse_model, all_rows in input_concat_dict.items(): dev_params_num = [([to_number(cell) for cell in row.split()]) for row in all_rows] dyr_dict[psse_model] = pd.DataFrame(dev_params_num) return dyr_dict
def read(system, file): """ Read PSS/E RAW file v32/v33 formats. """ blocks = [ 'bus', 'load', 'fshunt', 'gen', 'branch', 'transf', 'area', 'twotermdc', 'vscdc', 'impedcorr', 'mtdc', 'msline', 'zone', 'interarea', 'owner', 'facts', 'swshunt', 'gne', 'Q' ] rawd = re.compile(r'rawd\d\d') ret = True block_idx = 0 # current block index mva = 100 raw = {} for item in blocks: raw[item] = [] data = [] mdata = [] # multi-line data dev_line = 0 # line counter for multi-line models # read file into `line_list` line_list = andes.io.read_file_like(file) # parse file into `raw` with to_number conversions for num, line in enumerate(line_list): line = line.strip() # get basemva and nominal frequency if num == 0: data = line.split('/')[0] data = data.split(',') mva = float(data[1]) system.config.mva = mva try: system.config.freq = float(data[5]) except IndexError: logger.warning( 'System frequency is set to 60 Hz.\n' 'Consider using a higher version PSS/E raw file.') system.config.freq = 60.0 # get raw file version version = 0 if len(data) >= 3: version = int(data[2]) else: if rawd.search(line): version = int( rawd.search(line).group(0).strip('rawd')) # NOQA continue elif num == 1 or num == 2: # store the case info line if len(line) > 0: logger.info(" " + line) continue elif num >= 3: if line[0:2] == '0 ' or line[0:3] == ' 0 ': # end of block block_idx += 1 continue elif line[0] == 'Q': # end of file break data = line.split(',') data = [to_number(item) for item in data] mdata.append(data) dev_line += 1 block_lines = get_block_lines(block_idx, mdata) if dev_line >= block_lines: if block_lines == 1: mdata = mdata[0] raw[blocks[block_idx]].append(mdata) mdata = [] dev_line = 0 # add device elements to system bus_params, bus_idx_list, sw = _parse_bus_v33(raw, system) max_bus = max(bus_idx_list) _parse_load_v33(raw, system) _parse_fshunt_v33(raw, system) _parse_gen_v33(raw, system, sw) _parse_line_v33(raw, system) _parse_transf_v33(raw, system, max_bus) _parse_swshunt_v33(raw, system) _parse_area_v33(raw, system) return ret
def read(system, file): """read PSS/E RAW file v32 format""" blocks = [ 'bus', 'load', 'fshunt', 'gen', 'branch', 'transf', 'area', 'twotermdc', 'vscdc', 'impedcorr', 'mtdc', 'msline', 'zone', 'interarea', 'owner', 'facts', 'swshunt', 'gne', 'Q' ] rawd = re.compile(r'rawd\d\d') ret = True block_idx = 0 # current block index mva = 100 raw = {} for item in blocks: raw[item] = [] data = [] mdata = [] # multi-line data dev_line = 0 # line counter for multi-line models # read file into `line_list` with open(file, 'r') as f: line_list = [line.rstrip('\n') for line in f] # parse file into `raw` with to_number conversions for num, line in enumerate(line_list): line = line.strip() # get basemva and nominal frequency if num == 0: data = line.split('/')[0] data = data.split(',') mva = float(data[1]) system.config.mva = mva system.config.freq = float(data[5]) # get raw file version version = int(data[2]) if not version: version = int(rawd.search(line).group(0).strip('rawd')) logger.debug(f'PSSE raw version {version} detected') if version < 32 or version > 33: warn_experimental( 'RAW file version is not 32 or 33. Error may occur.') continue elif num == 1 or num == 2: # store the case info line if len(line) > 0: logger.info(" " + line) continue elif num >= 3: if line[0:2] == '0 ' or line[0:3] == ' 0 ': # end of block block_idx += 1 continue elif line[0] == 'Q': # end of file break data = line.split(',') data = [to_number(item) for item in data] mdata.append(data) dev_line += 1 block_lines = get_block_lines(block_idx, mdata) if dev_line >= block_lines: if block_lines == 1: mdata = mdata[0] raw[blocks[block_idx]].append(mdata) mdata = [] dev_line = 0 # add device elements to system sw = {} # idx:a0 max_bus = [] for data in raw['bus']: # version 32: # 0, 1, 2, 3, 4, 5, 6, 7, 8 # ID, NAME, BasekV, Type, Area Zone Owner Vm, Va # idx = data[0] max_bus.append(idx) ty = data[3] a0 = data[8] * deg2rad if ty == 3: sw[idx] = a0 param = { 'idx': idx, 'name': data[1], 'Vn': data[2], 'v0': data[7], 'a0': a0, 'area': data[4], 'zone': data[5], 'owner': data[6] } system.add('Bus', param) max_bus = max(max_bus) for data in raw['load']: # version 32: # 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 # Bus, Id, Status, Area, Zone, PL(MW), QL (MW), IP, IQ, YP, YQ, OWNER # bus = data[0] vn = system.Bus.get(src='Vn', idx=bus, attr='v') v0 = system.Bus.get(src='v0', idx=bus, attr='v') param = { 'bus': bus, 'u': data[2], 'Vn': vn, 'p0': (data[5] + data[7] * v0 + data[9] * v0**2) / mva, 'q0': (data[6] + data[8] * v0 - data[10] * v0**2) / mva, 'owner': data[11] } system.add('PQ', param) for data in raw['fshunt']: # 0, 1, 2, 3, 4 # Bus, name, Status, g (MW), b (Mvar) bus = data[0] vn = system.Bus.get(src='Vn', idx=bus, attr='v') param = { 'bus': bus, 'Vn': vn, 'u': data[2], 'Sn': mva, 'g': data[3] / mva, 'b': data[4] / mva } system.add('Shunt', param) gen_idx = 0 for data in raw['gen']: # 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11, 12, 13, 14, 15, 16,17,18,19 # I,ID,PG,QG,QT,QB,VS,IREG,MBASE,ZR,ZX,RT,XT,GTAP,STAT,RMPCT,PT,PB,O1,F1 bus = data[0] subidx = data[1] vn = system.Bus.get(src='Vn', idx=bus, attr='v') gen_mva = data[8] gen_idx += 1 status = data[14] param = { 'Sn': gen_mva, 'Vn': vn, 'u': status, 'idx': gen_idx, 'bus': bus, 'subidx': subidx, 'p0': data[2] / mva, 'q0': data[3] / mva, 'pmax': data[16] / mva, 'pmin': data[17] / mva, 'qmax': data[4] / mva, 'qmin': data[5] / mva, 'v0': data[6], 'ra': data[9], # ra - armature resistance 'xs': data[10], # xs - synchronous reactance } if data[0] in sw.keys(): param.update({'a0': sw[data[0]]}) system.add('Slack', param) else: system.add('PV', param) for data in raw['branch']: # # I,J,CKT,R,X,B,RATEA,RATEB,RATEC,GI,BI,GJ,BJ,ST,LEN,O1,F1,...,O4,F4 # param = { 'bus1': data[0], 'bus2': data[1], 'r': data[3], 'x': data[4], 'b': data[5], 'Vn1': system.Bus.get(src='Vn', idx=data[0], attr='v'), 'Vn2': system.Bus.get(src='Vn', idx=data[1], attr='v'), } system.add('Line', **param) xf_3_count = 1 for data in raw['transf']: if len(data) == 4: # """ # I,J,K,CKT,CW,CZ,CM,MAG1,MAG2,NMETR,'NAME',STAT,O1,F1,...,O4,F4 # R1-2,X1-2,SBASE1-2 # WINDV1,NOMV1,ANG1,RATA1,RATB1,RATC1,COD1,CONT1,RMA1,RMI1,VMA1,VMI1,NTP1,TAB1,CR1,CX1 # WINDV2,NOMV2 # """ tap = data[2][0] phi = data[2][2] if tap == 1 and phi == 0: transf = False else: transf = True param = { 'bus1': data[0][0], 'bus2': data[0][1], 'u': data[0][11], 'b': data[0][8], 'r': data[1][0], 'x': data[1][1], 'trans': transf, 'tap': tap, 'phi': phi, 'Vn1': system.Bus.get(src='Vn', idx=data[0][0], attr='v'), 'Vn2': system.Bus.get(src='Vn', idx=data[0][1], attr='v'), } system.add('Line', param) else: # I, J, K, CKT, CW, CZ, CM, MAG1, MAG2, NMETR, 'NAME', STAT, Ol, Fl,...,o4, F4 # R1-2, X1-2, SBASE1-2, R2-3, X2-3, SBASE2-3, R3-1, X3-1, SBASE3-1, VMSTAR, ANSTAR # WINDV1, NOMV1, ANG1, RATA1, BATB1, RATC1, COD1, CONT1, RMA1, RMI1, VMA1, VMI1, NTP1, TAB1, CR1, CX1 # WINDV2, NOMV2, ANG2, RATA2, BATB2, RATC2, COD2, CONT2, RMA2, RMI2, VMA2, VMI2, NTP2, TAB2, CR2, CX2 # WINDV3, NOMV3, ANG3, RATA3, BATB3, RATC3, COD3, CONT3, RMA3, RMI3, VMA3, VMI3, NTP3, TAB3, CR3, CX3 param = { 'idx': max_bus + xf_3_count, 'name': '_'.join(str(data[0][:3])), 'Vn': system.Bus.get(src='Vn', idx=data[0][0], attr='v'), 'v0': data[1][-2], 'a0': data[1][-1] * deg2rad } system.add('Bus', param) r = [] x = [] r.append((data[1][0] + data[1][6] - data[1][3]) / 2) r.append((data[1][3] + data[1][0] - data[1][6]) / 2) r.append((data[1][6] + data[1][3] - data[1][0]) / 2) x.append((data[1][1] + data[1][7] - data[1][4]) / 2) x.append((data[1][4] + data[1][1] - data[1][7]) / 2) x.append((data[1][7] + data[1][4] - data[1][1]) / 2) for i in range(0, 3): param = { 'trans': True, 'bus1': data[0][i], 'bus2': max_bus + xf_3_count, 'u': data[0][11], 'b': data[0][8], 'r': r[i], 'x': x[i], 'tap': data[2 + i][0], 'phi': data[2 + i][2], 'Vn1': system.Bus.get(src='Vn', idx=data[0][i], attr='v'), 'Vn2': system.Bus.get(src='Vn', idx=data[0][0], attr='v'), } system.add('Line', param) xf_3_count += 1 for data in raw['swshunt']: # I, MODSW, ADJM, STAT, VSWHI, VSWLO, SWREM, RMPCT, RMIDNT, # BINIT, N1, B1, N2, B2, ... N8, B8 bus = data[0] vn = system.Bus.get(src='Vn', idx=bus, attr='v') param = { 'bus': bus, 'Vn': vn, 'Sn': mva, 'u': data[3], 'b': data[9] / mva } system.add('Shunt', param) for data in raw['area']: # ID, ISW, PDES, PTOL, ARNAME param = { 'idx': data[0], 'name': data[4], # 'isw': data[1], # 'pdes': data[2], # 'ptol': data[3], } system.add('Area', param) for data in raw['zone']: # """ID, NAME""" param = {'idx': data[0], 'name': data[1]} # TODO: add back # system.add('Region', param) return ret
def read_add(system, file): """ Read addition PSS/E dyr file. Parameters ---------- system file Returns ------- """ warn_experimental("PSS/E dyr support") with open(file, 'r') as f: input_list = [line.strip() for line in f] # concatenate multi-line device data input_concat_dict = defaultdict(list) multi_line = list() for i, line in enumerate(input_list): if line == '': continue if '/' not in line: multi_line.append(line) else: multi_line.append(line.split('/')[0]) single_line = ' '.join(multi_line) single_list = single_line.split("'") psse_model = single_list[1].strip() input_concat_dict[psse_model].append(single_list[0] + single_list[2]) multi_line = list() # construct pandas dataframe for all models dyr_dict = dict() for psse_model, all_rows in input_concat_dict.items(): dev_params_num = [([to_number(cell) for cell in row.split()]) for row in all_rows] dyr_dict[psse_model] = pd.DataFrame(dev_params_num) # read yaml and set header for each pss/e model dirname = os.path.dirname(__file__) with open(f'{dirname}/psse-dyr.yaml', 'r') as f: dyr_yaml = yaml.full_load(f) for psse_model in dyr_dict: if psse_model in dyr_yaml: if 'inputs' in dyr_yaml[psse_model]: dyr_dict[psse_model].columns = dyr_yaml[psse_model]['inputs'] # load data into models for psse_model in dyr_dict: if psse_model not in dyr_yaml: logger.error(f"PSS/E Model <{psse_model}> is not supported.") continue dest = dyr_yaml[psse_model]['destination'] find = {} if 'find' in dyr_yaml[psse_model]: for name, source in dyr_yaml[psse_model]['find'].items(): for model, conditions in source.items(): cond_names = conditions.keys() cond_values = [ dyr_dict[psse_model][col] for col in conditions.values() ] find[name] = system.__dict__[model].find_idx( cond_names, cond_values) if 'get' in dyr_yaml[psse_model]: for name, source in dyr_yaml[psse_model]['get'].items(): for model, conditions in source.items(): idx_name = conditions['idx'] if idx_name in dyr_dict[psse_model]: conditions['idx'] = dyr_dict[psse_model][idx_name] else: conditions['idx'] = find[idx_name] find[name] = system.__dict__[model].get(**conditions) if 'outputs' in dyr_yaml[psse_model]: output_keys = list(dyr_yaml[psse_model]['outputs'].keys()) output_exprs = list(dyr_yaml[psse_model]['outputs'].values()) out_dict = {} for idx in range(len(output_exprs)): out_key = output_keys[idx] expr = output_exprs[idx] if expr in find: out_dict[out_key] = find[expr] elif ';' in expr: args, func = expr.split(';') func = eval(func) args = args.split(',') argv = [pairs.split('.') for pairs in args] argv = [dyr_dict[model][param] for model, param in argv] out_dict[output_keys[idx]] = func(*argv) else: out_dict[output_keys[idx]] = dyr_dict[psse_model][expr] df = pd.DataFrame.from_dict(out_dict) for row in df.to_dict(orient='records'): system.add(dest, row) system.link_ext_param(system.__dict__[dest]) return True
def read_add(system, file): """ Read an addition PSS/E dyr file. Parameters ---------- system : System System instance to which data will be loaded file : str Path to the additional `dyr` file Returns ------- bool data parsing status """ with open(file, 'r') as f: input_list = [line.strip() for line in f] # concatenate multi-line device data input_concat_dict = defaultdict(list) multi_line = list() for i, line in enumerate(input_list): if line == '': continue if '/' not in line: multi_line.append(line) else: multi_line.append(line.split('/')[0]) single_line = ' '.join(multi_line) if single_line.strip() == '': continue single_list = single_line.split("'") psse_model = single_list[1].strip() input_concat_dict[psse_model].append(single_list[0] + single_list[2]) multi_line = list() # construct pandas dataframe for all models dyr_dict = dict() # input data from dyr file for psse_model, all_rows in input_concat_dict.items(): dev_params_num = [([to_number(cell) for cell in row.split()]) for row in all_rows] dyr_dict[psse_model] = pd.DataFrame(dev_params_num) # read yaml and set header for each pss/e model dirname = os.path.dirname(__file__) with open(f'{dirname}/psse-dyr.yaml', 'r') as f: dyr_yaml = yaml.full_load(f) sorted_models = sort_psse_models(dyr_yaml) for psse_model in dyr_dict: if psse_model in dyr_yaml: if 'inputs' in dyr_yaml[psse_model]: dyr_dict[psse_model].columns = dyr_yaml[psse_model]['inputs'] # collect not supported models not_supported = [] for model in dyr_dict: if model not in sorted_models: not_supported.append(model) # print out debug messages if len(dyr_dict): logger.debug(f'dyr contains models {", ".join(dyr_dict.keys())}') if len(not_supported): logger.warning(f'Models not yet supported: {", ".join(not_supported)}') else: logger.debug('All dyr models are supported.') # load data into models for psse_model in sorted_models: if psse_model not in dyr_dict: # device not exist continue if psse_model not in dyr_yaml: logger.error(f"PSS/E Model <{psse_model}> is not supported.") continue logger.debug(f'Parsing PSS/E model {psse_model}') dest = dyr_yaml[psse_model]['destination'] find = {} if 'find' in dyr_yaml[psse_model]: for name, source in dyr_yaml[psse_model]['find'].items(): for model, conditions in source.items(): allow_none = conditions.pop('allow_none', 0) cond_names = conditions.keys() cond_values = [] for col in conditions.values(): if col in find: cond_values.append(find[col]) else: cond_values.append(dyr_dict[psse_model][col]) try: find[name] = system.__dict__[model].find_idx( cond_names, cond_values, allow_none=allow_none) except IndexError as e: logger.error( "Data file likely contains references to unsupported models." ) logger.error(e) return False if 'get' in dyr_yaml[psse_model]: for name, source in dyr_yaml[psse_model]['get'].items(): for model, conditions in source.items(): idx_name = conditions['idx'] if idx_name in dyr_dict[psse_model]: conditions['idx'] = dyr_dict[psse_model][idx_name] else: conditions['idx'] = find[idx_name] find[name] = system.__dict__[model].get(**conditions) if 'outputs' in dyr_yaml[psse_model]: output_keys = list(dyr_yaml[psse_model]['outputs'].keys()) output_exprs = list(dyr_yaml[psse_model]['outputs'].values()) out_dict = {} for idx in range(len(output_exprs)): out_key = output_keys[idx] expr = output_exprs[idx] if expr in find: out_dict[out_key] = find[expr] elif ';' in expr: args, func = expr.split(';') func = eval(func) args = args.split(',') argv = [pairs.split('.') for pairs in args] argv = [dyr_dict[model][param] for model, param in argv] out_dict[output_keys[idx]] = func(*argv) else: out_dict[output_keys[idx]] = dyr_dict[psse_model][expr] df = pd.DataFrame.from_dict(out_dict) for row in df.to_dict(orient='records'): system.add(dest, row) system.link_ext_param(system.__dict__[dest]) return True
def get_model_param(): sysid = request.args.get('sysid', None) model_name = request.args.get('name', None) var_name = request.args.get('var', None) idx = request.args.get('idx', None) value = request.args.get('value', None) sysbase = request.args.get('sysbase', 'False') if not sysid: flask.abort(400) if sysbase == 'False': sysbase = False elif sysbase == 'True': sysbase = True system = systems[sysid] if request.method == 'GET': if idx is not None: idx = to_number(idx) if request.method == 'GET': if not model_name or (model_name not in system.devman.devices): return 'Model name <{}> invalid or not loaded in system'.format( model_name) else: # with model_name model_ref = system.__dict__[model_name] if var_name: # with `var_name` if var_name not in model_ref.__dict__: return 'Error: variable <{}> not exist in <{}>'.format( var_name, model_name) if idx: return jsonify( model_ref.get_field(field=var_name, idx=idx)) elif not idx: return jsonify( list(model_ref.get_field(field=var_name))) elif not var_name: # without `var_name` if idx: if idx not in model_ref.idx: return 'Error: idx <{}> not exist in <{}>'.format( idx, model_name) return jsonify(model_ref.get_element_data(idx)) elif not idx: return jsonify(model_ref.data_to_list()) elif request.method == 'POST': if any([model_name, var_name, idx, value]) is None: flask.abort(400) model_ref = system.__dict__[model_name] if var_name not in model_ref.__dict__: flask.abort(404) idx = to_number(idx) if idx not in model_ref.idx: flask.abort(404) if sysbase == 'False': sysbase = False elif sysbase == 'True': sysbase = True model_ref.set_field(var_name, idx, value, sysbase) model_ref.reload_new_param() return jsonify(model_ref.get_field(var_name, idx))