Exemple #1
0
def Return_Load_Info():	
	ierr, Complex_Power = psspy.aloadcplx(-1, 4, 'MVANOM') #Obtain Complex Power of Loads
	ierr, Complex_Current = psspy.aloadcplx(-1, 4, 'ILNOM') #Obtain Complex Currents of Loads
	ierr, Complex_Impedance = psspy.aloadcplx(-1, 4, 'YLNOM') #Obtain Complex Impedances of Loads
	ierr, Load_Numbers = psspy.aloadint(-1, 4, 'NUMBER') #Obtain Load Numbers
	ierr, Load_Count = psspy.aloadcount(-1, 4) #Obtain Count of Loads

	return Load_Count, Load_Numbers, Complex_Power, Complex_Current, Complex_Impedance
def Return_Load_Info():	
    ierr, Complex_Power = psspy.aloadcplx(-1, 4, 'MVANOM') #Obtain Complex Power of Loads
    ierr, Complex_Current = psspy.aloadcplx(-1, 4, 'ILNOM') #Obtain Complex Currents of Loads
    ierr, Complex_Impedance = psspy.aloadcplx(-1, 4, 'YLNOM') #Obtain Complex Impedances of Loads
    ierr, Load_Numbers = psspy.aloadint(-1, 4, 'NUMBER') #Obtain Load Numbers
    ierr, Load_Count = psspy.aloadcount(-1, 4) #Obtain Count of Loads
    ierr, Load_Amount = psspy.aloadcplx(-1, 4, 'MVAACT')
    return Load_Count, Load_Numbers, Load_Amount, Complex_Power, Complex_Current, Complex_Impedance
Exemple #3
0
    def readLoadPowers(self):
        '''
        Reads and stores active and reactive powers of each load
        '''
        ierr1, [load] = psspy.aloadcplx(-1, 4, 'TOTALACT')
        self.loadPowerP = []
        self.loadPowerQ = []
        for cplxload in load:
            self.loadPowerP.append(cplxload.real)
            self.loadPowerQ.append(cplxload.imag)

        assert ierr1 == 0, 'Error with reading active and reactive powers'
        return self.loadPowerP, self.loadPowerQ
Exemple #4
0
    def readLoadPowers(self):
        '''
        Reads and stores active and reactive powers of each load
        '''
        ierr1, [load] = psspy.aloadcplx(-1, 4, 'TOTALACT')
        self.loadPowerP = []
        self.loadPowerQ = []
        for cplxload in load:
            self.loadPowerP.append(cplxload.real)
            self.loadPowerQ.append(cplxload.imag)

        assert ierr1 == 0, 'Error with reading active and reactive powers'
        return self.loadPowerP, self.loadPowerQ
Exemple #5
0
def randdist(argin):
    filename=argin[0]
    percentage=argin[1]
    mode=argin[2]
    shuntctrlmode=0
    if mode!='arbitrary':
        shuntctrlmode=argin[3]
    psspy.case(filename)
    ierr, Qload=psspy.aloadcplx(-1, string="MVAACT")    
    Qload=[x.imag for x in Qload[0]]   
    ierr, tlbuses = psspy.aloadint(string='NUMBER')
    nbus=len(tlbuses[0])
    if mode=='random':
        zoseq=[0,1]*nbus
        sb=random.sample(zoseq,nbus)
    elif mode=='arbitrary':
        abus=argin[3]      # argin[3] in this case is the arbitrary buses to apply the disturbance
        sb=[0]*nbus
        for i in range(len(abus)):
            sb[tlbuses[0].index(abus[i])]=1            
    else:
        sb=[1]*nbus
    for j in range(nbus):
        if sb[j]==1:            
            Qd=Qload[j]+percentage/100.0*abs(Qload[j])
            ierr=psspy.load_data_3(i=tlbuses[0][j],REALAR2=Qd)
    if shuntctrlmode==1:
        for i in tlbuses[0]:
            ierr = psspy.switched_shunt_data_3(i, intgar9=1)
    psspy.fnsl(options1=0,options5=0)
    ierr, voltd = psspy.abusreal(-1, string="PU")        #voltage at buses after disturbance
    argout=[]
    argout.append(voltd)
    argout.append(Qload)
    argout.append(tlbuses)
    return argout;
Exemple #6
0
def LoadIncreaseMW(load_bus, percentage):
    psspy.bsys(0, 0, [0.0, 0.0], 0, [], len(load_bus), load_bus, 0, [], 0, [])
    ierr, allBusLoad = psspy.aloadcplx(0, 1, ['MVAACT'])
    allBusLoad = allBusLoad[0]
    BusLoadReal = np.real(allBusLoad)
    return np.sum(BusLoadReal) * percentage / 100
Exemple #7
0
def randdist(argin):

    filename = argin[0]  # initializing input arguments
    maxdist = argin[1]
    mode = argin[2]
    shuntctrlmode = argin[3]
    capbus = argin[4]
    capstep = argin[5]
    capQ = argin[6]
    pilot = argin[7]
    ndist = argin[8]
    nswitch = argin[9]
    reloadfile = 1
    # By default the network data file will be reloaded at each iteration
    if len(argin) == 11:
        reloadfile = argin[10]
    psspy.case(filename)
    ierr, Qload = psspy.aloadcplx(
        -1, string="MVAACT"
    )  # Qload is the amount of apparent power (P+jQ) for all loads
    Qload = [
        x.imag for x in Qload[0]
    ]  # We just need Reactive power (Q) so we find imaginary part of apparent power
    ierr, tlbuses = psspy.aloadint(
        string='NUMBER'
    )  # tlbuses is all loads' bus nomber, it includes also the compensators that we have added as loads to the network
    nbus = len(tlbuses[0])  # nbus is No. of all load buses
    ncap = len(capbus)
    ierr, busn = psspy.abusint(-1, string='NUMBER')

    npn = len(pilot)

    volt = []
    voltd = []
    vpn = [[0 for x in range(npn)] for y in range(ndist * nswitch)]
    vpnd = [[0 for x in range(npn)] for y in range(ndist * nswitch)]
    dvpn = [[0 for x in range(npn)] for y in range(ndist * nswitch)]
    switch = [[0 for x in range(ncap)] for y in range(ndist * nswitch)]
    for i in range(
            ndist
    ):  # in this loop we generate ndist random distrurbane cases and apply nswitch control actions on each case
        if reloadfile == 1:
            psspy.case(filename)
        percentage = random.random(
        ) * maxdist  # choose randomly the amount of disturbance with maximum of maxdist
        zoseq = [0, 1] * nbus
        if mode == 'random':
            sb = random.sample(
                zoseq, nbus)  # choose randomly loads to apply the disturbance
        if mode == 'all': sb = [1] * nbus
        capQd = [0 for x in range(ncap)]
        for j in range(nbus):  # applying the disturbance
            if sb[j] == 1:
                ##                if not(tlbuses[0][j] in capbus):          # we make sure that no dist. applied on capacitor buses (which are considered also as loads)
                Qd = Qload[j] + percentage / 100.0 * abs(Qload[j])
                ierr = psspy.load_data_3(i=tlbuses[0][j], REALAR2=Qd)
            if tlbuses[0][j] in capbus:
                capidx = capbus.index(tlbuses[0][j])
                if sb[j] == 1:
                    capQd[capidx] = Qd
                else:
                    capQd[capidx] = Qload[j]
        if shuntctrlmode == 1:  # by this option we can unlock all compensators over the network
            for j in tlbuses[0]:
                ierr = psspy.switched_shunt_data_3(j, intgar9=1)

        print '###### DIST(' + str(i) + ') ########'
        psspy.fdns(OPTIONS1=0, OPTIONS5=0,
                   OPTIONS6=1)  # do power flow on the disturbed system
        ierr, v = psspy.abusreal(
            -1, string="PU"
        )  # and measure voltage at all buses after disturbance (there is no option in PSS to measure the voltage of just one bus)

        for j in range(
                nswitch):  # now we apply random cap. switchings nswitch times
            [scb, ss, qss] = capselect(capbus, capstep, capQ)

            print '### ADD CAP ###'
            for k in range(len(scb)):
                scbidx = capbus.index(scb[k])
                switch[i * nswitch + j][scbidx] = ss[k]

                capQd[scbidx] = capQd[scbidx] - ss[k] * qss[k]
                ierr = psspy.load_data_3(i=scb[k], REALAR2=capQd[scbidx])

            print '###### DIST(' + str(i) + ') , ' + 'SWITCHCASE(' + str(
                i * nswitch + j) + ') ########'
            psspy.fdns(OPTIONS1=0, OPTIONS5=0,
                       OPTIONS6=1)  # do power flow on the disturbed system
            ierr, vd = psspy.abusreal(
                -1, string="PU"
            )  # and measure voltage at all buses after disturbance (there is no option in PSS to measure the voltage of just one bus)
            voltd.append(vd)
            volt.append(v)
            for k in range(npn):  # measuring vpn, and vpnd as outputs
                pnidx = busn[0].index(pilot[k])
                vpn[i * nswitch + j][k] = v[0][pnidx]
                vpnd[i * nswitch + j][k] = vd[0][pnidx]
                dvpn[i * nswitch +
                     j][k] = vpnd[i * nswitch + j][k] - vpn[i * nswitch + j][k]
            print '### REMOVE CAP ###'
            for k in range(
                    len(scb)
            ):  # after cap switchings we remove their effect for next switching
                scbidx = capbus.index(scb[k])
                capQd[scbidx] = capQd[scbidx] + ss[k] * qss[k]
                ierr = psspy.load_data_3(i=scb[k], REALAR2=capQd[scbidx])

    return volt, voltd, vpn, vpnd, dvpn, switch
Exemple #8
0
    x2.show_alerts(False)

    r0 = 1
    c0 = 1
    x2.set_range(r0, c0, zip(*vpn))
    x2.set_range(r0, c0 + 1, zip(*vpn1))
    x2.save()

##############################################################
##############################################################
##############################################################
## STEP7- Apply the Control to the disturbed model in Python

if flag7 == 1:
    ierr, Qload = psspy.aloadcplx(
        -1, string="MVAACT"
    )  # Qload is the amount of apparent power (P+jQ) for all loads
    Qload = [
        x.imag for x in Qload[0]
    ]  # We just need Reactive power (Q) so we find imaginary part of apparent power
    ierr, tlbuses = psspy.aloadint(
        string='NUMBER'
    )  # tlbuses is all loads' bus nomber, it includes also the compensators that we have added as loads to the network

    ctrl = [0, 1, -1, 0, 0, 0, 0, 2, -1, 1, 0, 2, 0, 1, 0, 1]
    Qctrl = [0 for x in range(ncap)]
    for k in range(len(ctrl)):
        Qctrl[k] = Qload[tlbuses[0].index(capbus[k])] - ctrl[k] * capQ[k]
        ierr = psspy.load_data_3(i=capbus[k], REALAR2=Qctrl[k])
    psspy.fdns(OPTIONS1=0, OPTIONS5=0,
               OPTIONS6=1)  # do power flow on the disturbed system
Exemple #9
0
    def read_raw(self):
        ''' Read the raw file.'''

        # Read bus numbers
        ierr, bus_numbers = psspy.abusint(-1, 2, 'NUMBER')

        assert ierr == 0, 'Error with reading bus numbers'

        # Reads voltage levels at buses stored in self.busNumbers
        ierr, voltage_levels = psspy.abusreal(-1, 2, 'PU')

        assert ierr == 0, 'Error reading voltage levels'

        # Reads voltage levels at buses stored in self.busNumbers
        ierr, voltage_angles = psspy.abusreal(-1, 2, 'ANGLED')

        assert ierr == 0, 'Error reading voltage angles'

        # Creates a Python dictionary containing bus numbers as keys and associates
        # a dictionary with voltage and angle to each of the keys
        for bus, voltage, angle in zip(bus_numbers[0], voltage_levels[0],
                                       voltage_angles[0]):
            self.buses[bus] = {'voltage': voltage, 'angle': angle}

        # Reads and stores bus numbers where generators are connected
        ierr, [machine_bus_numbers] = psspy.amachint(-1, 4, 'NUMBER')
        ierr, [machine_ids] = psspy.amachchar(-1, 4, 'ID')
        assert ierr == 0, 'Error reading generator bus numbers'

        # Reads and stores active and reactive powers of each generator
        ierr1, [machine_power_p] = psspy.amachreal(-1, 4, 'PGEN')
        ierr2, [machine_power_q] = psspy.amachreal(-1, 4, 'QGEN')

        assert ierr1 == 0 and ierr2 == 0, 'Error with reading active and reactive powers'

        # Creates a Python dictionary containing keys in form of
        # "BUSNUMBER_MACHINEID" and associates a dictionary with active and
        # reactive powers to each of the keys
        for k in range(0, len(machine_ids)):
            self.machines[(str(machine_bus_numbers[k]) + '_' +
                           machine_ids[k][:-1])] = {
                               'bus': machine_bus_numbers[k],
                               'P': machine_power_p[k],
                               'Q': machine_power_q[k]
                           }

        # Reads and stores bus numbers where loads are connected
        ierr, [load_bus_numbers] = psspy.aloadint(-1, 4, 'NUMBER')
        ierr, [load_ids] = psspy.aloadchar(-1, 4, 'ID')
        assert ierr == 0, 'Error reading load bus numbers'

        # Reads and stores active and reactive powers of each load
        ierr1, [load] = psspy.aloadcplx(-1, 4, 'TOTALACT')
        load_power_p = []
        load_power_q = []
        for cplxload in load:
            load_power_p.append(cplxload.real)
            load_power_q.append(cplxload.imag)

        assert ierr1 == 0, 'Error with reading active and reactive powers'

        # Creates a Python dictionary containing keys in form of
        # "BUSNUMBER_LOADID" and associates a dictionary with active and
        # reactive powers to each of the keys

        for load, bus, active, reactive in zip(load_ids, load_bus_numbers,
                                               load_power_p, load_power_q):
            self.loads[(str(bus) + '_' + load[:-1])] = {
                'bus': bus,
                'P': active,
                'Q': reactive
            }

        # Reads and stores bus numbers where 2WindingTrafos are connected
        ierr1, [two_w_trafo_from] = psspy.atrnint(-1, 1, 1, 2, 1, 'FROMNUMBER')
        ierr2, [two_w_trafo_to] = psspy.atrnint(-1, 1, 1, 2, 1, 'TONUMBER')

        assert ierr1 == 0 and ierr2 == 0, 'Error reading trafo bus numbers'

        # Reads and stores 2WindingTrafo ratios taking into account the primary side
        ierr1, [two_w_trafo_ratio1] = psspy.atrnreal(-1, 1, 1, 2, 1, 'RATIO')
        ierr2, [two_w_trafo_ratio2] = psspy.atrnreal(-1, 1, 1, 2, 1, 'RATIO2')

        assert ierr1 == 0 and ierr2 == 0, 'Error reading trafo bus numbers'

        # Creates a Python dictionary containing keys in form of
        # "BUSNUMBER_LOADID" and associates a dictionary with active and
        # reactive powers to each of the keys
        for f_bus, to_bus, ratio1, ratio2 in zip(two_w_trafo_from,
                                                 two_w_trafo_to,
                                                 two_w_trafo_ratio1,
                                                 two_w_trafo_ratio2):
            self.trafos[(str(f_bus) + '_' + str(to_bus))] = {
                'fromBus': f_bus,
                'toBus': to_bus,
                't1': ratio1,
                't2': ratio2
            }
Exemple #10
0
def pout_excel(savfile='savnw.sav', outpath=None, show=True):
    '''Exports power flow results to Excel Spreadsheet.
    When 'savfile' is not provided, it uses Network Data from PSS(R)E memory.
    When 'xlsfile' is provided and exists, power flow results are saved in 'next sheet#' of 'xlsfile'.
    When 'xlsfile' is provided and does not exists, power flow results are saved in 'Sheet1' of 'xlsfile'.
    When 'xlsfile' is not provided, power flow results are saved in 'Sheet1' of 'Book#.xls' file.
    '''

    import psspy

    psspy.psseinit()

    if savfile:
        ierr = psspy.case(savfile)
        if ierr != 0: return
        fpath, fext = os.path.splitext(savfile)
        if not fext: savfile = fpath + '.sav'
        #ierr = psspy.fnsl([0,0,0,1,1,0,0,0])
        #if ierr != 0: return
    else:  # saved case file not provided, check if working case is in memory
        ierr, nbuses = psspy.abuscount(-1, 2)
        if ierr != 0:
            print '\n No working case in memory.'
            print ' Either provide a Saved case file name or open Saved case in PSS(R)E.'
            return
        savfile, snapfile = psspy.sfiles()

    # ================================================================================================
    # PART 1: Get the required results data
    # ================================================================================================

    # Select what to report
    if psspy.bsysisdef(0):
        sid = 0
    else:  # Select subsytem with all buses
        sid = -1

    flag_bus = 1  # in-service
    flag_plant = 1  # in-service
    flag_load = 1  # in-service
    flag_swsh = 1  # in-service
    flag_brflow = 1  # in-service
    owner_brflow = 1  # bus, ignored if sid is -ve
    ties_brflow = 5  # ignored if sid is -ve

    # ------------------------------------------------------------------------------------------------
    # Case Title
    titleline1, titleline2 = psspy.titldt()

    # ------------------------------------------------------------------------------------------------
    # Bus Data
    # Bus Data - Integer
    istrings = ['number', 'type', 'area', 'zone', 'owner', 'dummy']
    ierr, idata = psspy.abusint(sid, flag_bus, istrings)
    if ierr:
        print '(1) psspy.abusint error = %d' % ierr
        return
    ibuses = array2dict(istrings, idata)
    # Bus Data - Real
    rstrings = [
        'base', 'pu', 'kv', 'angle', 'angled', 'mismatch', 'o_mismatch'
    ]
    ierr, rdata = psspy.abusreal(sid, flag_bus, rstrings)
    if ierr:
        print '(1) psspy.abusreal error = %d' % ierr
        return
    rbuses = array2dict(rstrings, rdata)
    # Bus Data - Complex
    xstrings = [
        'voltage', 'shuntact', 'o_shuntact', 'shuntnom', 'o_shuntnom',
        'mismatch', 'o_mismatch'
    ]
    ierr, xdata = psspy.abuscplx(sid, flag_bus, xstrings)
    if ierr:
        print '(1) psspy.abuscplx error = %d' % ierr
        return
    xbuses = array2dict(xstrings, xdata)
    # Bus Data - Character
    cstrings = ['name', 'exname']
    ierr, cdata = psspy.abuschar(sid, flag_bus, cstrings)
    if ierr:
        print '(1) psspy.abuschar error = %d' % ierr
        return
    cbuses = array2dict(cstrings, cdata)

    # Store bus data for all buses
    ibusesall = {}
    rbusesall = {}
    xbusesall = {}
    cbusesall = {}
    if sid == -1:
        ibusesall = ibuses
        rbusesall = rbuses
        xbusesall = xbuses
        cbusesall = cbuses
    else:
        ierr, idata = psspy.abusint(-1, flag_bus, istrings)
        if ierr:
            print '(2) psspy.abusint error = %d' % ierr
            return
        ibusesall = array2dict(istrings, idata)

        ierr, rdata = psspy.abusreal(-1, flag_bus, rstrings)
        if ierr:
            print '(2) psspy.abusreal error = %d' % ierr
            return
        rbusesall = array2dict(rstrings, rdata)

        ierr, xdata = psspy.abuscplx(-1, flag_bus, xstrings)
        if ierr:
            print '(2) psspy.abuscplx error = %d' % ierr
            return
        xbusesall = array2dict(xstrings, xdata)

        ierr, cdata = psspy.abuschar(-1, flag_bus, cstrings)
        if ierr:
            print '(2) psspy.abuschar error = %d' % ierr
            return
        cbusesall = array2dict(cstrings, cdata)

    # ------------------------------------------------------------------------------------------------
    # Plant Bus Data
    # Plant Bus Data - Integer
    istrings = [
        'number', 'type', 'area', 'zone', 'owner', 'dummy', 'status', 'ireg'
    ]
    ierr, idata = psspy.agenbusint(sid, flag_plant, istrings)
    if ierr:
        print 'psspy.agenbusint error = %d' % ierr
        return
    iplants = array2dict(istrings, idata)
    # Plant Bus Data - Real
    rstrings = [
        'base', 'pu', 'kv', 'angle', 'angled', 'iregbase', 'iregpu', 'iregkv',
        'vspu', 'vskv', 'rmpct', 'pgen', 'qgen', 'mva', 'percent', 'pmax',
        'pmin', 'qmax', 'qmin', 'mismatch', 'o_pgen', 'o_qgen', 'o_mva',
        'o_pmax', 'o_pmin', 'o_qmax', 'o_qmin', 'o_mismatch'
    ]
    ierr, rdata = psspy.agenbusreal(sid, flag_plant, rstrings)
    if ierr:
        print 'psspy.agenbusreal error = %d' % ierr
        return
    rplants = array2dict(rstrings, rdata)
    # Plant Bus Data - Complex
    xstrings = ['voltage', 'pqgen', 'mismatch', 'o_pqgen', 'o_mismatch']
    ierr, xdata = psspy.agenbuscplx(sid, flag_plant, xstrings)
    if ierr:
        print 'psspy.agenbusreal error = %d' % ierr
        return
    xplants = array2dict(xstrings, xdata)
    # Plant Bus Data - Character
    cstrings = ['name', 'exname', 'iregname', 'iregexname']
    ierr, cdata = psspy.agenbuschar(sid, flag_plant, cstrings)
    if ierr:
        print 'psspy.agenbuschar error = %d' % ierr
        return
    cplants = array2dict(cstrings, cdata)

    # ------------------------------------------------------------------------------------------------
    # Load Data - based on Individual Loads Zone/Area/Owner subsystem
    # Load Data - Integer
    istrings = ['number', 'area', 'zone', 'owner', 'status']
    ierr, idata = psspy.aloadint(sid, flag_load, istrings)
    if ierr:
        print 'psspy.aloadint error = %d' % ierr
        return
    iloads = array2dict(istrings, idata)
    # Load Data - Real
    rstrings = [
        'mvaact', 'mvanom', 'ilact', 'ilnom', 'ylact', 'ylnom', 'totalact',
        'totalnom', 'o_mvaact', 'o_mvanom', 'o_ilact', 'o_ilnom', 'o_ylact',
        'o_ylnom', 'o_totalact', 'o_totalnom'
    ]
    ierr, rdata = psspy.aloadreal(sid, flag_load, rstrings)
    if ierr:
        print 'psspy.aloadreal error = %d' % ierr
        return
    rloads = array2dict(rstrings, rdata)
    # Load Data - Complex
    xstrings = rstrings
    ierr, xdata = psspy.aloadcplx(sid, flag_load, xstrings)
    if ierr:
        print 'psspy.aloadcplx error = %d' % ierr
        return
    xloads = array2dict(xstrings, xdata)
    # Load Data - Character
    cstrings = ['id', 'name', 'exname']
    ierr, cdata = psspy.aloadchar(sid, flag_load, cstrings)
    if ierr:
        print 'psspy.aloadchar error = %d' % ierr
        return
    cloads = array2dict(cstrings, cdata)

    # ------------------------------------------------------------------------------------------------
    # Total load on a bus
    totalmva = {}
    totalil = {}
    totalyl = {}
    totalys = {}
    totalysw = {}
    totalload = {}
    busmsm = {}
    for b in ibuses['number']:
        ierr, ctmva = psspy.busdt2(b, 'MVA', 'ACT')
        if ierr == 0: totalmva[b] = ctmva

        ierr, ctil = psspy.busdt2(b, 'IL', 'ACT')
        if ierr == 0: totalil[b] = ctil

        ierr, ctyl = psspy.busdt2(b, 'YL', 'ACT')
        if ierr == 0: totalyl[b] = ctyl

        ierr, ctys = psspy.busdt2(b, 'YS', 'ACT')
        if ierr == 0: totalys[b] = ctys

        ierr, ctysw = psspy.busdt2(b, 'YSW', 'ACT')
        if ierr == 0: totalysw[b] = ctysw

        ierr, ctld = psspy.busdt2(b, 'TOTAL', 'ACT')
        if ierr == 0: totalload[b] = ctld

        #Bus mismstch
        ierr, msm = psspy.busmsm(b)
        if ierr != 1: busmsm[b] = msm

    # ------------------------------------------------------------------------------------------------
    # Switched Shunt Data
    # Switched Shunt Data - Integer
    istrings = [
        'number', 'type', 'area', 'zone', 'owner', 'dummy', 'mode', 'ireg',
        'blocks', 'stepsblock1', 'stepsblock2', 'stepsblock3', 'stepsblock4',
        'stepsblock5', 'stepsblock6', 'stepsblock7', 'stepsblock8'
    ]
    ierr, idata = psspy.aswshint(sid, flag_swsh, istrings)
    if ierr:
        print 'psspy.aswshint error = %d' % ierr
        return
    iswsh = array2dict(istrings, idata)
    # Switched Shunt Data - Real (Note: Maximum allowed NSTR are 50. So they are split into 2)
    rstrings = [
        'base', 'pu', 'kv', 'angle', 'angled', 'vswhi', 'vswlo', 'rmpct',
        'bswnom', 'bswmax', 'bswmin', 'bswact', 'bstpblock1', 'bstpblock2',
        'bstpblock3', 'bstpblock4', 'bstpblock5', 'bstpblock6', 'bstpblock7',
        'bstpblock8', 'mismatch'
    ]
    rstrings1 = [
        'o_bswnom', 'o_bswmax', 'o_bswmin', 'o_bswact', 'o_bstpblock1',
        'o_bstpblock2', 'o_bstpblock3', 'o_bstpblock4', 'o_bstpblock5',
        'o_bstpblock6', 'o_bstpblock7', 'o_bstpblock8', 'o_mismatch'
    ]
    ierr, rdata = psspy.aswshreal(sid, flag_swsh, rstrings)
    if ierr:
        print '(1) psspy.aswshreal error = %d' % ierr
        return
    rswsh = array2dict(rstrings, rdata)
    ierr, rdata1 = psspy.aswshreal(sid, flag_swsh, rstrings1)
    if ierr:
        print '(2) psspy.aswshreal error = %d' % ierr
        return
    rswsh1 = array2dict(rstrings1, rdata1)
    for k, v in rswsh1.iteritems():
        rswsh[k] = v
    # Switched Shunt Data - Complex
    xstrings = ['voltage', 'yswact', 'mismatch', 'o_yswact', 'o_mismatch']
    ierr, xdata = psspy.aswshcplx(sid, flag_swsh, xstrings)
    if ierr:
        print 'psspy.aswshcplx error = %d' % ierr
        return
    xswsh = array2dict(xstrings, xdata)
    # Switched Shunt Data - Character
    cstrings = ['vscname', 'name', 'exname', 'iregname', 'iregexname']
    ierr, cdata = psspy.aswshchar(sid, flag_swsh, cstrings)
    if ierr:
        print 'psspy.aswshchar error = %d' % ierr
        return
    cswsh = array2dict(cstrings, cdata)

    # ------------------------------------------------------------------------------------------------
    # Branch Flow Data
    # Branch Flow Data - Integer
    istrings = [
        'fromnumber', 'tonumber', 'status', 'nmeternumber', 'owners', 'own1',
        'own2', 'own3', 'own4'
    ]
    ierr, idata = psspy.aflowint(sid, owner_brflow, ties_brflow, flag_brflow,
                                 istrings)
    if ierr:
        print 'psspy.aflowint error = %d' % ierr
        return
    iflow = array2dict(istrings, idata)
    # Branch Flow Data - Real
    rstrings = [
        'amps',
        'pucur',
        'pctrate',
        'pctratea',
        'pctrateb',
        'pctratec',
        'pctmvarate',
        'pctmvaratea',
        'pctmvarateb',  #'pctmvaratec','fract1','fract2','fract3',
        'fract4',
        'rate',
        'ratea',
        'rateb',
        'ratec',
        'p',
        'q',
        'mva',
        'ploss',
        'qloss',
        'o_p',
        'o_q',
        'o_mva',
        'o_ploss',
        'o_qloss'
    ]
    ierr, rdata = psspy.aflowreal(sid, owner_brflow, ties_brflow, flag_brflow,
                                  rstrings)
    if ierr:
        print 'psspy.aflowreal error = %d' % ierr
        return
    rflow = array2dict(rstrings, rdata)
    # Branch Flow Data - Complex
    xstrings = ['pq', 'pqloss', 'o_pq', 'o_pqloss']
    ierr, xdata = psspy.aflowcplx(sid, owner_brflow, ties_brflow, flag_brflow,
                                  xstrings)
    if ierr:
        print 'psspy.aflowcplx error = %d' % ierr
        return
    xflow = array2dict(xstrings, xdata)
    # Branch Flow Data - Character
    cstrings = [
        'id', 'fromname', 'fromexname', 'toname', 'toexname', 'nmetername',
        'nmeterexname'
    ]
    ierr, cdata = psspy.aflowchar(sid, owner_brflow, ties_brflow, flag_brflow,
                                  cstrings)
    if ierr:
        print 'psspy.aflowchar error = %d' % ierr
        return
    cflow = array2dict(cstrings, cdata)

    # ================================================================================================
    # PART 2: Export acquired results to Excel
    # ================================================================================================
    p, nx = os.path.split(savfile)
    n, x = os.path.splitext(nx)
    # Require path otherwise Excel stores file in My Documents directory
    xlsfile = get_output_filename(outpath, 'pout_' + n + '.xlsx')

    if os.path.exists(xlsfile):
        xlsfileExists = True
    else:
        xlsfileExists = False

    # Excel Specifications, Worksheet Size: 65,536 rows by 256 columns
    # Limit maximum data that can be exported to meet above Worksheet Size.
    maxrows, maxcols = 65530, 256
    # if required, validate number of rows and columns against these values

    # Start Excel, add a new workbook, fill it with acquired data
    xlApp = win32com.client.Dispatch("Excel.Application")

    # DisplayAlerts = True is important in order to save changed data.
    # DisplayAlerts = False suppresses all POP-UP windows, like File Overwrite Yes/No/Cancel.
    xlApp.DisplayAlerts = False

    # set this to True if want see Excel file, False if just want to save
    xlApp.Visible = show

    if xlsfileExists:  # file exist, open it and add worksheet
        xlApp.Workbooks.Open(xlsfile)
        xlBook = xlApp.ActiveWorkbook
        xlSheet = xlBook.Worksheets.Add()
    else:  # file does not exist, add workbook and select sheet (=1, default)
        xlApp.Workbooks.Add()
        xlBook = xlApp.ActiveWorkbook
        xlSheet = xlBook.ActiveSheet
        try:
            xlBook.Sheets("Sheet2").Delete()
            xlBook.Sheets("Sheet3").Delete()
        except:
            pass

    # Format Excel Sheet
    xlSheet.Columns.WrapText = False
    xlSheet.Columns.Font.Name = 'Courier New'
    xlSheet.Columns.Font.Size = 10

    nclns, rowvars, xlsclnsdict = exportedvalues()

    xlSheet.Columns(
        eval('"' + xlsclnsdict['DESC'] + ':' + xlsclnsdict['BUS'] +
             '"')).ColumnWidth = 6
    xlSheet.Columns(
        eval('"' + xlsclnsdict['BUSNAME'] + ':' + xlsclnsdict['BUSNAME'] +
             '"')).ColumnWidth = 18
    xlSheet.Columns(
        eval('"' + xlsclnsdict['CKT'] + ':' + xlsclnsdict['CKT'] +
             '"')).ColumnWidth = 3
    xlSheet.Columns(
        eval('"' + xlsclnsdict['MW'] + ':' + xlsclnsdict['MVA'] +
             '"')).ColumnWidth = 10
    xlSheet.Columns(
        eval('"' + xlsclnsdict['%I'] + ':' + xlsclnsdict['%I'] +
             '"')).ColumnWidth = 6
    xlSheet.Columns(
        eval('"' + xlsclnsdict['VOLTAGE'] + ':' + xlsclnsdict['MVARLOSS'] +
             '"')).ColumnWidth = 10
    xlSheet.Columns(
        eval('"' + xlsclnsdict['AREA'] + ':' + xlsclnsdict['ZONE'] +
             '"')).ColumnWidth = 4

    xlSheet.Columns(
        eval('"' + xlsclnsdict['MW'] + ':' + xlsclnsdict['MVA'] +
             '"')).NumberFormat = "0.00"
    xlSheet.Columns(
        eval('"' + xlsclnsdict['%I'] + ':' + xlsclnsdict['%I'] +
             '"')).NumberFormat = "0.00"
    xlSheet.Columns(
        eval('"' + xlsclnsdict['VOLTAGE'] + ':' + xlsclnsdict['MVARLOSS'] +
             '"')).NumberFormat = "0.00"

    xlSheet.Columns(
        eval('"' + xlsclnsdict['CKT'] + ':' + xlsclnsdict['CKT'] +
             '"')).HorizontalAlignment = -4108
    xlSheet.Columns(
        eval('"' + xlsclnsdict['AREA'] + ':' + xlsclnsdict['ZONE'] +
             '"')).HorizontalAlignment = -4108
    # Integer value -4108 is for setting alignment to "center"

    # Page steup
    xlSheet.PageSetup.Orientation = 2  #1: Portrait, 2:landscape
    xlSheet.PageSetup.LeftMargin = xlApp.InchesToPoints(0.5)
    xlSheet.PageSetup.RightMargin = xlApp.InchesToPoints(0.5)
    xlSheet.PageSetup.TopMargin = xlApp.InchesToPoints(0.25)
    xlSheet.PageSetup.BottomMargin = xlApp.InchesToPoints(0.5)
    xlSheet.PageSetup.HeaderMargin = xlApp.InchesToPoints(0.25)
    xlSheet.PageSetup.FooterMargin = xlApp.InchesToPoints(0.25)

    # ColorIndex Constants
    # BLACK       --> ColorIndex = 1
    # WHITE       --> ColorIndex = 2
    # RED         --> ColorIndex = 3
    # GREEN       --> ColorIndex = 4
    # BLUE        --> ColorIndex = 5
    # PURPLE      --> ColorIndex = 7
    # LIGHT GREEN --> ColorIndex = 43

    # ------------------------------------------------------------------------------------------------
    # Report Title
    colstart = 1
    row = 1
    col = colstart
    xlSheet.Cells(row, col).Value = "POWER FLOW OUTPUT REPORT"
    xlSheet.Cells(row, col).Font.Bold = True
    xlSheet.Cells(row, col).Font.Size = 14
    xlSheet.Cells(row, col).Font.ColorIndex = 7

    row += 1
    xlSheet.Cells(row, col).Value = savfile

    row += 1
    xlSheet.Cells(row, col).Value = titleline1

    row += 1
    xlSheet.Cells(row, col).Value = titleline2

    row += 2
    tr, lc, br, rc = row, 1, row, nclns  #toprow, leftcolumn, bottomrow, rightcolumn
    xlSheet.Range(xlSheet.Cells(tr, lc + 1),
                  xlSheet.Cells(br, rc)).Value = rowvars[1:]
    xlSheet.Range(xlSheet.Cells(tr, lc), xlSheet.Cells(br,
                                                       rc)).Font.Bold = True
    xlSheet.Range(xlSheet.Cells(tr, lc), xlSheet.Cells(br,
                                                       rc)).Font.ColorIndex = 3
    xlSheet.Range(xlSheet.Cells(tr, lc),
                  xlSheet.Cells(br, rc)).VerticalAlignment = -4108
    xlSheet.Range(xlSheet.Cells(tr, lc),
                  xlSheet.Cells(br, rc)).HorizontalAlignment = -4108

    clnlabelrow = row
    row += 1  # add blank row after lables

    # Worksheet Headers and Footer
    # Put Title and ColumnHeads on top of each page
    rows2repeat = "$" + str(1) + ":$" + str(row)
    xlSheet.PageSetup.PrintTitleRows = rows2repeat

    xlSheet.PageSetup.LeftFooter = "PF Results: " + savfile
    xlSheet.PageSetup.RightFooter = "&P of &N"

    # ------------------------------------------------------------------------------------------------
    for i, bus in enumerate(ibuses['number']):

        # select bus and put bus data in a row

        rd = initdict(rowvars)
        rd['BUS'] = bus
        rd['BUSNAME'] = cbuses['exname'][i]
        rd['VOLTAGE'] = rbuses['pu'][i]
        rd['AREA'] = ibuses['area'][i]
        rd['ZONE'] = ibuses['zone'][i]

        row += 1
        rowvalues = [rd[each] for each in rowvars]
        xlSheet.Range(xlSheet.Cells(row, col),
                      xlSheet.Cells(row, nclns)).Value = rowvalues
        xlSheet.Range(xlSheet.Cells(row, col),
                      xlSheet.Cells(row, nclns)).Font.Bold = True
        xlSheet.Range(xlSheet.Cells(row, col),
                      xlSheet.Cells(row, nclns)).Font.ColorIndex = 5

        # check generation on selected bus
        plantbusidxes = busindexes(bus, iplants['number'])

        for idx in plantbusidxes:
            pcti = rplants['percent'][idx]
            if pcti == 0.0: pcti = ''
            rd = initdict(rowvars)
            rd['DESC'] = 'FROM'
            rd['BUSNAME'] = 'GENERATION'
            rd['MW'] = rplants['pgen'][idx]
            rd['MVAR'] = rplants['qgen'][idx]
            rd['MVA'] = rplants['mva'][idx]
            rd['%I'] = pcti
            rd['VOLTAGE'] = rplants['kv'][idx]

            row += 1
            rowvalues = [rd[each] for each in rowvars]
            xlSheet.Range(xlSheet.Cells(row, col),
                          xlSheet.Cells(row, nclns)).Value = rowvalues

        # check total load on selected bus
        if bus in totalmva:
            rd = initdict(rowvars)
            rd['DESC'] = 'TO'
            rd['BUSNAME'] = 'LOAD-PQ'
            rd['MW'] = totalmva[bus].real
            rd['MVAR'] = totalmva[bus].imag
            rd['MVA'] = abs(totalmva[bus])

            row += 1
            rowvalues = [rd[each] for each in rowvars]
            xlSheet.Range(xlSheet.Cells(row, col),
                          xlSheet.Cells(row, nclns)).Value = rowvalues

        if bus in totalil:
            rd = initdict(rowvars)
            rd['DESC'] = 'TO'
            rd['BUSNAME'] = 'LOAD-I'
            rd['MW'] = totalil[bus].real
            rd['MVAR'] = totalil[bus].imag
            rd['MVA'] = abs(totalil[bus])

            row += 1
            rowvalues = [rd[each] for each in rowvars]
            xlSheet.Range(xlSheet.Cells(row, col),
                          xlSheet.Cells(row, nclns)).Value = rowvalues

        if bus in totalyl:
            rd = initdict(rowvars)
            rd['DESC'] = 'TO'
            rd['BUSNAME'] = 'LOAD-Y'
            rd['MW'] = totalyl[bus].real
            rd['MVAR'] = totalyl[bus].imag
            rd['MVA'] = abs(totalyl[bus])

            row += 1
            rowvalues = [rd[each] for each in rowvars]
            xlSheet.Range(xlSheet.Cells(row, col),
                          xlSheet.Cells(row, nclns)).Value = rowvalues
        '''
        if bus in totalload:
            rd             = initdict(rowvars)
            rd['DESC']     = 'TO'
            rd['BUSNAME']  = 'LOAD-TOTAL'
            rd['MW']       = totalload[bus].real
            rd['MVAR']     = totalload[bus].imag
            rd['MVA']      = abs(totalload[bus])

            row += 1
            rowvalues = [rd[each] for each in rowvars]
            xlSheet.Range(xlSheet.Cells(row,col),xlSheet.Cells(row,nclns)).Value = rowvalues
        '''

        if bus in totalys:
            rd = initdict(rowvars)
            rd['DESC'] = 'TO'
            rd['BUSNAME'] = 'SHUNT'
            rd['MW'] = totalys[bus].real
            rd['MVAR'] = totalys[bus].imag
            rd['MVA'] = abs(totalys[bus])

            row += 1
            rowvalues = [rd[each] for each in rowvars]
            xlSheet.Range(xlSheet.Cells(row, col),
                          xlSheet.Cells(row, nclns)).Value = rowvalues

        if bus in totalysw:
            rd = initdict(rowvars)
            rd['DESC'] = 'TO'
            rd['BUSNAME'] = 'SWITCHED SHUNT'
            rd['MW'] = totalysw[bus].real
            rd['MVAR'] = totalysw[bus].imag
            rd['MVA'] = abs(totalysw[bus])

            row += 1
            rowvalues = [rd[each] for each in rowvars]
            xlSheet.Range(xlSheet.Cells(row, col),
                          xlSheet.Cells(row, nclns)).Value = rowvalues
        """
        # Sometimes load/shunt/switch shunt area/owner/zone's could be different than the bus
        # to which it is connected. So when producing subsystem based reports, these equipment
        # might get excluded.

        # check loads on selected bus
        loadbusidxes=busindexes(bus,iloads['number'])
        pq_p = 0; pq_q = 0
        il_p = 0; il_q = 0
        yl_p = 0; yl_q = 0
        for idx in loadbusidxes:
            pq_p += xloads['mvaact'][idx].real
            pq_q += xloads['mvaact'][idx].imag
            il_p += xloads['ilact'][idx].real
            il_q += xloads['ilact'][idx].imag
            yl_p += xloads['ylact'][idx].real
            yl_q += xloads['ylact'][idx].imag

        pq_mva = abs(complex(pq_p,pq_q))
        il_mva = abs(complex(il_p,il_q))
        yl_mva = abs(complex(yl_p,yl_q))

        if pq_mva:  #PQ Loads
            rd             = initdict(rowvars)
            rd['DESC']     = 'TO'
            rd['BUSNAME']  = 'LOAD-PQ'
            rd['MW']       = pq_p
            rd['MVAR']     = pq_q
            rd['MVA']      = pq_mva

            row += 1
            rowvalues = [rd[each] for each in rowvars]
            xlSheet.Range(xlSheet.Cells(row,col),xlSheet.Cells(row,nclns)).Value = rowvalues

        if il_mva:   #I Loads
            rd             = initdict(rowvars)
            rd['DESC']     = 'TO'
            rd['BUSNAME']  = 'LOAD-I'
            rd['MW']       = il_p
            rd['MVAR']     = il_q
            rd['MVA']      = il_mva

            row += 1
            rowvalues = [rd[each] for each in rowvars]
            xlSheet.Range(xlSheet.Cells(row,col),xlSheet.Cells(row,nclns)).Value = rowvalues

        if yl_mva:   #Y Loads
            rd             = initdict(rowvars)
            rd['DESC']     = 'TO'
            rd['BUSNAME']  = 'LOAD-Y'
            rd['MW']       = yl_p
            rd['MVAR']     = yl_q
            rd['MVA']      = yl_mva

            row += 1
            rowvalues = [rd[each] for each in rowvars]
            xlSheet.Range(xlSheet.Cells(row,col),xlSheet.Cells(row,nclns)).Value = rowvalues

        # check shunts on selected bus
        if abs(xbuses['shuntact'][i]):
            rd             = initdict(rowvars)
            rd['DESC']     = 'TO'
            rd['BUSNAME']  = 'SHUNT'
            rd['MW']       = xbuses['shuntact'][i].real
            rd['MVAR']     = xbuses['shuntact'][i].imag
            rd['MVA']      = abs(xbuses['shuntact'][i])

            row += 1
            rowvalues = [rd[each] for each in rowvars]
            xlSheet.Range(xlSheet.Cells(row,col),xlSheet.Cells(row,nclns)).Value = rowvalues

        # check switched shunts on selected bus
        swshbusidxes=busindexes(bus,iswsh['number'])
        pswsh = 0; qswsh = 0
        for idx in swshbusidxes:
            pswsh += xswsh['yswact'][idx].real
            qswsh += xswsh['yswact'][idx].imag
        mvaswsh = abs(complex(pswsh,qswsh))
        if mvaswsh:
            rd             = initdict(rowvars)
            rd['DESC']     = 'TO'
            rd['BUSNAME']  = 'SWITCHED SHUNT'
            rd['MW']       = pswsh
            rd['MVAR']     = qswsh
            rd['MVA']      = mvaswsh

            row += 1
            rowvalues = [rd[each] for each in rowvars]
            xlSheet.Range(xlSheet.Cells(row,col),xlSheet.Cells(row,nclns)).Value = rowvalues
        """

        # check connected branches to selected bus
        flowfrombusidxes = busindexes(bus, iflow['fromnumber'])
        for idx in flowfrombusidxes:
            if iflow['tonumber'][
                    idx] < 10000000:  #don't process 3-wdg xmer star-point buses
                tobusidx = busindexes(iflow['tonumber'][idx],
                                      ibusesall['number'])
                tobusVpu = rbusesall['pu'][tobusidx[0]]
                tobusarea = ibusesall['area'][tobusidx[0]]
                tobuszone = ibusesall['zone'][tobusidx[0]]
                pcti = rflow['pctrate'][idx]
                if pcti == 0.0: pcti = ''

                rd = initdict(rowvars)
                rd['DESC'] = 'TO'
                rd['BUS'] = iflow['tonumber'][idx]
                rd['BUSNAME'] = cflow['toexname'][idx]
                rd['CKT'] = cflow['id'][idx]
                rd['MW'] = rflow['p'][idx]
                rd['MVAR'] = rflow['q'][idx]
                rd['MVA'] = rflow['mva'][idx]
                rd['%I'] = pcti
                rd['VOLTAGE'] = tobusVpu
                rd['MWLOSS'] = rflow['ploss'][idx]
                rd['MVARLOSS'] = rflow['qloss'][idx]
                rd['AREA'] = tobusarea
                rd['ZONE'] = tobuszone

                row += 1
                rowvalues = [rd[each] for each in rowvars]
                xlSheet.Range(xlSheet.Cells(row, col),
                              xlSheet.Cells(row, nclns)).Value = rowvalues

        # Bus Mismatch
        if bus in busmsm:
            rd = initdict(rowvars)
            rd['BUSNAME'] = 'BUS MISMATCH'
            rd['MW'] = busmsm[bus].real
            rd['MVAR'] = busmsm[bus].imag
            rd['MVA'] = abs(busmsm[bus])

            row += 1
            rowvalues = [rd[each] for each in rowvars]
            xlSheet.Range(xlSheet.Cells(row, col),
                          xlSheet.Cells(row, nclns)).Value = rowvalues
            xlSheet.Range(xlSheet.Cells(row, col),
                          xlSheet.Cells(row, nclns)).Font.ColorIndex = 10
            xlSheet.Range(xlSheet.Cells(row, col),
                          xlSheet.Cells(row, nclns)).Font.Bold = True

            # xlEdgeTop border set to xlThin
            xlSheet.Range(xlSheet.Cells(row, col + 4),
                          xlSheet.Cells(row, col + 6)).Borders(8).Weight = 2

        # Insert EdgeBottom border(Borders(9)) with xlThin weight(2)
        xlSheet.Range(xlSheet.Cells(row, col),
                      xlSheet.Cells(row, nclns)).Borders(9).Weight = 2

        # Insert blank row
        row += 1

    # ------------------------------------------------------------------------------------------------
    # Draw borders
    # Column Lable Row
    # xlEdgeTop border set to xlThin
    xlSheet.Range(xlSheet.Cells(clnlabelrow, 1),
                  xlSheet.Cells(clnlabelrow, nclns)).Borders(8).Weight = 2
    # xlEdgeBottom border set to xlThin
    xlSheet.Range(xlSheet.Cells(clnlabelrow, 2),
                  xlSheet.Cells(clnlabelrow, nclns)).Borders(9).Weight = 2

    # Remaining WorkSheet
    # xlEdgeLeft border set to xlThinline
    xlSheet.Range(xlSheet.Cells(clnlabelrow, 1),
                  xlSheet.Cells(row - 1, nclns)).Borders(7).Weight = 2
    # xlEdgeRight border set to xlThinline
    xlSheet.Range(xlSheet.Cells(clnlabelrow, 1),
                  xlSheet.Cells(row - 1, nclns)).Borders(10).Weight = 2
    # xlInsideVertical border set to xlHairline
    xlSheet.Range(xlSheet.Cells(clnlabelrow, 1),
                  xlSheet.Cells(row - 1, nclns)).Borders(11).Weight = 1

    # ------------------------------------------------------------------------------------------------
    # Save the workbook and close the Excel application

    if xlsfile:  # xls file provided
        xlBook.SaveAs(Filename=xlsfile)
    else:
        xlsbookfilename = os.path.join(
            os.getcwd(), xlBook.Name)  # xlBook.Name returns without '.xls'
        xlBook.SaveAs(Filename=xlsbookfilename)
        xlsbookfilename = os.path.join(
            os.getcwd(), xlBook.Name)  # xlBook.Name returns '.xls' extn.

    if not show:
        xlBook.Close()
        xlApp.Quit()
        txt = '\n Power Flow Results saved to file %s' % xlsfile
        sys.stdout.write(txt)