Tutorial ========= Use this tutorial to help you start working with GridWorkbench. .. note:: This tutorial is for **windows machines only!** Installation --------------- Install GWB using pip: .. code-block:: console > pip install gridworkbench If installation is successful, output should look like the following: .. code-block:: console Successfully installed gridworkbench-0.0.15 .. _reading: Creating a GWB Object & Reading in a PowerWorld Case ------------------------------------------------------------------------------------ The following lines of code do the following: #. Import the GridWorkbench class #. Create a GWB object named *wb* #. Open a PowerWorld case #. Read in the case information .. code-block:: console from gridworkbench import GridWorkbench fileName = r"Your Directory/Hawaii40_220906.pwb" # PowerWorld case directory wb = GridWorkbench(fileName) # create GWB object, open case wb.pwb_read_all(hush = True) # read in case, turn off default console printout An alternative, more explicit method to open and read in a PowerWorld case is shown below .. code-block:: console from gridworkbench import GridWorkbench wb = GridWorkbench() # create GWB object fileName = r"Your Directory/Hawaii40_220906.pwb" # PowerWorld case directory wb.open_pwb(fileName) # open case wb.pwb_read_all(hush = True) # read in case, turn off default printout A GWB object must be created before trying to access data from the PowerWorld case. Additionally, all data from the PowerWorld case must be accessed through the GWB object. The PowerWorld case used in these blocks of code can be downloaded here: `Electric Grid Test Case Repository `_. .. _container: Container Objects ---------------------------- GWB is organized into a hierarchy of containers, and each level may contain zero, one, or multiple containers of lower level/levels. The hierarchy from highest to lowest can be seen below. GWB allows users to move up and down the hierarchy. For instance, if the user has a bus object, they can use the bus's substation object to access its area object, which gives access to the region that the bus is in. .. figure:: Layout.* :align: center :width: 400 :alt: GWB Hierarchy GWB Object Hierarchy Determining Attributes of Objects -------------------------------------------------- To determine the attributes of a certain object in GWB, input the object as the argument to Python's built in *dir()* function. The attributes of the object are any of the strings in the list that do not start and end with a double underscore. For instance, in the output seen below, the bus object has attributes of area, branch_from, branch_to, and more. The non-attributes are usually listed first and are grouped together, then the attributes are listed together. .. code-block:: console for bus in wb.buses: print("Bus attributes: ", dir(bus)) break Output of the code above is seen below: .. code-block:: console Bus attributes: ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__','__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_node_map', '_number', '_sub', 'area', 'branch_from', 'branch_to', 'branches', 'branches_from', 'branches_to', 'gen', 'gens', 'load', 'loads', 'name', 'node', 'nodes', 'nominal_kv', 'number', 'region', 'shunt', 'shunts', 'status', 'sub', 'vang', 'vpu', 'wb', 'zone_number'] Region Objects ---------------------- A region is a very large portion of the power system. Most grids will only have one region. Regions can be accessed by their number or iterated over using the GWB object. Check out :ref:`this ` section in the :doc:`documentation` for more information. .. code-block:: console # Access region by its number print(wb.region(1)) # Iterate over regions for region in wb.regions: print("Region # =", region.number) Area Objects -------------------- Area objects comprise a large part of the power system, but are smaller than regions. They can be accessed by their number, through the workbench object, or a region object. Check out :ref:`this ` section in the :doc:`documentation` for more information. .. code-block:: console # Access area by number areaObject = wb.area(1) # Access area through GWB object for area in wb.areas: print("Area name =", area.name) # Access area through regions for region in wb.regions: for area in region.areas: print("Area name =", area.name) Substation Objects ---------------------------- Substations can be accessed by number, through their containing area, or through the workbench object. Its main attributes are buses (a list containing all the buses inside the substation), name, and number. Check out :ref:`this ` section in the :doc:`documentation` for more information. .. code-block:: console # Access substation by number substationObject = wb.sub(2) # Access substation by iterating through areas for area in wb.areas: for sub in area.subs: print("Substation number =", sub.number) # Access substation number print("Substation name =", sub.name) # Access substation name # Access substations through GWB object for sub in wb.subs: print("Substation name =", sub.name) Bus Objects ------------------ Buses represent electrical points in a power system. They can hold other grid objects, such as generators, loads, shunts, and branches. Buses can be accessed by their number, by iterating through substations, or by iterating through the GWB object. Its main attributes are name, number, nominal voltage, and their attached objects (generators, loads, shunts, and branches). Check out :ref:`this ` section in the :doc:`documentation` for more information. .. code-block:: console # Access bus by number busObject = wb.bus(1) # Access bus by iterating through substations for sub in wb.subs: for bus in sub.buses: print("Bus name =", bus.name) print("Bus number =", bus.number) print("Bus nominal voltage =", bus.nominal_kv) # Access bus by iterating through GWB object for bus in wb.buses: print("Bus name =", bus.name) Generator Objects --------------------------- The most common ways to access generator objects is through their buses or through the GWB object. Their most common attributes are power, reactive power, ID, and fuel type. Check out :ref:`this ` section in the :doc:`documentation` for more information. .. code-block:: console # Access generators by iterating through buses for bus in wb.buses: for gen in bus.gens: print("Generator power =", gen.p) # Access real power print("Generator reactive power =", gen.q) # Access reactive power print("Generator ID =", gen.id) # Access ID print("Generator fuel type =", gen.fuel_type) # Access fuel type # Access generators through GWB object for gen in wb.gens: print("Generator power =", gen.p) # Access real power Load Objects -------------------- The most common ways to access load objects is through their buses or through the GWB object. The main load attributes are real power, reactive power, id, and status (returns a Boolean indicating whether or not the load is open or closed: True if load is closed, False if open). Check out :ref:`this ` section in the :doc:`documentation` for more information. .. code-block:: console # Access loads by iterating through buses for bus in wb.buses: for load in bus.loads: print("Load power", load.p) # Access real power print("Load reactive power", load.q) # Access reactive power print("Load ID =", load.id) # Access load ID print("Load status =", load.status) # Access load status # Access loads through GWB object for load in wb.loads: print("Load power =", load.p) # Access real power Shunt Objects -------------------- Shunt objects can be accessed through their buses or through the GWB object. The attributes of shunts can be determined by using the *dir()* function. Check out :ref:`this ` section in the :doc:`documentation` for more information. .. code-block:: console # Access shunts through GWB object for shunt in wb.shunts: print("Shunt reactive power =", shunt.q) # Access reactive power Branch Objects ---------------------- Branch objects can represent two-node objects such as transmission lines and transformers. Most branch objects will be transmission lines and some will be transformers. It is possible to access branches from any container, but it is most useful to access them from their buses since two buses are connected by a branch. Branches can also be accessed through the GWB object. Their most commonly used attributes are susceptance, conductance, power ratings, resistance, inductance, from bus, to bus, and branch_device_type. Check out :ref:`this ` section in the :doc:`documentation` for more information. .. code-block:: console # Access branches by iterating through buses for bus in wb.buses: for branch in bus.branches: print("Branch susceptance =", branch.B) # Access branch susceptance # Access branches through GWB object for branch in wb.branches: print("Branch Rating A =", branch.MVA_Limit_A) Using Easy Sim Auto (ESA) in GWB -------------------------------------------------- ESA can be accessed using GWB through the attribute “esa” in the GWB class. See ESA’s documentation for a list of the most commonly used functions here: `Easy Sim Auto `_. Although the above documentation covers many commonly used functions, there may still be some functions that need to be used that are not listed in the documentation. To use non-default ESA functions, use ESA’s *RunScriptCommand()* function to access the desired function in PowerWorld. Other PowerWorld commands can be found here: `PowerWorld Auxiliary File Format `_. Using GWB Without SimAuto or ESA - Using aux Files ---------------------------------------------------------------------------- If you don't have SimAuto installed, you can still use GWB, but it must be done using aux files. To access data in PowerWorld (such as bus data), open the model explorer and save the desired data as an aux file. The following example shows how to read in bus data from an aux file for bus data. .. code-block:: console from gridworkbench import GridWorkbench wb = GridWorkbench() directory = r"directory to aux file.AUX" wb.import_aux(directory) for bus in wb.buses: print(bus.name) Bus information is retrieved just like it was done when SimAuto was installed. If changes are made to the case, you can save them in a new aux file, which is shown in the following lines of code: .. code-block:: console export_path = r"new directory.AUX" wb.export_aux(export_path) Other objects can be read in and accessed in a similar manner-just download their aux files, and read them in.