Skip to content

Commit

Permalink
TCOPFLOW Python Bindings First Pass (#131)
Browse files Browse the repository at this point in the history
* add new branch and pytests repo

* add tecopflow files

* clean dir and add new tcopflow files

* Apply pre-commmit fixes

* add tcopflow files to python bindings

* rename python files from test to example

* Apply pre-commmit fixes

* rebase on origin branch

* test_tcopflow.cpp

* sort tcopflow functions

* Apply pre-commmit fixes

* test tcopflow functions

* first passing tcopflow test

* Apply pre-commmit fixes

* clean tcopflow test file

* Apply pre-commmit fixes

* file clean up and comment added to test_tcopflow.py

* removed tcopflow_bind files

* add examples to example_tcopflow.pu

* Apply pre-commmit fixes

* remove u unused value on test_5_tcopflow.py

* Apply pre-commmit fixes

* checked preconditions before importing exago on test_5_tcopflow.py

* check preconditions for all tests

* Apply pre-commmit fixes

* documented tcopflow function on python_bindings.md file and tested the functions

* Added functions to exago_python_tcopflow.cpp and updated the documentation

* Apply pre-commmit fixes

* checked preconditions() before importing exago

* fix pre-commit checks

* Apply pre-commmit fixes

* check preconditions and import exago

* check preconditions and import exago on test_9_finalize.py

* Apply pre-commmit fixes

* remove duplicate check_preconditions() on test_0_initialize.py

* import exago after pre_conditions check

---------

Co-authored-by: Mohan, Jaya <[email protected]>
Co-authored-by: cameronrutherford <[email protected]>
Co-authored-by: Jaelyn Litzinger <[email protected]>
Co-authored-by: jaelynlitz <[email protected]>
Co-authored-by: Jaya Mohan <[email protected]>
Co-authored-by: Jaya Mohan <[email protected]>
Co-authored-by: Jaya Mohan <[email protected]>
Co-authored-by: Jayapreethi <[email protected]>
Co-authored-by: Jaya Mohan <[email protected]>
  • Loading branch information
10 people authored May 21, 2024
1 parent edc9e45 commit 84fdbf2
Show file tree
Hide file tree
Showing 18 changed files with 259 additions and 21 deletions.
28 changes: 27 additions & 1 deletion docs/python_bindings.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ The following table assumes `opflow = exago.OPFLOW()`.
| `OPFLOWReadMatPowerData` | `opflow.read_mat_power_data` | |
| `OPFLOWSolutionToPS` | `opflow.solution_to_ps` | |
| `OPFLOWSetUpPS` | `opflow.set_up_ps` | |
| `OPFLOWSkipOptions` | `opflow.skip_options | |
| `OPFLOWSkipOptions` | `opflow.skip_options` | |
| `OPFLOWSetLinesMonitored` | | Implemented as two different methods: | |
| |`opflow.set_lines_monitored([...])` | Specify a list of line kvlevels (type `float`) to monitor |
| |`opflow.set_lines_monitored(n, "file")` | Read `n` line kvlevels from a file (`n=-1` for all). |
Expand Down Expand Up @@ -267,6 +267,32 @@ The following table assumes `sopflow = exago.SOPFLOW()`.
| ` SOPFLOWSaveSolution` | `save_solution` | |
| ` SOPFLOWSaveSolutionAll` | `save_solution_all` | |

#### TCOPFLOW

The following table assumes `tcopflow = exago.TCOPFLOW()`.

| C++ API | Python API | Notes |
|---|---|---|
| `TCOPFLOW` | `exago.TCOPFLOW` class | |
| ` TCOPFLOWSetModel` | `set_model` | |
| ` TCOPFLOWSetNetworkData` | `set_network_data` | |
| ` TCOPFLOWSetSolver` | `set_solver` | |
| ` TCOPFLOWSetTolerance` | `set_tolerance` | |
| ` TCOPFLOWSetTimeStepandDuration` | `set_timestep_and_duration` | |
| ` TCOPFLOWSetLoadProfiles` | `set_load_profiles` | |
| ` TCOPFLOWSetWindGenProfiles` | `wind_gen_profiles` | |
| ` TCOPFLOWSetup` | `setup` | |
| ` TCOPFLOWSolve` | `solve` | |
| ` TCOPFLOWGetConvergenceStatus` | `get_convergence_status` | |
| ` TCOPFLOWGetObjective` | `get_objective` | |
| ` TCOPFLOWGetNumIterations` | `get_num_iterations` | |
| ` TCOPFLOWSetTolerance` | `set_tolerance` | |
| ` TCOPFLOWGetTolerance` | `get_tolerance` | |
| ` TCOPFLOWPrintSolution` | `print_solution` | |
| ` TCOPFLOWSaveSolution` | `save_solution` | |
| ` TCOPFLOWSavesolutionAll` | `save_solution_all` ||


### Enums

`OutputFormat` is the enum that specifies the output format in functions like `opflow.save_solution`.
Expand Down
6 changes: 4 additions & 2 deletions interfaces/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ if(EXAGO_ENABLE_IPOPT OR EXAGO_ENABLE_HIOP)
endif()

if(EXAGO_ENABLE_IPOPT)
list(APPEND EXAGO_PY_SRCS exago_python_scopflow.cpp exago_python_sopflow.cpp)
list(APPEND EXAGO_PY_LIBS ExaGO::SOPFLOW ExaGO::SCOPFLOW)
list(APPEND EXAGO_PY_SRCS exago_python_scopflow.cpp exago_python_sopflow.cpp
exago_python_tcopflow.cpp
)
list(APPEND EXAGO_PY_LIBS ExaGO::SOPFLOW ExaGO::SCOPFLOW ExaGO::TCOPFLOW)
endif()

# New true python bindings
Expand Down
4 changes: 4 additions & 0 deletions interfaces/python/exago_python.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,9 @@ PYBIND11_MODULE(exago, m) {

extern void init_exago_sopflow(pybind11::module & m);
init_exago_sopflow(m);

extern void init_exago_tcopflow(pybind11::module & m);
init_exago_tcopflow(m);

#endif
}
141 changes: 141 additions & 0 deletions interfaces/python/exago_python_tcopflow.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#include "exago_python_tcopflow.hpp"

// -------------------------------------------------------------
// class TCOPFLOW_wrapper
//
// Wrap to make sure allocation and destruction is handled correctly
// -------------------------------------------------------------
class TCOPFLOW_wrapper {
public:
TCOPFLOW tcopf;
TCOPFLOW_wrapper(void) {
PetscErrorCode ierr;
MPI_Comm communicator;
ierr = ExaGOGetSelfCommunicator(&communicator);
ExaGOCheckError(ierr);
ierr = TCOPFLOWCreate(communicator, &tcopf);
ExaGOCheckError(ierr);
}
~TCOPFLOW_wrapper(void) {
PetscErrorCode ierr;
ierr = TCOPFLOWDestroy(&tcopf);
ExaGOCheckError(ierr);
}
};

// -------------------------------------------------------------
// init_exago_tcopflow
// -------------------------------------------------------------
void init_exago_tcopflow(pybind11::module &m) {

pybind11::class_<TCOPFLOW_wrapper>(m, "TCOPFLOW")
.def(pybind11::init())
.def("set_network_data",
[](TCOPFLOW_wrapper &w, std::string filename) {
PetscErrorCode ierr;
ierr = TCOPFLOWSetNetworkData(w.tcopf, filename.c_str());
ExaGOCheckError(ierr);
})
.def("set_solver",
[](TCOPFLOW_wrapper &w, std::string solver) {
PetscErrorCode ierr;
ierr = TCOPFLOWSetSolver(w.tcopf, solver.c_str());
ExaGOCheckError(ierr);
})
.def("set_tolerance",
[](TCOPFLOW_wrapper &w, double tol) {
PetscErrorCode ierr;
ierr = TCOPFLOWSetTolerance(w.tcopf, tol);
ExaGOCheckError(ierr);
})
.def("setup",
[](TCOPFLOW_wrapper &w) {
PetscErrorCode ierr;
ierr = TCOPFLOWSetUp(w.tcopf);
ExaGOCheckError(ierr);
})
.def("set_model",
[](TCOPFLOW_wrapper &w, std::string model) {
PetscErrorCode ierr;
ierr = TCOPFLOWSetModel(w.tcopf, model.c_str());
ExaGOCheckError(ierr);
})

.def("solve",
[](TCOPFLOW_wrapper &w) {
PetscErrorCode ierr;
ierr = TCOPFLOWSolve(w.tcopf);
ExaGOCheckError(ierr);
})
.def("set_time_step_and_duration",
[](TCOPFLOW_wrapper &w, double dt, double tmax) {
PetscErrorCode ierr;
ierr = TCOPFLOWSetTimeStepandDuration(w.tcopf, dt, tmax);
ExaGOCheckError(ierr);
})
.def("set_load_profiles",
[](TCOPFLOW_wrapper &w, const std::string &pload,
const std::string &qload) {
PetscErrorCode ierr;
ierr =
TCOPFLOWSetLoadProfiles(w.tcopf, pload.c_str(), qload.c_str());
ExaGOCheckError(ierr);
})
.def("set_wind_gen_profiles",
[](TCOPFLOW_wrapper &w, std::string filename) {
PetscErrorCode ierr;
ierr = TCOPFLOWSetWindGenProfiles(w.tcopf, filename.c_str());
ExaGOCheckError(ierr);
})
.def("get_convergence_status",
[](TCOPFLOW_wrapper &w) -> bool {
PetscErrorCode ierr;
PetscBool flag;
ierr = TCOPFLOWGetConvergenceStatus(w.tcopf, &flag);
ExaGOCheckError(ierr);
return flag;
})
.def("get_objective",
[](TCOPFLOW_wrapper &w) -> double {
PetscErrorCode ierr;
double obj;
ierr = TCOPFLOWGetObjective(w.tcopf, &obj);
ExaGOCheckError(ierr);
return obj;
})
.def("get_num_iterations",
[](TCOPFLOW_wrapper &w) -> int {
PetscErrorCode ierr;
PetscInt n;
ierr = TCOPFLOWGetNumIterations(w.tcopf, &n);
ExaGOCheckError(ierr);
return n;
})
.def("get_tolerance",
[](TCOPFLOW_wrapper &w) -> double {
PetscErrorCode ierr;
double tol;
ierr = TCOPFLOWGetTolerance(w.tcopf, &tol);
ExaGOCheckError(ierr);
return tol;
})
.def("print_solution",
[](TCOPFLOW_wrapper &w, int isol) {
PetscErrorCode ierr;
ierr = TCOPFLOWPrintSolution(w.tcopf, isol);
ExaGOCheckError(ierr);
})
.def("save_solution",
[](TCOPFLOW_wrapper &w, int n, OutputFormat fmt,
std::string outfile) {
PetscErrorCode ierr;
ierr = TCOPFLOWSaveSolution(w.tcopf, n, fmt, outfile.c_str());
ExaGOCheckError(ierr);
})
.def("save_solution_all",
[](TCOPFLOW_wrapper &w, OutputFormat fmt, std::string outdir) {
PetscErrorCode ierr;
ierr = TCOPFLOWSaveSolutionAll(w.tcopf, fmt, outdir.c_str());
ExaGOCheckError(ierr);
});
}
8 changes: 8 additions & 0 deletions interfaces/python/exago_python_tcopflow.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef _exago_python_tcopflow_hpp_
#define _exago_python_tcopflow_hpp_

#include "exago_python_opflow.hpp"
#include <tcopflow.h>
#include <private/tcopflowimpl.h>

#endif
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
17 changes: 17 additions & 0 deletions interfaces/python/example_tcopflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import os
import exago

# Initialize a given application to be run
exago.initialize("tcopflow_test")
tcopf = exago.TCOPFLOW()
path = exago.prefix()
tcopf.set_network_data(
os.path.join(path, 'share', 'exago', 'datafiles', 'case9', 'case9mod.m'))
tcopf.set_solver("IPOPT")
tcopf.solve()
tcopf.print_solution(0)

# Delete instance before finalization (try, at least)
del tcopf

exago.finalize()
11 changes: 10 additions & 1 deletion tests/interfaces/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,16 @@ endif()

# The SCOPFLOW and SOPFLOW API tests are currently written only for IPOPT
if(EXAGO_ENABLE_IPOPT)
string(APPEND TEST_FILES " " "test_3_scopflow.py" " " "test_4_sopflow.py")
string(
APPEND
TEST_FILES
" "
"test_3_scopflow.py"
" "
"test_4_sopflow.py"
" "
"test_5_tcopflow.py"
)
endif()
string(APPEND TEST_FILES " " "test_9_finalize.py")

Expand Down
6 changes: 2 additions & 4 deletions tests/interfaces/python/test_0_initialize.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
# test initializing exago only once
from check_preconditions import check_preconditions
import os
import pytest
from check_preconditions import check_preconditions
import mpi4py.rc
mpi4py.rc.threads = False
from mpi4py import MPI # noqa
import exago # noqa


check_preconditions()
import exago # noqa


@pytest.mark.nocomm
Expand Down
5 changes: 2 additions & 3 deletions tests/interfaces/python/test_1_pflow.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
from check_preconditions import check_preconditions
import os
import pytest
from check_preconditions import check_preconditions
import mpi4py.rc
mpi4py.rc.threads = False
from mpi4py import MPI # noqa
import exago # noqa

check_preconditions()
import exago # noqa


@pytest.mark.nocomm
Expand Down
6 changes: 2 additions & 4 deletions tests/interfaces/python/test_2_opflow.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
from check_preconditions import check_preconditions
import os
import pytest
from check_preconditions import check_preconditions
import mpi4py.rc
mpi4py.rc.threads = False
from mpi4py import MPI # noqa
import exago # noqa

check_preconditions()
import exago # noqa

exago_ignore = -1000000

Expand Down
4 changes: 2 additions & 2 deletions tests/interfaces/python/test_3_scopflow.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
from check_preconditions import check_preconditions
import tempfile
import os
import shutil
import pytest
from check_preconditions import check_preconditions
import mpi4py.rc
mpi4py.rc.threads = False
from mpi4py import MPI # noqa
check_preconditions()
import exago # noqa

check_preconditions()

exago_ignore = -1000000

Expand Down
4 changes: 2 additions & 2 deletions tests/interfaces/python/test_4_sopflow.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
from check_preconditions import check_preconditions
import tempfile
import os
import shutil
import pytest
from check_preconditions import check_preconditions
import mpi4py.rc
mpi4py.rc.threads = False
from mpi4py import MPI # noqa
check_preconditions()
import exago # noqa

check_preconditions()

exago_ignore = -1000000

Expand Down
37 changes: 37 additions & 0 deletions tests/interfaces/python/test_5_tcopflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from check_preconditions import check_preconditions
import tempfile
import os
import shutil
import pytest
import mpi4py.rc
mpi4py.rc.threads = False
from mpi4py import MPI # noqa
check_preconditions()
import exago # noqa


def run_tcopflow(solver):
tcopf = exago.TCOPFLOW()
path = exago.prefix()

tcopf.set_tolerance(1.0E-03)
tcopf.set_network_data(os.path.join(
path, 'share', 'exago', 'datafiles', 'case9', 'case9mod_gen3_wind.m'))
tcopf.set_solver(solver)

tcopf.setup()
tcopf.solve()

assert tcopf.get_convergence_status()

obj = tcopf.get_objective()
assert isinstance(obj, float)

n = tcopf.get_num_iterations()
assert isinstance(n, int)


@pytest.mark.nocomm
@pytest.mark.MPI
def test_tcopflow_1():
run_tcopflow('IPOPT')
3 changes: 1 addition & 2 deletions tests/interfaces/python/test_9_finalize.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# test only run once things here
import pytest
import exago
from check_preconditions import check_preconditions

check_preconditions()
import exago # noqa


@pytest.mark.nocomm
Expand Down

0 comments on commit 84fdbf2

Please sign in to comment.