Skip to content

Commit

Permalink
Initial commit (#1)
Browse files Browse the repository at this point in the history
Signed-off-by: Geoffroy Jamgotchian <[email protected]>
  • Loading branch information
geofjamg authored Nov 16, 2020
1 parent fcec277 commit 61ce329
Show file tree
Hide file tree
Showing 26 changed files with 1,202 additions and 1 deletion.
91 changes: 91 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: CI

on: [push]

jobs:
build:
name: Build ${{ matrix.config.name }} ${{ matrix.python.name }} wheel
runs-on: ${{ matrix.config.os }}
strategy:
matrix:
config:
- {
name: linux,
os: ubuntu-latest,
}
- {
name: darwin,
os: macos-latest,
}
- {
name: windows,
os: windows-latest,
}
python:
- {
name: cp37,
version: '3.7',
}

steps:
- name: Checkout sources
uses: actions/checkout@v1
with:
submodules: true

- name: Setup GraalVM
uses: ayltai/setup-graalvm@v1
with:
java-version: 11
graalvm-version: 20.1.0
native-image: true

- name: Fix GraalVM Native Image on Windows
if: matrix.config.name == 'windows'
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
call "%JAVA_HOME%\bin\native-image.cmd" -jar "%JAVA_HOME%\lib\graalvm\svm-driver.jar" -H:Path="%JAVA_HOME%\bin"
- name: Setup Python
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python.version }}

- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
python -m pip install wheel
- name: Build wheel
run: python setup.py bdist_wheel

- name: Install wheel
shell: bash
run: python -m pip install dist/*.whl --user

- name: Run tests
run: python -m unittest tests/test.py

- name: Upload wheel
uses: actions/upload-artifact@v2
with:
name: gridpy-wheel-${{ matrix.config.name }}-${{ matrix.python.name }}
path: dist/*.whl

package:
name: Package wheels
runs-on: ubuntu-latest
needs: build

steps:
- name: Download wheels
uses: actions/download-artifact@v2
with:
path: download

- name: Upload wheels
uses: actions/upload-artifact@v2
with:
name: gridpy-wheels
path: download/**/*.whl
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# IntelliJ
.idea
*.iml

# Distribution
/dist
/gridpy.egg-info
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "cpp/lib/pybind11"]
path = cpp/lib/pybind11
url = https://github.com/pybind/pybind11.git
57 changes: 56 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,56 @@
# gridpy
# GridPy

A PowSyBl Python binding POC, based on GraalVM.

Prerequisite:
- Maven >= 3.5
- Cmake >= 3.14
- C++ compiler
- Python >= 3.7
- [GraalVM 20.1](https://github.com/graalvm/graalvm-ce-builds/releases/tag/vm-20.1.0)

To build from sources and install GrydPy package:
```bash
git clone --recursive https://github.com/gridsuite/gridpy.git
export JAVA_HOME=<path to GraalVM>
pip3 install . --user
```

To run unit tests:
```bash
python3 -m unittest tests/test.py
```

Usage example:

Import network and load flow modules:
```python
import gridpy.network
import gridpy.loadflow
import gridpy as gp

gp.print_version()
```
```bash
Powsybl versions:
+-----------------------+-----------------------+------------+------------------------------------------+-------------------------------+
| Repository name | Maven project version | Git branch | Git version | Build timestamp |
+-----------------------+-----------------------+------------+------------------------------------------+-------------------------------+
| powsybl-open-loadflow | 0.7.0 | UNKNOWN | 56e24b2262aaae28a065e3947caeb5759d753f97 | 2020-10-19T16:39:20.924+02:00 |
| powsybl-core | 3.7.1 | v3.7.1 | 44627f289a1ae0e7535f12ae9c3378f9a17182a1 | 2020-10-16T23:04:45.020+02:00 |
+-----------------------+-----------------------+------------+------------------------------------------+-------------------------------+
```
Create an IEEE 14 network and run a load flow:
```python
n = gp.network.create_ieee14()
r = gp.loadflow.run(n)
print(r.is_ok())
```
```bash
{network_0_iterations=3, network_0_status=CONVERGED}
True
```
Import a UCTE file:
```python
n = gp.network.load('test.uct')
```
1 change: 1 addition & 0 deletions cpp/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cmake-build-debug/
55 changes: 55 additions & 0 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#
# Copyright (c) 2020, RTE (http://www.rte-france.com)
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
cmake_minimum_required(VERSION 3.14)
project(gridpy-cpp)

include(ExternalProject)

set(CMAKE_CXX_STANDARD 11)

# change shared library rpath to resolve java library in same directory
# only works on linux
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH "$ORIGIN")

set(MAVEN_TARGET_DIR ${CMAKE_CURRENT_BINARY_DIR}/java)
set(GRIDPY_JAVA_LIB ${CMAKE_SHARED_LIBRARY_PREFIX}gridpy-java${CMAKE_SHARED_LIBRARY_SUFFIX})
set(GRIDPY_JAVA_OLD_LIB gridpy-java${CMAKE_SHARED_LIBRARY_SUFFIX})

# on MacOS, java library is created with an absolute path id, we need to fix it using install_name_tool before
# linking with our shared library
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
set(INSTALL_EXTRA_COMMAND COMMAND install_name_tool -id @loader_path/${GRIDPY_JAVA_LIB} ${MAVEN_TARGET_DIR}/${GRIDPY_JAVA_LIB})
endif()

# as GraalVm does not follow same library naming convention (lib prefix is missing on Linux and MacOS) we need to rename
# it in the install command step
ExternalProject_Add(gridpy-java
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../java/
PATCH_COMMAND mvn --batch-mode -PalternateBuildDir -Dalt.build.dir=${MAVEN_TARGET_DIR} package
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy ${MAVEN_TARGET_DIR}/${GRIDPY_JAVA_OLD_LIB} ${MAVEN_TARGET_DIR}/${GRIDPY_JAVA_LIB} ${INSTALL_EXTRA_COMMAND}
)

set(SOURCE_DIR "src")

include_directories(${SOURCE_DIR} ${MAVEN_TARGET_DIR})
set(SOURCES "${SOURCE_DIR}/gridpy.cpp")

link_directories(${MAVEN_TARGET_DIR})

add_subdirectory(lib/pybind11)
pybind11_add_module(_gridpy ${SOURCES} "${SOURCE_DIR}/bindings.cpp")

add_dependencies(_gridpy gridpy-java)
target_link_libraries(_gridpy PRIVATE ${GRIDPY_JAVA_LIB})

# copy auxiliary java lib so that it can be installed with module one
if(DEFINED CMAKE_LIBRARY_OUTPUT_DIRECTORY)
add_custom_command(TARGET _gridpy POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${MAVEN_TARGET_DIR}/${GRIDPY_JAVA_LIB} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
endif(DEFINED CMAKE_LIBRARY_OUTPUT_DIRECTORY)
1 change: 1 addition & 0 deletions cpp/lib/pybind11
Submodule pybind11 added at 06b673
32 changes: 32 additions & 0 deletions cpp/src/bindings.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Copyright (c) 2020, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <pybind11/pybind11.h>
#include "gridpy.h"

namespace py = pybind11;

PYBIND11_MODULE(_gridpy, m) {
gridpy::init();

m.doc() = "PowSyBl Python API";

m.def("print_version", &gridpy::printVersion, "Print a table with all PowSybBl modules version");

m.def("create_empty_network", &gridpy::createEmptyNetwork, "Create an empty network",
py::arg("id") = "Default");

m.def("create_ieee14_network", &gridpy::createIeee14Network, "Create an IEEE 14 network");

m.def("load_network", &gridpy::loadNetwork, "Load a network from a file");

py::class_<gridpy::LoadFlowResult>(m, "LoadFlowResult")
.def("is_ok", &gridpy::LoadFlowResult::isOk);

m.def("run_load_flow", &gridpy::runLoadFlow, "Run a load flow", py::arg("network"));

m.def("destroy_object_handle", &gridpy::destroyObjectHandle, "Destroy Java object handle", py::arg("object_handle"));
}
83 changes: 83 additions & 0 deletions cpp/src/gridpy.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/**
* Copyright (c) 2020, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "gridpy.h"
#include "gridpy-java.h"
#include <iostream>

namespace gridpy {

graal_isolate_t* isolate = nullptr;

void init() {
graal_isolatethread_t* thread = nullptr;

if (graal_create_isolate(nullptr, &isolate, &thread) != 0) {
throw std::runtime_error("graal_create_isolate error");
}
}

class GraalVmGuard {
public:
GraalVmGuard() {
if (!isolate) {
throw std::runtime_error("isolate has not been created");
}
if (graal_attach_thread(isolate, &thread_) != 0) {
throw std::runtime_error("graal_create_isolate error");
}
}

~GraalVmGuard() noexcept(false) {
if (graal_detach_thread(thread_) != 0) {
throw std::runtime_error("graal_detach_thread error");
}
}

graal_isolatethread_t * thread() const {
return thread_;
}

private:
graal_isolatethread_t* thread_ = nullptr;
};

LoadFlowResult::~LoadFlowResult() {
GraalVmGuard guard;
freeLoadFlowResultPointer(guard.thread(), ptr_);
}

void printVersion() {
GraalVmGuard guard;
printVersion(guard.thread());
}

void* createEmptyNetwork(const std::string& id) {
GraalVmGuard guard;
return createEmptyNetwork(guard.thread(), (char*) id.data());
}

void* createIeee14Network() {
GraalVmGuard guard;
return createIeee14Network(guard.thread());
}

void* loadNetwork(const std::string& file) {
GraalVmGuard guard;
return loadNetwork(guard.thread(), (char*) file.data());
}

LoadFlowResult* runLoadFlow(void* network) {
GraalVmGuard guard;
return new LoadFlowResult(runLoadFlow(guard.thread(), network));
}

void destroyObjectHandle(void* objectHandle) {
GraalVmGuard guard;
destroyObjectHandle(guard.thread(), objectHandle);
}

}
43 changes: 43 additions & 0 deletions cpp/src/gridpy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Copyright (c) 2020, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef GRIDPY_H
#define GRIDPY_H

#include <string>
#include "classes/gridpy-api.h"

namespace gridpy {

struct LoadFlowResult {

load_flow_result* ptr_;

explicit LoadFlowResult(load_flow_result* ptr)
: ptr_(ptr) {
}

bool isOk() { return ptr_->ok; }

~LoadFlowResult();
};

void init();

void printVersion();

void* createEmptyNetwork(const std::string& id);

void* createIeee14Network();

void* loadNetwork(const std::string& file);

LoadFlowResult* runLoadFlow(void* network);

void destroyObjectHandle(void* objectHandle);
}

#endif //GRIDPY_H
11 changes: 11 additions & 0 deletions gridpy/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#
# Copyright (c) 2020, RTE (http://www.rte-france.com)
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
import _gridpy


def print_version():
_gridpy.print_version()
Loading

0 comments on commit 61ce329

Please sign in to comment.