Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Hi Bruce,

You'd like a list of all of the loads grouped by bus number and their P and Q values. Is that close?

I'd use the subsystem data retrieval API to collect information about the loads. The subsystem API gives you all of the loads at once, rather than getting them one at time like with the single element data retrieval API.

Here is what it might look like to grab a list of the bus numbers and ids of all the loads in a case.

ierr, numbers_ids = psspy.aloadint(sid=-1, string=["NUMBER", "ID"])

sid=1 is just a short-hand for "the entire case". The numbers_ids variable will be a list of lists:

[ [2002, 2003, 2004, 2004, 2005, ... ]
  [1, 1, 1, 2, 1, ...] ]

I'd do something similar to get the real and reactive power:

ierr, p_qs = psspy.aloadreal(sid=-1, string=["P", "Q"])

Now join the numbers, ids, P and Q values all together to make a list of four columns:

nums_ids_p_q = numbers_ids + p_qs

Transpose the list of four columns into rows because it is easier to work with:

loads = zip(*nums_ids_p_q)

Each row of the loads variable represents the number, id, P and Q value:

[ (2002, 1, 1.3, 0.8),
  (2003, 1, 1.04, 0.9),
  ... ]

Now your data is in a pretty standard looking format. Kind of like a spreadsheet in Excel. You could write little bits of code to sum up and give you totals per bus and per load.

Let me know how you get on with it. If you get some code working, but need some specific pointers, you can update your question pretty easily.

Hi Bruce,

You'd like a list of all of the loads grouped by bus number and their P and Q values. Is that close?

I'd use the subsystem data retrieval API to collect information about the loads. The subsystem API gives you all of the loads at once, rather than getting them one at time like with the single element data retrieval API.

Here is what it might look like to grab a list of the bus numbers and ids of all the loads in a case.

ierr, numbers_ids = psspy.aloadint(sid=-1, string=["NUMBER", "ID"])

sid=1sid=-1 is just a short-hand for "the "a subsystem that covers the entire case". The numbers_ids variable will be a list of lists:

[ [2002, 2003, 2004, 2004, 2005, ... ]
  [1, 1, 1, 2, 1, ...] ]

I'd do something similar to get the real and reactive power:

ierr, p_qs = psspy.aloadreal(sid=-1, string=["P", "Q"])

Now join the numbers, ids, P and Q values all together to make a list of four columns:

nums_ids_p_q = numbers_ids + p_qs

Transpose the list of four columns into rows because it is easier to work with:

loads = zip(*nums_ids_p_q)

Each row of the loads variable represents the number, id, P and Q value:

[ (2002, 1, 1.3, 0.8),
  (2003, 1, 1.04, 0.9),
  ... ]

Now your data is in a pretty standard looking format. Kind of like a spreadsheet in Excel. You could write little bits of code to sum up and give you totals per bus and per load.

Let me know how you get on with it. If you get some code working, but need some specific pointers, you can update your question pretty easily.

Hi Bruce,

You'd like a list of all of the loads grouped by bus number and their P and Q values. Is that close?

I'd use the subsystem data retrieval API to collect information about the loads. The subsystem API gives you all of the loads at once, rather than getting them one at time like with the single element data retrieval API.

Here is what it might look like to grab a list of the bus numbers and ids of all the loads in a case.

ierr, numbers_ids = psspy.aloadint(sid=-1, string=["NUMBER", "ID"])

sid=-1 is just a short-hand for "a subsystem that covers the entire case". The numbers_ids variable will be a list of lists:

[ [2002, 2003, 2004, 2004, 2005, ... ]
  [1, 1, 1, 2, 1, ...] ]

I'd do something similar to get the real and reactive power:

ierr, p_qs = psspy.aloadreal(sid=-1, string=["P", "Q"])

Now join the numbers, ids, P and Q values all together to make a list of four columns:

nums_ids_p_q = numbers_ids + p_qs

Transpose the list of four columns into rows because it is easier to work with:

loads = zip(*nums_ids_p_q)

Each row of the loads variable represents the number, id, P and Q value:

[ (2002, 1, 1.3, 0.8),
  (2003, 1, 1.04, 0.9),
  ... ]

Now your data is in a pretty standard looking format. Kind of like a spreadsheet in Excel. You could write little bits of code to sum up and give you totals per bus and per load.

Let me know how you get on with it. If you get some code working, but need some specific pointers, you can update your question pretty easily.

(edit)

The next step is to sum the total load flowing radially from a terminal station. And there are a couple of ways to do this.

1. Total load flowing from the terminal station. This is probably what you are looking for if you are sizing the bus at the terminal station.

2. Total load existing radially from the terminal station, excluding any losses. I'd sometimes use this method as a sanity check to see if my model is correct.

I'll take you through how to do number 1. It is far easier to calculate and answers your question (Let me know if it doesn't).

explanation of terms In our mock system, bus 2100 is the terminal station bus. Buses 2110, 2120 and 2130 are radial from the terminal station. Whereas buses 2240 and 2250 are not radial.

the method

Hi Bruce,

You'd like a list of all of the loads grouped by bus number and their P and Q values. Is that close?

I'd use the subsystem data retrieval API to collect information about the loads. The subsystem API gives you all of the loads at once, rather than getting them one at time like with the single element data retrieval API.

Here is what it might look like to grab a list of the bus numbers and ids of all the loads in a case.

ierr, numbers_ids = psspy.aloadint(sid=-1, string=["NUMBER", "ID"])

sid=-1 is just a short-hand for "a subsystem that covers the entire case". The numbers_ids variable will be a list of lists:

[ [2002, 2003, 2004, 2004, 2005, ... ]
  [1, 1, 1, 2, 1, ...] ]

I'd do something similar to get the real and reactive power:

ierr, p_qs = psspy.aloadreal(sid=-1, string=["P", "Q"])

Now join the numbers, ids, P and Q values all together to make a list of four columns:

nums_ids_p_q = numbers_ids + p_qs

Transpose the list of four columns into rows because it is easier to work with:

loads = zip(*nums_ids_p_q)

Each row of the loads variable represents the number, id, P and Q value:

[ (2002, 1, 1.3, 0.8),
  (2003, 1, 1.04, 0.9),
  ... ]

Now your data is in a pretty standard looking format. Kind of like a spreadsheet in Excel. You could write little bits of code to sum up and give you totals per bus and per load.

Let me know how you get on with it. If you get some code working, but need some specific pointers, you can update your question pretty easily.

(edit)

The next step is to sum the total load flowing radially from a terminal station. And there are a couple of ways to do this.

1. Total load flowing from the terminal station. This is probably what you are looking for if you are sizing the bus at the terminal station.

2. Total load existing radially from the terminal station, excluding any losses. I'd sometimes use this method as a sanity check to see if my model is correct.

I'll take you through how to do number 1. It is far easier to calculate and answers your question (Let me know if it doesn't).

explanation of terms In our mock system, bus 2100 is the terminal station bus. Buses 2110, 2120 and 2130 are radial from the terminal station. Whereas buses 2240 and 2250 are not radial.

the method

  • List of all the P and Q branch flows in the case.

  • Select the P and Q branch flows from our target terminal (some radial, some will be back into the main system)

  • Identify which branches are radial

  • Sum those radial PQ values.

list all PQ flows in the case

ierr, from_to = psspy.aflowint(sid=-1, string=["FROMNUMBER", "TONUMBER"])
ierr, p_q = psspy.aflowreal(sid=-1, string=["P", "Q"])
from_to_p_q = from_to + p_q
branches = zip(*from_to_p_q)

branches from our terminal station assuming the number is 2100

terminal_bus = 2100
terminal_branches = [(frombus, tobus, p, q) 
                      for (frombus, tobus, p, q) in branches 
                      if terminal_bus in (frombus, tobus)]

find the radial branches I'll use a trick here and employ some set theory. Radial buses are those that become islanded when the terminal station bus is taken offline. This only works if your target network is truly radial from a single bus or a group of buses. Another method is to check for buses that are connected through a transformer.

# select all in service buses (flag=1)
allbuses = psspy.abusint(sid=-1, string=["NUMBER"], flag=1)

Hi Bruce,

You'd like a list of all of the loads grouped by bus number and their P and Q values. Is that close?

I'd use the subsystem data retrieval API to collect information about the loads. The subsystem API gives you all of the loads at once, rather than getting them one at time like with the single element data retrieval API.

Here is what it might look like to grab a list of the bus numbers and ids of all the loads in a case.

ierr, numbers_ids = psspy.aloadint(sid=-1, string=["NUMBER", "ID"])

sid=-1 is just a short-hand for "a subsystem that covers the entire case". The numbers_ids variable will be a list of lists:

[ [2002, 2003, 2004, 2004, 2005, ... ]
  [1, 1, 1, 2, 1, ...] ]

I'd do something similar to get the real and reactive power:

ierr, p_qs = psspy.aloadreal(sid=-1, string=["P", "Q"])

Now join the numbers, ids, P and Q values all together to make a list of four columns:

nums_ids_p_q = numbers_ids + p_qs

Transpose the list of four columns into rows because it is easier to work with:

loads = zip(*nums_ids_p_q)

Each row of the loads variable represents the number, id, P and Q value:

[ (2002, 1, 1.3, 0.8),
  (2003, 1, 1.04, 0.9),
  ... ]

Now your data is in a pretty standard looking format. Kind of like a spreadsheet in Excel. You could write little bits of code to sum up and give you totals per bus and per load.

Let me know how you get on with it. If you get some code working, but need some specific pointers, you can update your question pretty easily.

(edit)

The next step is to sum the total load flowing radially from a terminal station. And there are a couple of ways to do this.

1. Total load flowing from the terminal station. This is probably what you are looking for if you are sizing the bus at the terminal station.

2. Total load existing radially from the terminal station, excluding any losses. I'd sometimes use this method as a sanity check to see if my model is correct.

I'll take you through how to do number 1. It is far easier to calculate and answers your question (Let me know if it doesn't).

explanation of terms In our mock system, bus 2100 is the terminal station bus. Buses 2110, 2120 and 2130 are radial from the terminal station. Whereas buses 2240 and 2250 are not radial.

the method

  • List of all the P and Q branch flows in the case.

  • Select the P and Q branch flows from our target terminal (some radial, some will be back into the main system)

  • Identify which branches are radial

  • Sum those radial PQ values.

list all PQ flows in the case

ierr, from_to = psspy.aflowint(sid=-1, string=["FROMNUMBER", "TONUMBER"])
ierr, p_q = psspy.aflowreal(sid=-1, string=["P", "Q"])
from_to_p_q = from_to + p_q
branches = zip(*from_to_p_q)

branches from our terminal station assuming the number is 2100

terminal_bus = 2100
terminal_branches = [(frombus, tobus, p, q) 
                      for (frombus, tobus, p, q) in branches 
                      if terminal_bus in (frombus, tobus)]

find the radial branches I'll use a trick here and employ some set theory. Radial buses are those that become islanded when the terminal station bus is taken offline. This only works if your target network is truly radial from a single bus or a group of buses. Another method is to check for buses that are connected through a transformer.

# select all in service buses (flag=1)
allbuses ierr, (allbuses,) = psspy.abusint(sid=-1, string=["NUMBER"], flag=1)
# now switch off the terminal bus 2100 and island the radial buses
psspy.bus_data_2(2100, intgar1=4)
psspy.island()
# don't solve or save your case - it will blow up!!
ierr, (after_island_buses,) = psspy.abusint(sid=-1, string=["NUMBER"], flag=1)
# find the buses that were islanded
islanded = set(allbuses) - set(after_island_buses)

set is a special data type in Python that is an array, but only holds unique values. You can do mathematical set operations using it. In this case, I found the difference between the in service buses before and after switching off the radial ones. The difference will be only the radial buses.

Try set for yourself to see what I mean:

before = set([1,2,3,4,5])
after = set([1,2,5])
print (before - after)

The radial branches are those with a bus in common with this set of islanded buses.

radial_branches = [(frombus, tobus, p, q) 
                    for (frombus, tobus, p, q) in terminal_branches
                    if set((frombus, tobus)) & islanded]

Finally sum up the radial flows from the terminal station bus

from operator import itemgetter
totalp = sum(map(itemgetter(2), radial_branches)
totalq = sum(map(itemgetter(3), radial_branches)

Phew, thats it. I see that your report requires splitting this out into motor load and other load types. The procedure I'd use there is to just multiply the total with the fraction of motor load that you identify.

Hi Bruce,

You'd like a list of all of the loads grouped by bus number and their P and Q values. Is that close?

I'd use the subsystem data retrieval API to collect information about the loads. The subsystem API gives you all of the loads at once, rather than getting them one at time like with the single element data retrieval API.

Here is what it might look like to grab a list of the bus numbers and ids of all the loads in a case.

ierr, numbers_ids = psspy.aloadint(sid=-1, string=["NUMBER", "ID"])

sid=-1 is just a short-hand for "a subsystem that covers the entire case". The numbers_ids variable will be a list of lists:

[ [2002, 2003, 2004, 2004, 2005, ... ]
  [1, 1, 1, 2, 1, ...] ]

I'd do something similar to get the real and reactive power:

ierr, p_qs = psspy.aloadreal(sid=-1, string=["P", "Q"])

Now join the numbers, ids, P and Q values all together to make a list of four columns:

nums_ids_p_q = numbers_ids + p_qs

Transpose the list of four columns into rows because it is easier to work with:

loads = zip(*nums_ids_p_q)

Each row of the loads variable represents the number, id, P and Q value:

[ (2002, 1, 1.3, 0.8),
  (2003, 1, 1.04, 0.9),
  ... ]

Now your data is in a pretty standard looking format. Kind of like a spreadsheet in Excel. You could write little bits of code to sum up and give you totals per bus and per load.

Let me know how you get on with it. If you get some code working, but need some specific pointers, you can update your question pretty easily.

(edit)

The next step is to sum the total load flowing radially from a terminal station. And there are a couple of ways to do this.

1. Total load flowing from the terminal station. This is probably what you are looking for if you are sizing the bus at the terminal station.

2. Total load existing radially from the terminal station, excluding any losses. I'd sometimes use this method as a sanity check to see if my model is correct.

I'll take you through how to do number 1. It is far easier to calculate and answers your question (Let me know if it doesn't).

explanation of terms In our mock system, bus 2100 is the terminal station bus. Buses 2110, 2120 and 2130 are radial from the terminal station. Whereas buses 2240 and 2250 are not radial.

the method

  • List of all the P and Q branch flows in the case.

  • Select the P and Q branch flows from our target terminal (some radial, some will be back into the main system)

  • Identify which branches are radial

  • Sum those radial PQ values.

list all PQ flows in the case

ierr, from_to = psspy.aflowint(sid=-1, string=["FROMNUMBER", "TONUMBER"])
ierr, p_q = psspy.aflowreal(sid=-1, string=["P", "Q"])
from_to_p_q = from_to + p_q
branches = zip(*from_to_p_q)

branches from our terminal station assuming the number is 2100

terminal_bus = 2100
terminal_branches = [(frombus, tobus, p, q) 
                      for (frombus, tobus, p, q) in branches 
                      if terminal_bus in (frombus, tobus)]

find the radial branches I'll use a trick here and employ some set theory. Radial buses are those that become islanded when the terminal station bus is taken offline. This only works if your target network is truly radial from a single bus or a group of buses. Another method is to check for buses that are connected through a transformer.

# select all in service buses (flag=1)
ierr, (allbuses,) = psspy.abusint(sid=-1, string=["NUMBER"], flag=1)
# now switch off the terminal bus 2100 and island the radial buses
psspy.bus_data_2(2100, intgar1=4)
psspy.island()
# don't solve or save your case - it will blow up!!
ierr, (after_island_buses,) = psspy.abusint(sid=-1, string=["NUMBER"], flag=1)
# find the buses that were islanded
islanded = set(allbuses) - set(after_island_buses)

set is a special data type in Python that is an array, but only holds unique values. You can do mathematical set operations using it. In this case, I found the difference between the in service buses before and after switching off the radial ones. The difference will be only the radial buses.

Try set for yourself to see what I mean:

before = set([1,2,3,4,5])
after = set([1,2,5])
print (before - after)

The radial branches are those with a bus in common with this set of islanded buses.

radial_branches = [(frombus, tobus, p, q) 
                    for (frombus, tobus, p, q) in terminal_branches
                    if set((frombus, tobus)) & islanded]

Finally sum up the radial flows from the terminal station bus

from operator import itemgetter
totalp = sum(map(itemgetter(2), radial_branches)
totalq = sum(map(itemgetter(3), radial_branches)

Phew, thats it. I see that your report requires splitting this out into motor load and other load types. The procedure I'd use there is to just multiply the total with the fraction of motor load that you identify.

(another edit) Was just thinking about how some of your load will be directly attached to the terminal station bus (kind of like a house-load for the station). You will need to add on the load from these directly connected loads to your total. Your report shows the flow via Transformer B as a separate line entry - while I have summed the totals only. You could show the flow for each transformer separately instead of summing like I did at the end.

And one final note, I don't have a copy of PSS/E here with me in Germany so this code was based largely on my memory and the docs. You will certainly need to work on it a little.