From 82a56ad8d0407244e4aa50f4873938c5fce88e04 Mon Sep 17 00:00:00 2001 From: Alexander Grayver Date: Thu, 28 Nov 2019 17:50:10 +0100 Subject: [PATCH] Add manifolds to the python bindings --- .../include/manifold_wrapper.h | 93 ++++++++ .../include/triangulation_wrapper.h | 7 + contrib/python-bindings/source/CMakeLists.txt | 2 + .../python-bindings/source/export_manifold.cc | 60 +++++ .../source/export_triangulation.cc | 13 +- .../source/manifold_wrapper.cc | 220 ++++++++++++++++++ .../source/triangulation_wrapper.cc | 33 +++ contrib/python-bindings/source/wrappers.cc | 4 + doc/news/changes/minor/20191128Grayver | 5 + 9 files changed, 436 insertions(+), 1 deletion(-) create mode 100644 contrib/python-bindings/include/manifold_wrapper.h create mode 100644 contrib/python-bindings/source/export_manifold.cc create mode 100644 contrib/python-bindings/source/manifold_wrapper.cc create mode 100644 doc/news/changes/minor/20191128Grayver diff --git a/contrib/python-bindings/include/manifold_wrapper.h b/contrib/python-bindings/include/manifold_wrapper.h new file mode 100644 index 0000000000..e72018c338 --- /dev/null +++ b/contrib/python-bindings/include/manifold_wrapper.h @@ -0,0 +1,93 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2016 - 2017 by the deal.II authors +// +// This file is part of the deal.II library. +// +// The deal.II library is free software; you can use it, redistribute +// it, and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// The full text of the license can be found in the file LICENSE.md at +// the top level directory of deal.II. +// +// --------------------------------------------------------------------- + +#ifndef dealii_manifold_wrapper_h +#define dealii_manifold_wrapper_h + +#include + +#include + +#include + +DEAL_II_NAMESPACE_OPEN + +namespace python +{ + class ManifoldWrapper + { + public: + /** + * Copy constructor. + */ + ManifoldWrapper(const ManifoldWrapper &other); + + /** + * Constructor. + */ + ManifoldWrapper(const int dim, const int spacedim); + + /** + * Destructor. + */ + ~ManifoldWrapper(); + + /** + * Create SphericalManifold + */ + void + create_spherical(const PointWrapper center); + + /** + * Create PolarManifold + */ + void + create_polar(const PointWrapper center); + + /** + * Create CylindricalManifold + */ + void + create_cylindrical(const int axis, const double tolerance); + + /** + * Return pointer to an underlying manifold object + */ + void * + get_manifold() const; + + + private: + /** + * Dimension of the underlying Manifold object. + */ + int dim; + + /** + * Space dimension of the underlying Manifold object. + */ + int spacedim; + + /** + * Pointer that can be casted to the underlying Mapping object. + */ + void *manifold_ptr; + }; + +} // namespace python + +DEAL_II_NAMESPACE_CLOSE + +#endif diff --git a/contrib/python-bindings/include/triangulation_wrapper.h b/contrib/python-bindings/include/triangulation_wrapper.h index 5e3f679be9..bbab008dee 100644 --- a/contrib/python-bindings/include/triangulation_wrapper.h +++ b/contrib/python-bindings/include/triangulation_wrapper.h @@ -20,6 +20,7 @@ #include +#include #include #include @@ -301,6 +302,12 @@ namespace python void flatten_triangulation(TriangulationWrapper &tria_out); + /** + * + */ + void + set_manifold(const int number, ManifoldWrapper &manifold); + /** * Refine all the cells @p n times. */ diff --git a/contrib/python-bindings/source/CMakeLists.txt b/contrib/python-bindings/source/CMakeLists.txt index 376dbe35b0..775a2d7e52 100644 --- a/contrib/python-bindings/source/CMakeLists.txt +++ b/contrib/python-bindings/source/CMakeLists.txt @@ -95,11 +95,13 @@ SET(_src export_point.cc export_triangulation.cc export_mapping.cc + export_manifold.cc cell_accessor_wrapper.cc tria_accessor_wrapper.cc point_wrapper.cc triangulation_wrapper.cc mapping_wrapper.cc + manifold_wrapper.cc ) FOREACH(_build ${DEAL_II_BUILD_TYPES}) diff --git a/contrib/python-bindings/source/export_manifold.cc b/contrib/python-bindings/source/export_manifold.cc new file mode 100644 index 0000000000..e752153655 --- /dev/null +++ b/contrib/python-bindings/source/export_manifold.cc @@ -0,0 +1,60 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2016 - 2017 by the deal.II authors +// +// This file is part of the deal.II library. +// +// The deal.II library is free software; you can use it, redistribute +// it, and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// The full text of the license can be found in the file LICENSE.md at +// the top level directory of deal.II. +// +// --------------------------------------------------------------------- + +#include + +#include + +DEAL_II_NAMESPACE_OPEN + +namespace python +{ + const char create_spherical_docstring[] = + " Create spherical manifold with a given center point \n"; + + + const char create_polar_docstring[] = + " Create polar manifold with a given center point \n"; + + + const char create_cylindrical_docstring[] = + " Create cylindrical manifold along a given axis \n" + " (0 - x, 1 - y, 2 - z) \n"; + + + + void + export_manifold() + { + boost::python::class_( + "ManifoldWrapper", + boost::python::init( + boost::python::args("dim", "spacedim"))) + .def("create_spherical", + &ManifoldWrapper::create_spherical, + create_spherical_docstring, + boost::python::args("self", "center")) + .def("create_polar", + &ManifoldWrapper::create_polar, + create_polar_docstring, + boost::python::args("self", "center")) + .def("create_cylindrical", + &ManifoldWrapper::create_cylindrical, + create_cylindrical_docstring, + boost::python::args("self", "axis", "tolerance")); + } +} // namespace python + +DEAL_II_NAMESPACE_CLOSE diff --git a/contrib/python-bindings/source/export_triangulation.cc b/contrib/python-bindings/source/export_triangulation.cc index ed38b6f58f..f1bab25860 100644 --- a/contrib/python-bindings/source/export_triangulation.cc +++ b/contrib/python-bindings/source/export_triangulation.cc @@ -333,6 +333,13 @@ namespace python + const char set_manifold_docstring[] = + "Assign a manifold object to a certain part of the triangulation. \n" + "The manifold_object is not copied and MUST persist until the \n" + "triangulation is destroyed. \n"; + + + void export_triangulation() { @@ -470,7 +477,11 @@ namespace python .def("load", &TriangulationWrapper::load, load_docstring, - boost::python::args("self", "filename")); + boost::python::args("self", "filename")) + .def("set_manifold", + &TriangulationWrapper::set_manifold, + set_manifold_docstring, + boost::python::args("self", "number", "manifold")); } } // namespace python diff --git a/contrib/python-bindings/source/manifold_wrapper.cc b/contrib/python-bindings/source/manifold_wrapper.cc new file mode 100644 index 0000000000..9c78c60cda --- /dev/null +++ b/contrib/python-bindings/source/manifold_wrapper.cc @@ -0,0 +1,220 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2016 - 2017 by the deal.II authors +// +// This file is part of the deal.II library. +// +// The deal.II library is free software; you can use it, redistribute +// it, and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// The full text of the license can be found in the file LICENSE.md at +// the top level directory of deal.II. +// +// --------------------------------------------------------------------- + +#include + +#include +#include + +DEAL_II_NAMESPACE_OPEN + +namespace python +{ + namespace internal + { + template + Manifold * + create_spherical_manifold(PointWrapper center) + { + const Point *point = + static_cast *>(center.get_point()); + return new SphericalManifold(*point); + } + + + + template + Manifold * + create_polar_manifold(PointWrapper center) + { + const Point *point = + static_cast *>(center.get_point()); + return new PolarManifold(*point); + } + + + + template + Manifold * + create_cylindrical_manifold(const int axis, const double tolerance) + { + return new CylindricalManifold(axis, tolerance); + } + + + + template + Manifold * + clone(void *manifold_ptr) + { + const Manifold *manifold = + static_cast *>(manifold_ptr); + + if (const SphericalManifold *d = + dynamic_cast *>(manifold)) + { + return new SphericalManifold(*d); + } + else if (const PolarManifold *d = + dynamic_cast *>(manifold)) + { + return new PolarManifold(*d); + } + else + ExcMessage("Unsupported manifold type in clone."); + + return nullptr; + } + } // namespace internal + + + + ManifoldWrapper::ManifoldWrapper(const int dim, const int spacedim) + : dim(dim) + , spacedim(spacedim) + { + AssertThrow(((dim == 2) && (spacedim == 2)) || + ((dim == 2) && (spacedim == 3)) || + ((dim == 3) && (spacedim == 3)), + ExcMessage("Wrong dim-spacedim combination.")); + } + + + + ManifoldWrapper::ManifoldWrapper(const ManifoldWrapper &other) + { + dim = other.dim; + spacedim = other.spacedim; + + AssertThrow(other.manifold_ptr != nullptr, + ExcMessage("Underlying manifold does not exist.")); + + if ((dim == 2) && (spacedim == 2)) + { + manifold_ptr = internal::clone<2, 2>(other.manifold_ptr); + } + else if ((dim == 2) && (spacedim == 3)) + { + manifold_ptr = internal::clone<2, 3>(other.manifold_ptr); + } + else if ((dim == 3) && (spacedim == 3)) + { + manifold_ptr = internal::clone<3, 3>(other.manifold_ptr); + } + else + AssertThrow(false, ExcMessage("Wrong dim-spacedim combination.")); + } + + + + ManifoldWrapper::~ManifoldWrapper() + { + if (dim != -1) + { + if ((dim == 2) && (spacedim == 2)) + { + // We cannot call delete on a void pointer so cast the void pointer + // back first. + Manifold<2, 2> *tmp = static_cast *>(manifold_ptr); + delete tmp; + } + else if ((dim == 2) && (spacedim == 3)) + { + Manifold<2, 3> *tmp = static_cast *>(manifold_ptr); + delete tmp; + } + else + { + Manifold<3, 3> *tmp = static_cast *>(manifold_ptr); + delete tmp; + } + + dim = -1; + spacedim = -1; + manifold_ptr = nullptr; + } + } + + + + void + ManifoldWrapper::create_spherical(const PointWrapper center) + { + if ((dim == 2) && (spacedim == 2)) + { + manifold_ptr = internal::create_spherical_manifold<2, 2>(center); + } + else if ((dim == 2) && (spacedim == 3)) + { + manifold_ptr = internal::create_spherical_manifold<2, 3>(center); + } + else if ((dim == 3) && (spacedim == 3)) + { + manifold_ptr = internal::create_spherical_manifold<3, 3>(center); + } + else + AssertThrow(false, ExcMessage("Wrong dim-spacedim combination.")); + } + + + + void + ManifoldWrapper::create_polar(const PointWrapper center) + { + if ((dim == 2) && (spacedim == 2)) + { + manifold_ptr = internal::create_polar_manifold<2, 2>(center); + } + else if ((dim == 2) && (spacedim == 3)) + { + manifold_ptr = internal::create_polar_manifold<2, 3>(center); + } + else if ((dim == 3) && (spacedim == 3)) + { + manifold_ptr = internal::create_polar_manifold<3, 3>(center); + } + else + AssertThrow(false, ExcMessage("Wrong dim-spacedim combination.")); + } + + + + void + ManifoldWrapper::create_cylindrical(const int axis, const double tolerance) + { + if ((dim == 2) && (spacedim == 3)) + { + manifold_ptr = + internal::create_cylindrical_manifold<2, 3>(axis, tolerance); + } + else if ((dim == 3) && (spacedim == 3)) + { + manifold_ptr = + internal::create_cylindrical_manifold<3, 3>(axis, tolerance); + } + else + AssertThrow(false, ExcMessage("Wrong dim-spacedim combination.")); + } + + + void * + ManifoldWrapper::get_manifold() const + { + return manifold_ptr; + } + +} // namespace python + +DEAL_II_NAMESPACE_CLOSE diff --git a/contrib/python-bindings/source/triangulation_wrapper.cc b/contrib/python-bindings/source/triangulation_wrapper.cc index 3e28e49104..45b1024ea8 100644 --- a/contrib/python-bindings/source/triangulation_wrapper.cc +++ b/contrib/python-bindings/source/triangulation_wrapper.cc @@ -1266,6 +1266,39 @@ namespace python } + + void + TriangulationWrapper::set_manifold(const int number, + ManifoldWrapper &manifold) + { + if ((dim == 2) && (spacedim == 2)) + { + Triangulation<2, 2> *tria = + static_cast *>(triangulation); + Manifold<2, 2> *m = + static_cast *>(manifold.get_manifold()); + tria->set_manifold(number, *m); + } + else if ((dim == 2) && (spacedim == 3)) + { + Triangulation<2, 3> *tria = + static_cast *>(triangulation); + Manifold<2, 3> *m = + static_cast *>(manifold.get_manifold()); + tria->set_manifold(number, *m); + } + else + { + Triangulation<3, 3> *tria = + static_cast *>(triangulation); + Manifold<3, 3> *m = + static_cast *>(manifold.get_manifold()); + tria->set_manifold(number, *m); + } + } + + + void TriangulationWrapper::setup(const std::string &dimension, const std::string &spacedimension) diff --git a/contrib/python-bindings/source/wrappers.cc b/contrib/python-bindings/source/wrappers.cc index 5d26719cd0..aa18628b45 100644 --- a/contrib/python-bindings/source/wrappers.cc +++ b/contrib/python-bindings/source/wrappers.cc @@ -33,6 +33,8 @@ namespace python export_triangulation(); void export_mapping(); + void + export_manifold(); } // namespace python DEAL_II_NAMESPACE_CLOSE @@ -66,6 +68,7 @@ BOOST_PYTHON_MODULE(Debug) dealii::python::export_point(); dealii::python::export_triangulation(); dealii::python::export_mapping(); + dealii::python::export_manifold(); } #else @@ -84,6 +87,7 @@ BOOST_PYTHON_MODULE(Release) dealii::python::export_point(); dealii::python::export_triangulation(); dealii::python::export_mapping(); + dealii::python::export_manifold(); } #endif diff --git a/doc/news/changes/minor/20191128Grayver b/doc/news/changes/minor/20191128Grayver new file mode 100644 index 0000000000..dfb0c89d0d --- /dev/null +++ b/doc/news/changes/minor/20191128Grayver @@ -0,0 +1,5 @@ +Added: New python wrappers for the Manifold class +with a possibility to assign manifold object to a +python triangulation object. +
+(Alexander Grayver, 2019/11/28) -- 2.39.5