Skip to content

Commit

Permalink
v0.4.1. Update pysteps to stepspy.
Browse files Browse the repository at this point in the history
  • Loading branch information
changgang committed Aug 25, 2019
1 parent e85ca4d commit 4251c90
Show file tree
Hide file tree
Showing 10 changed files with 2,933 additions and 46 deletions.
103 changes: 57 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,46 +1,57 @@
Simulation Toolkit for Electrical Power Systems

Maintainer: Changgang Li <[email protected]>

Please go to http://steps.drli.group:310 for documentation.

How to build:
1) Select which Linear Algebra solver is to be used

Open STEPS.cbp and go to header/basic/sparse_matrix_define.h. Comment the solver you don't want to use.

For example, if you want to keep only c_sparse, comment out umfpack and klu.

Then go to source/basic/sparse_matrix_klu.cpp and umfpack.cpp, disable 'compile' and 'link' options of the two files.

2) Go compile the Linear Algebra solver.

For example, open csparse.cbp, and compile CSparse. The target should be 'static library'

3) Go compile the CppTest.

Open cpptest.cbp, and compile CppTest. The target should be 'static library'

4) Build STEPS

In the linker settings, you should include the above two static libraries libCSparse.a and libCpptest.a.

Then compile the STEPS.

5) If you want to build a 64bit version, use 64 bit MinGW and select the X64 version compiler.

If you want to compile a complete version, follow the steps:

1) Compile BLAS as static library

2) Compile UMFPACK as static library

3) Compile CSparse as static library

4) Compile CppTest as static library

5) Compile STEPS as dynamic library or exectuable file. Include libUMFPACK.a, libBLAS.a, libCSparse.a, and libCpptest.a. Put libBLAS.a after libUMFPACK.a.

When compiling in Windows, remove -no-pie and -lgfortran options and remove libKLU.a, libBLAS.a, libUMFPACK.a


# Simulation Toolkit for Electrical Power Systems
- Maintainer: Changgang Li <[email protected]> from School of Electrical Engineering, Shandong University.
- Documentation: http://steps.drli.group:310
- Date of Readme: August 25, 2019

## Major functions
Simulation Toolkit for Electrical Power Systems (STEPS) is an open source power system simulator designed for balanced large-scale AC-DC hybrid power system analysis.
Currently, it supports powerflow solution and dynamic simulation. In the future, short circuit analysis and eigenvalue analysis will be supported with no timetable.
The data format of STEPS is improved based on PSS/E raw and dyr data format. BPA dat format is also supported.
You are encourage to join us for further development.
## Prerequisite
1. Install Code::Blocks.
2. Install C and C++ compiler supprting C++17. GCC is recommended.
- For Unix-like systems, follow guides to install gcc and g++ with the latest version.
- For Windows system, MinGW-64 is suggested.
- Go to http://mingw-w64.org/ and go to its sourceforge download site for the latest version.
- Install 32-bit version or 64-bit version as you like. 64-bit version is recommended.
3. Start Code::Blocks, and configure its toolchain exectuable.
4. Install Python if you want to try the stepspy module. 64-bit version is recommended. However, if you want to use 32-bit dynamic library of STEPS, you should install Python of the 32-bit version.

## How to build
1. Select Linear Algebra solver to use
1. Open STEPS.cbp in the code/ folder with Code::Blocks.
2. Go to header/basic/sparse\_matrix\_define.h. Comment the solver you don't want to use. For example, if you want to keep only c\_sparse, comment umfpack and klu.
3. Go to source/basic/sparse\_matrix\_klu.cpp and umfpack.cpp, disable 'compile' and 'link' options of the two files.
4. Save STEPS.cbp.
2. Compile Linear Algebra solver.
1. Open the Linear Algebra solver project. For example, if you choose to use CSparse as default Linear Algebra solver, open csparse.cbp in the code/ folder with Code::Blocks.
2. Go 'Project'-'Properties'-'Build targets'and set type as 'static library'.
3. Compile CSparse. You should get a libCSparse.a in folder build/bin/Release/.
3. Compile CppTest.
1. Open cpptest.cbp in the code/ folder with Code::Blocks, set build target as 'static library'.
2. Compile CppTest. You should get a libCppTest.a in folder build/bin/Release/.
4. Build STEPS
1. Open STEPS.cbp in the code/ folder with Code::Blocks.
2. Go 'Project'-'Build options'-'Linker settings', and add the libCsparse.a and libCppTest.a library to 'Link libraries'.
3. Go 'Project'-'Properties'-'Build Target', and select build target
- If you want to compile STEPS as dynamic library, select 'Dynamic library', and set the output file name as 'libsteps.so' for Unix-like systems or 'libsteps.dll' for Windows systems.
- If you want to compile STEPS as console application, select 'Console application'.
4. If the target is dynamic library, disable 'Link' option for Source files with leading name of 'main'. If the target is console application, enable 'Link' option for only one of Source files with leading name of 'main'.
5. Compile the STEPS. You should get the output file in folder build/bin/Release/.
6. When compiling in Windows, remove -no-pie and -lgfortran options and remove libKLU.a, libBLAS.a, libUMFPACK.a

Here is a complete procedure of how to build STEPS.
1. Compile BLAS as static library. You can find BLAS.cbp in the code/ folder.
2. Compile UMFPACK as static library. You can find UMFPACK.cbp in the code/ folder.
3. Compile CSparse as static library. You can find CSparse.cbp in the code/ folder.
4. Compile CppTest as static library. You can find CppTest.cbp in the code/ folder.
5. Compile STEPS as dynamic library or exectuable file. Include libUMFPACK.a, libBLAS.a, libCSparse.a, and libCpptest.a. Put libBLAS.a after libUMFPACK.a.


## How to use stepspy
stepspy is a Python module of advanced APIs of STEPS. It enables most of STEPS applications. It is recommended to use stepspy in Python 3 of 64-bit version, though Python 2 is also supported.

stepspy will be uploaded to pypi.org soon, and will be installed via:
- pip3 install stepspy
- python -m pip install stepspy
21 changes: 21 additions & 0 deletions python/stepspy0.6/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2019 Changgang Li

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
13 changes: 13 additions & 0 deletions python/stepspy0.6/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
stepspy: a Python module of Simulation Toolkit for Electrical Power Systems

Author: Changgang Li <[email protected]> from the School of Electrical Engineering, Shandong University, China

stepspy provides almost all functions of STEPS (https://github.com/changgang/steps). It calls dynamic library of STEPS, and wraps it to advanced functions.

If you want to manually install stepspy, follow the instructions:
1. Go to https://github.com/changgang/steps to download or fork the latest version of STEPS.
2. Compile STEPS into dynamic library following instructions of STEPS.
3. Go to python/ folder of STEPS, and copy the latest version of stepspy/ to PYTHONPATH/Lib/site-packages/.
4, Move the dynamic library of STEPS to stepspy/libsteps/ in the PYTHONPATH/Lib/site-packages/.
5, If the VC runtime is missing, download and install Microsoft Visual C++ 2017 Redistributable of 32 or 64 bit version.
5, If VC runtime or Mingw Runtime is missing, install vcredit or copy libwinpthread-1.dll from mingw compiler/bin/ to c:/windows/system32 and c:/windows/SysWOW64
188 changes: 188 additions & 0 deletions python/stepspy0.6/demo/demo_pysteps2_powerflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
#coding = utf-8
'''
Here is a demo of showing how to slove powerflow with pysteps2.
Changgang Li, 2018/09/07
'''

from pysteps2 import STEPS # import the class 'STEPS'

simulator = STEPS() # create a STEPS simulator instance


powerflow_data_file = 'IEEE9.raw' # file name of powerflow data. Use absolute path if necessary
powerflow_data_type = 'PSS/E' # powerflow data type. Currently, use 'PSS/E' only

simulator.load_powerflow_data(powerflow_data_file, powerflow_data_type) # load powerflow data into the simulator

data_type = 'D' # if you want to set or get doubule data, set data_type as 'F' or 'D'.
data_name = 'MAX ACTIVE POWER IMBALANCE IN MW' # the data name in the powerflow solver of the simulator
# the data_type and data_name should be consistent. make sure the data_type is correct.
# If the data is double, use 'F' or 'D'. If the data is integer, use 'I'. If the data is boolean, use 'B'. If the data is string, use 'S'
'''
(1) when data_type is 'D' or 'F' you can set/get the following data
'MAX ACTIVE POWER IMBALANCE IN MW': maximum allowed active power mismatch at each bus, in MW. This is the powerflow convergence threshold of P equations.
'MAX REACTIVE POWER IMBALANCE IN MVAR': maximum allowed reactive power mismatch at each bus, in MVar. This is the powerflow convergence threshold of Q equations.
'ITERATION ACCELERATOR': acceleration factor for iteration. by default it is 1.0. if >1.0, then the powerflow solver is accelerated. if <1.0, the powerflow solver is decellerated.
(2) when data_type is 'I', you can set/get the following data
'MAX ITERATION': maximum iteration count allowed for solving powerflow. If set as 1, you can get the solution step by step.
(3)when data_type is 'B', you can set/get the following data
'FLAT START LOGIC': if true, powerflow will be solved with unity voltage profile (1.0pu, 0.0deg), if false, poewrflow will be solved from the current voltage profile.
'''

# here goes get and set maximum active power imbalance in MW
data_type = 'D'
data_name = 'MAX ACTIVE POWER IMBALANCE IN MW'
P_error_MW = simulator.get_powerflow_solver_parameter(data_type, data_name)

value = 0.001
simulator.set_powerflow_solver_parameter(data_type, data_name, value)

# here goes get and set maximum reactive power imbalance in MVAR
data_type = 'D'
data_name = 'MAX REACTIVE POWER IMBALANCE IN MVAR'
Q_error_MVar = simulator.get_powerflow_solver_parameter(data_type, data_name)

value = 0.001
simulator.set_powerflow_solver_parameter(data_type, data_name, value)

# here goes get and set maximum iteration
data_type = 'I'
data_name = 'MAX ITERATION'
Iter_max = simulator.get_powerflow_solver_parameter(data_type, data_name)

value = 50
simulator.set_powerflow_solver_parameter(data_type, data_name, value)

# here goes get and set flat start logic
data_type = 'B'
data_name = 'FLAT START LOGIC'
flat_flag = simulator.get_powerflow_solver_parameter(data_type, data_name)

value = False
simulator.set_powerflow_solver_parameter(data_type, data_name, value)

# now assuming that maximum active and reactive power imbalance are already set.
# show how to solve powerflow

# solve powerflow with flat start logic disabled
data_type = 'B'
data_name = 'FLAT START LOGIC'
value = False
simulator.set_powerflow_solver_parameter(data_type, data_name, value)

simulator.solve_powerflow('NR') # use 'NR' for Newton-Raphson solution, use 'PQ' for PQ decoupled solution

# solve powerflow with flat start logic enabled
data_type = 'B'
data_name = 'FLAT START LOGIC'
value = True
simulator.set_powerflow_solver_parameter(data_type, data_name, value)

simulator.solve_powerflow('PQ')

# if you want to solve powerflow step by step to get the solution process,
# you can set MAX ITERATION as 1, and Flat start logic as false
data_type = 'I'
data_name = 'MAX ITERATION'
value = 1
simulator.set_powerflow_solver_parameter(data_type, data_name, value)

data_type = 'B'
data_name = 'FLAT START LOGIC'
value = True
simulator.set_powerflow_solver_parameter(data_type, data_name, value)

simulator.solve_powerflow('NR') # first slove it with flat start enable

data_type = 'B'
data_name = 'FLAT START LOGIC'
value = False
simulator.set_powerflow_solver_parameter(data_type, data_name, value) # from now on, disable flat start

while not simulator.is_powerflow_converged(): # use is_powerflow_converged() to check if powerflow is converged
simulator.solve_powerflow('NR')
simulator.save_jacobian_matrix('jacobian.txt') # if you are solving with NR method, you can get jacobian matrix of each iteration in the file

# once powerflow is converged, you can export powerflow result to file
powerflow_result_file = 'pf_result.txt'
simulator.save_powerflow_result(powerflow_result_file) # you can check the file's contents

# you can get power loss of a solved powerflow case
ploss_MW = simulator.get_powerflow_loss() # in MW
print('Loss is:', ploss_MW)

# if you want to get the voltage of each bus, you can try the following codes
buses = simulator.get_all_buses()
for bus in buses:
bus_name = simulator.get_bus_data(bus, 'S', 'Name')
voltage = simulator.get_bus_data(bus, 'D', 'Voltage in PU')
angle = simulator.get_bus_data(bus, 'D', 'Angle in deg')
print(bus, bus_name, voltage, angle)

# if you want to get the generation of each generator, you can try the following codes
generators = simulator.get_generators_at_bus(0) # 0 indicate all generators will be returned
for generator in generators:
P = simulator.get_generator_data(generator, 'D', 'PGEN_MW')
Q = simulator.get_generator_data(generator, 'D', 'QGEN_MVAR')
print(generator, P, Q)

# if you want to get the load of each load, you can try the following codes
loads = simulator.get_loads_at_bus(0) # 0 indicate all loads will be returned
for load in loads:
P = simulator.get_load_data(load, 'D', 'P_MW')
Q = simulator.get_load_data(load, 'D', 'Q_MVAR')
print(load, P, Q)

# if you want to get the power of each line, you can try the following codes
lines = simulator.get_lines_at_bus(0) # 0 indicate all lines will be returned
for line in lines:
bus_send = simulator.get_line_data(line, 'I', 'BUS_SEND') # get the bus number of sending side
bus_recv = simulator.get_line_data(line, 'I', 'BUS_RECV') # get the bus number of receiving side
Psend = simulator.get_line_data(line, 'D', 'PSEND_MW') # active power at sending side
Qsend = simulator.get_line_data(line, 'D', 'QSEND_MVAR') # reactive power at sending side
Precv = simulator.get_line_data(line, 'D', 'PRECV_MW') # active power at receiving side
Qrecv = simulator.get_line_data(line, 'D', 'QRECV_MVAR') # reactive power at receiving side
print(line, bus_send, (Psend, Qsend), bus_recv, (Precv, Qrecv))

# if you want to get the power of each transformer, you can try the following codes
transformers = simulator.get_transformers_at_bus(0) # 0 indicate all transformers will be returned
for transformer in transformers:
bus_pri = simulator.get_transformer_data(transformer, 'I', 'Primary', 'BUS') # get the bus number of primary side
bus_sec = simulator.get_transformer_data(transformer, 'I', 'Secondary', 'BUS') # get the bus number of secondary side

P_pri = simulator.get_transformer_data(transformer, 'D', 'Primary', 'P_MW') # active power at primary side
Q_pri = simulator.get_transformer_data(transformer, 'D', 'Primary', 'Q_MVAR') # reactive power at primary side
P_sec = simulator.get_transformer_data(transformer, 'D', 'Secondary', 'P_MW') # active power at secondary side
Q_sec = simulator.get_transformer_data(transformer, 'D', 'Secondary', 'Q_MVAR') # reactive power at secondary side
print(transformer, bus_pri, (P_pri, Q_pri), bus_sec, (P_sec, Q_sec))



# if you want to change generation of each generaor, trye the following codes
generator = (2,'1') # generator bus, and generator ID, check generator line of raw file
simulator.set_generator_data(generator, 'D', 'PGEN_MW', 50.0) # remember, only P of generator at bus of type 2 can be changed

data_type = 'I'
data_name = 'MAX ITERATION'
value = 10
simulator.set_powerflow_solver_parameter(data_type, data_name, value)

data_type = 'B'
data_name = 'FLAT START LOGIC'
value = True
simulator.set_powerflow_solver_parameter(data_type, data_name, value)

simulator.solve_powerflow('NR')










23 changes: 23 additions & 0 deletions python/stepspy0.6/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import setuptools

with open("README.md", "r") as fh:
long_description = fh.read()

setuptools.setup(
name="stepspy",
version="0.6.0",
author="Changgang Li",
author_email="[email protected]",
description="Python module of Simulation Toolkit for Electrical Power Systems",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/changgang/steps",
packages=setuptools.find_packages(),
classifiers=[
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 3",
"Programming Language :: C++",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
)
3 changes: 3 additions & 0 deletions python/stepspy0.6/stepspy/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .stepspy import STEPS
name = 'stepspy'
__all__ = ['STEPS']
1 change: 1 addition & 0 deletions python/stepspy0.6/stepspy/libsteps/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__all__ = ['pylibsteps']
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Loading

0 comments on commit 4251c90

Please sign in to comment.