From 1fb1423c3a99dfb6759d8769af8b8202fd4157cb Mon Sep 17 00:00:00 2001
From: Michael Buehlmann <michael.buehlmann@gmail.com>
Date: Wed, 9 Dec 2020 11:38:10 -0600
Subject: [PATCH] add mismatch behavior to python interface

---
 new_python/README.md     |  3 +++
 new_python/genericio.cpp | 44 +++++++++++++++++++++++++++++-----------
 2 files changed, 35 insertions(+), 12 deletions(-)

diff --git a/new_python/README.md b/new_python/README.md
index a5aef02..6c88db9 100644
--- a/new_python/README.md
+++ b/new_python/README.md
@@ -25,6 +25,9 @@ The library can then be imported in python. Here is a small example script:
 import numpy as np
 import pygio
 
+# inspect file
+pygio.inspect_genericio("generic_io_file")
+
 # read all variables
 data = pygio.read_genericio("generic_io_file")
 
diff --git a/new_python/genericio.cpp b/new_python/genericio.cpp
index b850e02..6b63bd6 100644
--- a/new_python/genericio.cpp
+++ b/new_python/genericio.cpp
@@ -17,14 +17,14 @@ namespace py = pybind11;
 
 class PyGenericIO : public gio::GenericIO {
 public:
-  PyGenericIO(const std::string& filename, unsigned method=gio::GenericIO::FileIOPOSIX)
+  PyGenericIO(const std::string& filename, gio::GenericIO::FileIO method=gio::GenericIO::FileIOPOSIX, gio::GenericIO::MismatchBehavior redistribute=gio::GenericIO::MismatchRedistribute)
 #ifdef GENERICIO_NO_MPI
       : gio::GenericIO(filename, method), num_ranks(0) {
 #else
       : gio::GenericIO(MPI_COMM_WORLD, filename, method), num_ranks(0) {
 #endif
     // open headers and rank info
-    openAndReadHeader(gio::GenericIO::MismatchRedistribute);
+    openAndReadHeader(redistribute);
     num_ranks = readNRanks();
     // read variable info
     getVariableInfo(variables);
@@ -136,11 +136,16 @@ private:
   std::vector<gio::GenericIO::VariableInfo> variables;
 };
 
-std::map<std::string, py::array> read_genericio(std::string filename, std::optional<std::vector<std::string>> var_names, PyGenericIO::FileIO method=PyGenericIO::FileIO::FileIOPOSIX) {
-  PyGenericIO reader(filename, method);
+std::map<std::string, py::array> read_genericio(std::string filename, std::optional<std::vector<std::string>> var_names, PyGenericIO::FileIO method=PyGenericIO::FileIO::FileIOPOSIX, PyGenericIO::MismatchBehavior redistribute=PyGenericIO::MismatchBehavior::MismatchRedistribute) {
+  PyGenericIO reader(filename, method, redistribute);
   return reader.read(var_names);
 }
 
+void inspect_genericio(std::string filename, PyGenericIO::FileIO method=PyGenericIO::FileIO::FileIOPOSIX, PyGenericIO::MismatchBehavior redistribute=PyGenericIO::MismatchBehavior::MismatchRedistribute) {
+  PyGenericIO reader(filename, method, redistribute);
+  reader.inspect();
+}
+
 #ifndef GENERICIO_NO_MPI
 void write_genericio(std::string filename, std::map<std::string, py::array> variables, std::array<double, 3> phys_scale, std::array<double, 3> phys_origin, PyGenericIO::FileIO method=PyGenericIO::FileIO::FileIOPOSIX) {
   // check data integrity, find particle count
@@ -189,11 +194,28 @@ void write_genericio(std::string filename, std::map<std::string, py::array> vari
 PYBIND11_MODULE(pygio, m) {
   m.doc() = "genericio python module";
 #ifndef GENERICIO_NO_MPI
-  m.def("_init_mpi", [](){MPI_Init(nullptr, nullptr); });
+  m.def("_init_mpi", [](){
+    int initialized;
+    MPI_Initialized(&initialized);
+    if(!initialized)
+      MPI_Init(nullptr, nullptr); 
+  });
 #endif
 
   py::class_<PyGenericIO> pyGenericIO(m, "PyGenericIO");
-  pyGenericIO.def(py::init<std::string>())
+
+  py::enum_<PyGenericIO::FileIO>(pyGenericIO, "FileIO")
+    .value("FileIOMPI", PyGenericIO::FileIO::FileIOMPI)
+    .value("FileIOPOSIX", PyGenericIO::FileIO::FileIOPOSIX)
+    .value("FileIOMPICollective", PyGenericIO::FileIO::FileIOMPICollective);
+
+  py::enum_<PyGenericIO::MismatchBehavior>(pyGenericIO, "MismatchBehavior")
+    .value("MismatchAllowed", PyGenericIO::MismatchBehavior::MismatchAllowed)
+    .value("MismatchDisallowed", PyGenericIO::MismatchBehavior::MismatchDisallowed)
+    .value("MismatchRedistribute", PyGenericIO::MismatchBehavior::MismatchRedistribute);
+
+  
+  pyGenericIO.def(py::init<std::string, PyGenericIO::FileIO, PyGenericIO::MismatchBehavior>(), py::arg("filename"), py::arg("method")=PyGenericIO::FileIO::FileIOPOSIX, py::arg("redistribute")=PyGenericIO::MismatchBehavior::MismatchRedistribute)
       .def("inspect", &PyGenericIO::inspect, "Print variable infos and size of GenericIO file")
       .def("get_variables", &PyGenericIO::get_variables, "Get a list of VariableInformations defined in the GenericIO file")
       .def("read_num_elems", (size_t (PyGenericIO::*)(int))(&PyGenericIO::readNumElems), py::arg("eff_rank")=-1)
@@ -202,10 +224,7 @@ PYBIND11_MODULE(pygio, m) {
       .def("read_phys_scale", &PyGenericIO::read_phys_scale)
       .def("read", &PyGenericIO::read, py::arg("variables")=nullptr);
 
-  py::enum_<PyGenericIO::FileIO>(pyGenericIO, "FileIO")
-    .value("FileIOMPI", PyGenericIO::FileIO::FileIOMPI)
-    .value("FileIOPOSIX", PyGenericIO::FileIO::FileIOPOSIX)
-    .value("FileIOMPICollective", PyGenericIO::FileIO::FileIOMPICollective);
+  
 
   py::class_<gio::GenericIO::VariableInfo>(pyGenericIO, "VariableInfo")
       .def_readonly("name", &gio::GenericIO::VariableInfo::Name)
@@ -216,8 +235,9 @@ PYBIND11_MODULE(pygio, m) {
         return std::string("<PyGenericIO.VariableInfo type=") +
                (vi.IsFloat ? "float" : "int") + " name='" + vi.Name + "'>";
       });
-  m.def("read_genericio", &read_genericio, py::arg("filename"), py::arg("variables")=nullptr, py::arg("method")=PyGenericIO::FileIO::FileIOPOSIX, py::return_value_policy::move);
+  m.def("read_genericio", &read_genericio, py::arg("filename"), py::arg("variables")=nullptr, py::arg("method")=PyGenericIO::FileIO::FileIOPOSIX, py::arg("redistribute")=PyGenericIO::MismatchBehavior::MismatchRedistribute, py::return_value_policy::move);
+  m.def("inspect_genericio", &inspect_genericio, py::arg("filename"), py::arg("method")=PyGenericIO::FileIO::FileIOPOSIX, py::arg("redistribute")=PyGenericIO::MismatchBehavior::MismatchRedistribute);
 #ifndef GENERICIO_NO_MPI
   m.def("write_genericio", &write_genericio, py::arg("filename"), py::arg("variables"), py::arg("phys_scale"), py::arg("phys_origin") = std::array<double, 3>({0., 0., 0.}), py::arg("method")=PyGenericIO::FileIO::FileIOPOSIX);
 #endif
-}
\ No newline at end of file
+}
-- 
GitLab