From debb2bfa046f9590c29d98b08edc2c9bf770c39c Mon Sep 17 00:00:00 2001
From: Martin Bauer <martin.bauer@fau.de>
Date: Mon, 16 Oct 2017 20:16:17 +0200
Subject: [PATCH] Started Python export of mesh module

---
 apps/pythonmodule/PythonModule.cpp            |   7 ++
 apps/pythonmodule/setup.py                    |   2 +-
 src/mesh/CMakeLists.txt                       |   3 +-
 src/mesh/TriangleMeshes.h                     |   9 --
 src/mesh/boundary/BoundarySetup.h             |  32 ++++++
 src/mesh/python/Exports.h                     |  41 +++++++
 src/mesh/python/Exports.impl.h                | 103 ++++++++++++++++++
 src/postprocessing/python/Exports.h           |   2 +-
 src/postprocessing/python/Exports.impl.h      |   2 +-
 src/python_coupling/helper/SharedPtrDeleter.h |  47 ++++++++
 10 files changed, 235 insertions(+), 13 deletions(-)
 create mode 100644 src/mesh/python/Exports.h
 create mode 100644 src/mesh/python/Exports.impl.h
 create mode 100644 src/python_coupling/helper/SharedPtrDeleter.h

diff --git a/apps/pythonmodule/PythonModule.cpp b/apps/pythonmodule/PythonModule.cpp
index 82fab2e0..acbd1e0e 100644
--- a/apps/pythonmodule/PythonModule.cpp
+++ b/apps/pythonmodule/PythonModule.cpp
@@ -22,6 +22,7 @@
 #include "blockforest/python/Exports.h"
 #include "field/GhostLayerField.h"
 #include "field/python/Exports.h"
+#include "mesh/python/Exports.h"
 #include "geometry/python/Exports.h"
 #include "postprocessing/python/Exports.h"
 #include "python_coupling/Manager.h"
@@ -116,6 +117,12 @@ struct InitObject
       // Timeloop
       pythonManager->addExporterFunction( timeloop::exportModuleToPython );
 
+#ifdef WALBERLA_BUILD_WITH_OPENMESH
+
+      pythonManager->addExporterFunction( mesh::exportModuleToPython<FlagFieldTypes> );
+
+#endif
+
 #ifdef WALBERLA_BUILD_WITH_CUDA
       using walberla::cuda::GPUField;
       typedef bmpl::vector<GPUField<double>, GPUField<float>, GPUField<int>, GPUField<uint8_t>, GPUField<uint16_t> > GPUFields;
diff --git a/apps/pythonmodule/setup.py b/apps/pythonmodule/setup.py
index 146f6238..e75807e9 100644
--- a/apps/pythonmodule/setup.py
+++ b/apps/pythonmodule/setup.py
@@ -62,4 +62,4 @@ if sys.argv[1] == 'build':
           " - to install run 'make pythonModuleInstall'\n"
           " - for development usage: \n"
           "      bash: export PYTHONPATH=%s:$PYTHONPATH \n"
-          "      fish: set -x PYTHONPATH %s $PYTHONPATH \n" % ( walberla_binary_dir,walberla_binary_dir ) )
\ No newline at end of file
+          '      fish: set -x "PYTHONPATH %s:$PYTHONPATH \n"' % ( walberla_binary_dir,walberla_binary_dir ) )
\ No newline at end of file
diff --git a/src/mesh/CMakeLists.txt b/src/mesh/CMakeLists.txt
index 2583d339..bab4bb5e 100644
--- a/src/mesh/CMakeLists.txt
+++ b/src/mesh/CMakeLists.txt
@@ -4,6 +4,7 @@
 #
 ###################################################################################################
 
-waLBerla_add_module( DEPENDS blockforest boundary core domain_decomposition field geometry stencil vtk BUILD_ONLY_IF_FOUND OpenMesh )
+waLBerla_add_module( DEPENDS blockforest boundary core domain_decomposition
+                             python_coupling field geometry stencil vtk BUILD_ONLY_IF_FOUND OpenMesh )
 
 ###################################################################################################
diff --git a/src/mesh/TriangleMeshes.h b/src/mesh/TriangleMeshes.h
index ebd92c62..7d1886ae 100644
--- a/src/mesh/TriangleMeshes.h
+++ b/src/mesh/TriangleMeshes.h
@@ -57,15 +57,6 @@ struct FloatTraits : public OpenMesh::DefaultTraits
 typedef OpenMesh::TriMesh_ArrayKernelT<FloatTraits> FloatTriangleMesh;
 
 
-struct PythonTraits : public OpenMesh::DefaultTraits
-{
-   typedef OpenMesh::Vec3d Point;
-   typedef OpenMesh::Vec3d Normal;
-   typedef OpenMesh::Vec4f Color;
-};
-typedef OpenMesh::TriMesh_ArrayKernelT<PythonTraits> PythonTriangleMesh;
-
-
 template< typename MeshType >
 inline void getVertexHandles( const MeshType & mesh, const typename MeshType::FaceHandle fh,
                               typename MeshType::VertexHandle & vh0, typename MeshType::VertexHandle & vh1, typename MeshType::VertexHandle & vh2 )
diff --git a/src/mesh/boundary/BoundarySetup.h b/src/mesh/boundary/BoundarySetup.h
index 5d9b2152..60891394 100644
--- a/src/mesh/boundary/BoundarySetup.h
+++ b/src/mesh/boundary/BoundarySetup.h
@@ -30,6 +30,7 @@
 #include "domain_decomposition/BlockDataID.h"
 
 #include "field/GhostLayerField.h"
+#include "field/FlagField.h"
 
 #include "stencil/D3Q27.h"
 
@@ -63,6 +64,10 @@ public:
    template< typename BoundaryHandlingType, typename BoundaryFunction, typename Stencil = stencil::D3Q27 >
    void setBoundaries( const BlockDataID boundaryHandlingID, const BoundaryFunction & boundaryFunction, Location boundaryLocation );
 
+
+   template<typename FlagField_T>
+   void setFlag( const ConstBlockDataID flagFieldID, field::FlagUID flagUID, Location boundaryLocation );
+
    void writeVTKVoxelfile( const std::string & identifier = "voxelzation", bool writeGhostLayers = false, const std::string & baseFolder = std::string("vtk_out"),
                            const std::string & executionFolder = std::string("voxelization") );
 
@@ -120,6 +125,33 @@ void BoundarySetup::setDomainCells( const BlockDataID boundaryHandlingId, const
 }
 
 
+template<typename FlagField_T>
+void BoundarySetup::setFlag( const ConstBlockDataID flagFieldID, field::FlagUID flagUID, Location boundaryLocation )
+{
+   for( auto blockIt = structuredBlockStorage_->begin(); blockIt != structuredBlockStorage_->end(); ++blockIt )
+   {
+      FlagField_T * flagField  = blockIt->getData< FlagField_T >( flagFieldID );
+      WALBERLA_CHECK_NOT_NULLPTR( flagField, "flagFieldID invalid!" );
+      auto flag = flagField->getFlag(flagUID);
+
+      const VoxelizationField * voxelizationField = blockIt->getData< VoxelizationField >( *voxelizationFieldId_ );
+      WALBERLA_ASSERT_NOT_NULLPTR( voxelizationField );
+      WALBERLA_CHECK_LESS_EQUAL( numGhostLayers_, flagField->nrOfGhostLayers(), "You want to use mesh boundary setup with " \
+                                 << numGhostLayers_ << " but your flag field has only " << flagField->nrOfGhostLayers() << " ghost layers!" );
+
+      const uint8_t domainValue = boundaryLocation == INSIDE ? uint8_t(0) : uint8_t(1);
+
+      for( cell_idx_t z = -cell_idx_c( numGhostLayers_ ); z < cell_idx_c( voxelizationField->zSize() + numGhostLayers_ ); ++z )
+         for( cell_idx_t y = -cell_idx_c( numGhostLayers_ ); y < cell_idx_c( voxelizationField->ySize() + numGhostLayers_ ); ++y )
+            for( cell_idx_t x = -cell_idx_c( numGhostLayers_ ); x < cell_idx_c( voxelizationField->xSize() + numGhostLayers_ ); ++x )
+            {
+               if( voxelizationField->get( x, y, z ) != domainValue )
+                  flagField->addFlag(x, y, z, flag);
+            }
+   }
+}
+
+
 template< typename BoundaryHandlingType, typename BoundaryFunction, typename Stencil >
 void BoundarySetup::setBoundaries( const BlockDataID boundaryHandlingID, const BoundaryFunction & boundaryFunction, Location boundaryLocation )
 {
diff --git a/src/mesh/python/Exports.h b/src/mesh/python/Exports.h
new file mode 100644
index 00000000..0ae7cfd3
--- /dev/null
+++ b/src/mesh/python/Exports.h
@@ -0,0 +1,41 @@
+//======================================================================================================================
+//
+//  This file is part of waLBerla. waLBerla is free software: you can
+//  redistribute it and/or modify it under the terms of the GNU General Public
+//  License as published by the Free Software Foundation, either version 3 of
+//  the License, or (at your option) any later version.
+//
+//  waLBerla is distributed in the hope that it will be useful, but WITHOUT
+//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+//  for more details.
+//
+//  You should have received a copy of the GNU General Public License along
+//  with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
+//
+//! \file Exports.h
+//! \ingroup mesh
+//! \author Martin Bauer <martin.bauer@fau.de>
+//
+//======================================================================================================================
+
+#pragma once
+
+#include "waLBerlaDefinitions.h"
+#ifdef WALBERLA_BUILD_WITH_PYTHON
+
+namespace walberla {
+namespace mesh {
+
+
+   template<typename FlagFields>
+   void exportModuleToPython();
+
+
+} // namespace mesh
+} // namespace walberla
+
+
+#include "Exports.impl.h"
+
+#endif // WALBERLA_BUILD_WITH_PYTHON
diff --git a/src/mesh/python/Exports.impl.h b/src/mesh/python/Exports.impl.h
new file mode 100644
index 00000000..f8b7c700
--- /dev/null
+++ b/src/mesh/python/Exports.impl.h
@@ -0,0 +1,103 @@
+//======================================================================================================================
+//
+//  This file is part of waLBerla. waLBerla is free software: you can
+//  redistribute it and/or modify it under the terms of the GNU General Public
+//  License as published by the Free Software Foundation, either version 3 of
+//  the License, or (at your option) any later version.
+//
+//  waLBerla is distributed in the hope that it will be useful, but WITHOUT
+//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+//  for more details.
+//
+//  You should have received a copy of the GNU General Public License along
+//  with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
+//
+//! \file Exports.impl.h
+//! \ingroup mesh
+//! \author Martin Bauer <martin.bauer@fau.de>
+//
+//======================================================================================================================
+
+// Do not reorder includes - the include order is important
+#include "python_coupling/PythonWrapper.h"
+#include "python_coupling/helper/ModuleScope.h"
+
+#ifdef WALBERLA_BUILD_WITH_PYTHON
+#ifdef WALBERLA_BUILD_WITH_OPENMESH
+
+#include "python_coupling/Manager.h"
+#include "python_coupling/helper/MplHelpers.h"
+#include "python_coupling/helper/BlockStorageExportHelpers.h"
+#include "python_coupling/helper/PythonIterableToStdVector.h"
+
+#include "OpenMesh/Core/IO/MeshIO.hh"
+#include "OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh"
+
+
+#include "mesh/MeshIO.h"
+
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/vector_c.hpp>
+#include <boost/mpl/for_each.hpp>
+
+
+namespace OpenMesh {
+namespace Python {
+
+   struct MeshTraits : public OpenMesh::DefaultTraits {
+     /** Use double precision points */
+     typedef OpenMesh::Vec3d Point;
+
+     /** Use double precision normals */
+     typedef OpenMesh::Vec3d Normal;
+
+     /** Use RGBA colors */
+     typedef OpenMesh::Vec4f Color;
+   };
+
+}
+}
+
+
+using namespace boost::python;
+
+
+namespace walberla {
+namespace mesh {
+
+typedef OpenMesh::TriMesh_ArrayKernelT<OpenMesh::Python::MeshTraits> PythonMesh;
+
+namespace internal
+{
+    PythonMesh * exp_readAndBroadcast(const std::string & fileName)
+     {
+         auto mesh = make_shared< PythonMesh >();
+         mesh->request_vertex_colors();
+         mesh::readAndBroadcast( fileName, *mesh);
+         auto meshCopy = new PythonMesh(*mesh);
+         return meshCopy;
+     }
+
+}
+
+
+
+template<typename FlagFields>
+void exportModuleToPython()
+{
+   python_coupling::ModuleScope fieldModule( "mesh" );
+
+   def( "readAndBroadcast", &internal::exp_readAndBroadcast, (arg("fileName")),
+      return_value_policy<manage_new_object>());
+
+}
+
+
+
+} // namespace mesh
+} // namespace walberla
+
+
+#endif //WALBERLA_BUILD_WITH_PYTHON
+#endif //WALBERLA_BUILD_WITH_OPENMESH
\ No newline at end of file
diff --git a/src/postprocessing/python/Exports.h b/src/postprocessing/python/Exports.h
index 6429aaa4..17cd6b07 100644
--- a/src/postprocessing/python/Exports.h
+++ b/src/postprocessing/python/Exports.h
@@ -13,7 +13,7 @@
 //  You should have received a copy of the GNU General Public License along
 //  with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
 //
-//! \file PythonExports.h
+//! \file Exports.h
 //! \ingroup postprocessing
 //! \author Martin Bauer <martin.bauer@fau.de>
 //
diff --git a/src/postprocessing/python/Exports.impl.h b/src/postprocessing/python/Exports.impl.h
index 82494546..d896efdf 100644
--- a/src/postprocessing/python/Exports.impl.h
+++ b/src/postprocessing/python/Exports.impl.h
@@ -13,7 +13,7 @@
 //  You should have received a copy of the GNU General Public License along
 //  with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
 //
-//! \file PythonExports.impl.h
+//! \file Exports.impl.h
 //! \ingroup geometry
 //! \author Martin Bauer <martin.bauer@fau.de>
 //
diff --git a/src/python_coupling/helper/SharedPtrDeleter.h b/src/python_coupling/helper/SharedPtrDeleter.h
new file mode 100644
index 00000000..5745647f
--- /dev/null
+++ b/src/python_coupling/helper/SharedPtrDeleter.h
@@ -0,0 +1,47 @@
+//======================================================================================================================
+//
+//  This file is part of waLBerla. waLBerla is free software: you can
+//  redistribute it and/or modify it under the terms of the GNU General Public
+//  License as published by the Free Software Foundation, either version 3 of
+//  the License, or (at your option) any later version.
+//
+//  waLBerla is distributed in the hope that it will be useful, but WITHOUT
+//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+//  for more details.
+//
+//  You should have received a copy of the GNU General Public License along
+//  with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
+//
+//! \file SharedPtrDeleter.h
+//! \ingroup python_export
+//! \author Martin Bauer <martin.bauer@fau.de>
+//
+//======================================================================================================================
+
+#pragma once
+
+#include "python_coupling/PythonWrapper.h"
+
+namespace walberla {
+namespace python_coupling {
+
+    template<typename T>
+    class SharedPtrDeleterTiedToPythonObject
+    {
+    public:
+        SharedPtrDeleterTiedToPythonObject(PyObject * object) : object_(object) {}
+
+        void operator() (T * )
+        {
+           Py_DECREF(object_);
+        }
+    private:
+        PyObject * object_;
+    };
+
+
+} // namespace python_coupling
+} // namespace walberla
+
+
-- 
GitLab