From ef65654e35350e9a0741d94513c0ef1ce69e89e0 Mon Sep 17 00:00:00 2001 From: Yung-Yu Chen Date: Tue, 19 Jul 2016 06:57:07 +0800 Subject: [PATCH 1/3] Remove inactive code. --- libmarch/include/march/core/Buffer.hpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libmarch/include/march/core/Buffer.hpp b/libmarch/include/march/core/Buffer.hpp index 3516fb0a..817ab38a 100644 --- a/libmarch/include/march/core/Buffer.hpp +++ b/libmarch/include/march/core/Buffer.hpp @@ -54,13 +54,6 @@ class Buffer: public std::enable_shared_from_this { Buffer & operator=(const Buffer &) = delete; Buffer & operator=(Buffer &&) = delete; - /*Buffer & operator=(Buffer && other) { - m_data = other.m_data; - m_data = nullptr; - m_length = other.m_length; - m_own_data = other.m_own_data; - return *this; - }*/ explicit operator bool() const { return nullptr == m_data; } From 39f2f1341f569e1c30f59b00ffaeacac5e09fdb1 Mon Sep 17 00:00:00 2001 From: Yung-Yu Chen Date: Tue, 19 Jul 2016 06:57:08 +0800 Subject: [PATCH 2/3] Create march::mesh::BoundaryData and move boundary-condition information to the C++ class. --- libmarch/include/march/mesh/BoundaryData.hpp | 109 +++++++++++++++++++ libmarch/include/march/mesh/LookupTable.hpp | 18 ++- libmarch/include/march/mesh/mesh.hpp | 2 + libmarch/tests/CMakeLists.txt | 1 + libmarch/tests/mesh_BoundaryData.cpp | 42 +++++++ solvcon/boundcond.py | 48 ++++++-- solvcon/march.cpp | 70 +++++++++++- solvcon/tests/test_boundcond.py | 40 +++++++ 8 files changed, 315 insertions(+), 15 deletions(-) create mode 100644 libmarch/include/march/mesh/BoundaryData.hpp create mode 100644 libmarch/tests/mesh_BoundaryData.cpp diff --git a/libmarch/include/march/mesh/BoundaryData.hpp b/libmarch/include/march/mesh/BoundaryData.hpp new file mode 100644 index 00000000..68a2460b --- /dev/null +++ b/libmarch/include/march/mesh/BoundaryData.hpp @@ -0,0 +1,109 @@ +#pragma once + +/* + * Copyright (c) 2016, Yung-Yu Chen + * BSD 3-Clause License, see COPYING + */ + +#include +#include + +#include "march/core/core.hpp" + +#include "march/mesh/LookupTable.hpp" + +namespace march +{ + +namespace mesh +{ + +/** + * SOLVCON legacy C interface for boundary conditions. + */ +struct sc_bound_t { + index_type nbound, nvalue; + index_type *facn; + real_type *value; +}; /* end struct sc_bound_t */ + +class BoundaryData { + +public: + + static constexpr size_t BFREL = 3; + +private: + + /** + * First column is the face index in block. The second column is the face + * index in bndfcs. The third column is the face index of the related + * block (if exists). + */ + LookupTable m_facn; + + /** + * Values attached (specified) for each boundary face. Each row is a + * boundary face, and each column is a value. + */ + LookupTableCore m_values; + +public: + + BoundaryData() {} + + BoundaryData(index_type nvalue) + : m_values(0, 0, {0, nvalue}, type_to::id) + {} + + BoundaryData(const BoundaryData &) = delete; + + BoundaryData(BoundaryData && other) { + m_facn = std::move(other.m_facn); + m_values = std::move(other.m_values); + } + + BoundaryData & operator=(const BoundaryData &) = delete; + + BoundaryData & operator=(BoundaryData && other) { + m_facn = std::move(other.m_facn); + m_values = std::move(other.m_values); + return *this; + } + + ~BoundaryData() = default; + + index_type nvalue() const { return m_values.ncolumn(); } + + LookupTable const & facn() const { return m_facn; } + + LookupTable & facn() { return m_facn; } + + LookupTableCore const & values() const { return m_values; } + + LookupTableCore & values() { return m_values; } + + template< size_t NVALUE > + LookupTable< real_type, NVALUE > const & values() const { + assert(NVALUE == m_values.ncolumn()); + return *reinterpret_cast< LookupTable< real_type, NVALUE > const * >(&m_values); + } + + template< size_t NVALUE > + LookupTable< real_type, NVALUE > & values() { + assert(NVALUE == m_values.ncolumn()); + return *reinterpret_cast< LookupTable< real_type, NVALUE > * >(&m_values); + } + + bool good_shape() const { + return m_facn.nghost() == 0 && m_values.nghost() == 0 + && m_facn.nbody() == m_values.nbody(); + } + +}; /* end class BoundaryData */ + +} /* end namespace mesh */ + +} /* end namespace march */ + +// vim: set ff=unix fenc=utf8 nobomb et sw=4 ts=4: diff --git a/libmarch/include/march/mesh/LookupTable.hpp b/libmarch/include/march/mesh/LookupTable.hpp index e522b862..b2e4e8d3 100644 --- a/libmarch/include/march/mesh/LookupTable.hpp +++ b/libmarch/include/march/mesh/LookupTable.hpp @@ -31,7 +31,7 @@ class LookupTableCore { std::vector m_dims; index_type m_nghost = 0; index_type m_nbody = 0; - index_type m_ncolumn = 1; + index_type m_ncolumn = 0; index_type m_elsize = 1; ///< Element size in bytes. DataTypeId m_datatypeid = MH_INT8; @@ -70,7 +70,21 @@ class LookupTableCore { LookupTableCore & operator=(const LookupTableCore &) = delete; - LookupTableCore & operator=(LookupTableCore &&) = delete; + LookupTableCore & operator=(LookupTableCore && other) { + m_buffer = other.m_buffer; other.m_buffer.reset(); + m_dims.swap(other.m_dims); + m_nghost = other.m_nghost; + m_nbody = other.m_nbody; + m_ncolumn = other.m_ncolumn; + m_elsize = other.m_elsize; + // reset to initial state + other.m_nghost = 0; + other.m_nbody = 0; + other.m_ncolumn = 0; + other.m_elsize = 1; + m_datatypeid = other.m_datatypeid; + return *this; + } const std::vector & dims() const { return m_dims; } diff --git a/libmarch/include/march/mesh/mesh.hpp b/libmarch/include/march/mesh/mesh.hpp index a0c9fc49..eb954e7d 100644 --- a/libmarch/include/march/mesh/mesh.hpp +++ b/libmarch/include/march/mesh/mesh.hpp @@ -6,5 +6,7 @@ */ #include "march/mesh/Block.hpp" +#include "march/mesh/LookupTable.hpp" +#include "march/mesh/BoundaryData.hpp" // vim: set ff=unix fenc=utf8 nobomb et sw=4 ts=4: diff --git a/libmarch/tests/CMakeLists.txt b/libmarch/tests/CMakeLists.txt index fca9a2cf..a34d09d1 100644 --- a/libmarch/tests/CMakeLists.txt +++ b/libmarch/tests/CMakeLists.txt @@ -13,6 +13,7 @@ add_executable(test_libmarch core_types.cpp core_Buffer.cpp mesh_LookupTable.cpp + mesh_BoundaryData.cpp ) target_link_libraries(test_libmarch stdc++ pthread) diff --git a/libmarch/tests/mesh_BoundaryData.cpp b/libmarch/tests/mesh_BoundaryData.cpp new file mode 100644 index 00000000..707c3cda --- /dev/null +++ b/libmarch/tests/mesh_BoundaryData.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016, Yung-Yu Chen + * BSD 3-Clause License, see LICENSE.txt + */ + +#include + +#include + +#include "march/march.hpp" + +using namespace march; +using namespace march::mesh; + +TEST(BoundaryDataTest, DefaultConstruction) { + BoundaryData bnd; + EXPECT_EQ(bnd.facn().nbyte(), 0); + EXPECT_EQ(bnd.values().nbyte(), 0); + EXPECT_EQ(bnd.nvalue(), 0); +} + +TEST(BoundaryDataTest, UsefulConstruction) { + BoundaryData bnd(5); + EXPECT_EQ((bnd.values<5>().nelem()), 0); + bnd.values<5>() = LookupTable(0, 10); + EXPECT_EQ((bnd.values<5>().nelem()), 50); +} + +TEST(BoundaryDataTest, InVector) { + std::vector bvec; + bvec.push_back(BoundaryData(5)); + EXPECT_EQ((bvec[0].values<5>().nelem()), 0); + EXPECT_TRUE(bvec[0].good_shape()); + bvec[0].values<5>() = LookupTable(0, 10); + EXPECT_EQ((bvec[0].values<5>().nelem()), 50); + EXPECT_FALSE(bvec[0].good_shape()); +} + +TEST(BoundaryDataTest, SetValue) { +} + +// vim: set ff=unix fenc=utf8 nobomb et sw=4 ts=4: diff --git a/solvcon/boundcond.py b/solvcon/boundcond.py index 23f27ca0..cddd37ae 100644 --- a/solvcon/boundcond.py +++ b/solvcon/boundcond.py @@ -45,6 +45,7 @@ from . import dependency from .gendata import TypeNameRegistry, TypeWithBinder dependency.import_module_may_fail('.mesh') +dependency.import_module_may_fail('.march') class Glue(object): """ @@ -185,11 +186,18 @@ class BCMeta(TypeWithBinder): """ Meta class for boundary condition class. """ + def __new__(cls, name, bases, namespace): newcls = super(BCMeta, cls).__new__(cls, name, bases, namespace) bctregy.register(newcls) return newcls + @property + def BFREL(self): + """Boundary face relation number.""" + return march.BoundaryData.BFREL + + # Base/abstract BC type. class BC(with_metaclass(BCMeta)): """ @@ -199,9 +207,6 @@ class BC(with_metaclass(BCMeta)): FIXME: provide doctests as examples. """ - #: Boundary face relation number. - BFREL = 3 - #: Holding names as pointers. Used for binder. _pointers_ = [] @@ -247,14 +252,6 @@ def __init__(self, bc=None, fpdtype=None): #: Associated :py:class:`Glue` object gluing two collocated #: :py:class:`BC` objects. self.glue = None - #: An :py:class:`numpy.ndarray` as a list of faces. First column - #: is the face index in block. The second column is the face index - #: in bndfcs. The third column is the face index of the related - #: block (if exists). - self.facn = empty((0,self.BFREL), dtype='int32') - #: An :py:class:`numpy.ndarray` for attached (specified) value for - #: each boundary face. - self.value = empty((0,self.nvalue), dtype=self.fpdtype) else: bc.cloneTo(self) super(BC, self).__init__() @@ -275,6 +272,35 @@ def nvalue(self): """ return len(self.vnames) + @property + def _data(self): + if not hasattr(self, "_data_store"): + self._data_store = march.BoundaryData(self.nvalue) + return self._data_store + + @property + def facn(self): + """ + An :py:class:`numpy.ndarray` as a list of faces. First column is the + face index in block. The second column is the face index in bndfcs. + The third column is the face index of the related block (if exists). + """ + return self._data.facn + @facn.setter + def facn(self, arr): + self._data.facn = arr + + @property + def value(self): + """ + An :py:class:`numpy.ndarray` for attached (specified) value for each + boundary face. + """ + return self._data.values + @value.setter + def value(self, arr): + self._data.values = arr + def __len__(self): """ Return the first shape element of :py:class:`facn`. diff --git a/solvcon/march.cpp b/solvcon/march.cpp index 3b8fc980..8c9f1f81 100644 --- a/solvcon/march.cpp +++ b/solvcon/march.cpp @@ -87,8 +87,7 @@ class make_array { py::object buffer = py::cast(tbl.buffer()); py::array ret; - buffer.inc_ref(); - if (PyArray_SetBaseObject((PyArrayObject *)tmp.ptr(), buffer.ptr()) == 0) { + if (PyArray_SetBaseObject((PyArrayObject *)tmp.ptr(), buffer.inc_ref().ptr()) == 0) { ret = tmp; } return ret; @@ -200,6 +199,73 @@ PYBIND11_PLUGIN(march) { "Body-part array without setter.") ; + py::class_< BoundaryData >(mod, "BoundaryData", "Data of a boundary condition.") + .def("__init__", [](BoundaryData *bnd) { new (bnd) BoundaryData(); }) + .def("__init__", [](BoundaryData *bnd, index_type nvalue) { new (bnd) BoundaryData(nvalue); }) + .def_property_readonly_static("BFREL", [](py::object /* self */) { return BoundaryData::BFREL; }) + .def_property( + "facn", + [](BoundaryData & bnd) { + if (0 == bnd.facn().nbyte()) { + npy_intp shape[2] = {0, BoundaryData::BFREL}; + return py::array( + PyArray_NewFromDescr( + &PyArray_Type, PyArray_DescrFromType(bnd.facn().datatypeid()), 2 /* nd */, + shape, nullptr /* strides */, nullptr /* data */, 0 /* flags */, nullptr), + false); + } else { + return make_array::body_from(bnd.facn()); + } + }, + [](BoundaryData & bnd, py::array src) { + if (PyArray_NDIM((PyArrayObject *)src.ptr()) != 2) { + throw py::index_error("BoundaryData.facn input array dimension isn't 2"); + } + if (PyArray_DIMS((PyArrayObject *)src.ptr())[1] != BoundaryData::BFREL) { + throw py::index_error("BoundaryData.facn second axis mismatch"); + } + index_type nface = PyArray_DIMS((PyArrayObject *)src.ptr())[0]; + if (nface != bnd.facn().nbody()) { + bnd.facn() = std::remove_reference::type(0, nface); + } + if (0 != bnd.facn().nbyte()) { + PyArray_CopyInto((PyArrayObject *) make_array::body_from(bnd.facn()).ptr(), (PyArrayObject *) src.ptr()); + } + }, + "List of faces." + ) + .def_property( + "values", + [](BoundaryData & bnd) { + if (0 == bnd.values().nbyte()) { + npy_intp shape[2] = {0, bnd.nvalue()}; + return py::array( + PyArray_NewFromDescr( + &PyArray_Type, PyArray_DescrFromType(bnd.values().datatypeid()), 2 /* nd */, + shape, nullptr /* strides */, nullptr /* data */, 0 /* flags */, nullptr), + false); + } else { + return make_array::body_from(bnd.values()); + } + }, + [](BoundaryData & bnd, py::array src) { + if (PyArray_NDIM((PyArrayObject *)src.ptr()) != 2) { + throw py::index_error("BoundaryData.values input array dimension isn't 2"); + } + index_type nface = PyArray_DIMS((PyArrayObject *)src.ptr())[0]; + index_type nvalue = PyArray_DIMS((PyArrayObject *)src.ptr())[1]; + if (nface != bnd.values().nbody() || nvalue != bnd.values().ncolumn()) { + bnd.values() = std::remove_reference::type(0, nface, {nface, nvalue}, type_to::id); + } + if (0 != bnd.values().nbyte()) { + PyArray_CopyInto((PyArrayObject *) make_array::body_from(bnd.values()).ptr(), (PyArrayObject *) src.ptr()); + } + }, + "Attached (specified) value for each boundary face." + ) + .def("good_shape", &BoundaryData::good_shape) + ; + return mod.ptr(); } diff --git a/solvcon/tests/test_boundcond.py b/solvcon/tests/test_boundcond.py index 05be9383..f6330762 100644 --- a/solvcon/tests/test_boundcond.py +++ b/solvcon/tests/test_boundcond.py @@ -6,6 +6,10 @@ import os from unittest import TestCase + +import numpy as np + +from .. import py3kcompat from ..testing import loadfile from ..io import gambit @@ -16,6 +20,10 @@ class TestBc(TestCase): #__test__ = False # temporarily turned off. blk = gambit.GambitNeutral(loadfile('sample.neu')).toblock() + def test_BFREL(self): + from ..boundcond import BC + self.assertEqual(3, BC.BFREL) + def test_print_vanilla(self): from ..boundcond import BC obj = BC() @@ -27,6 +35,38 @@ def test_print_sern(self): obj.sern = 5 self.assertEqual(str(obj), '[BC#5 "None": 0 faces with 0 values]') + def test_facn(self): + from ..boundcond import BC + obj = BC() + self.assertEqual((0, BC.BFREL), obj.facn.shape) + self.assertEqual(0, obj.facn.size) + + def test_facn_set(self): + from ..boundcond import BC + obj = BC() + # fake input only to fit the shape + obj.facn = np.array([[10, 0, -1], [23, 1, -1]], dtype='int32') + self.assertEqual((2, BC.BFREL), obj.facn.shape) + self.assertEqual([10, 0, -1, 23, 1, -1], obj.facn.ravel().tolist()) + # The second dimension must be BC.BFREL + with py3kcompat.assertRaisesRegex( + self, IndexError, "BoundaryData.facn second axis mismatch" + ): + obj.facn = np.array([[10, 0], [23, 1]], dtype='int32') + + def test_value(self): + from ..boundcond import BC + obj = BC() + self.assertEqual((0, 0), obj.value.shape) + self.assertEqual(0, obj.value.size) + + def test_value_set(self): + from ..boundcond import BC + obj = BC() + obj.value = np.array([[1, 2], [3, 4]], dtype='float64') + self.assertEqual((2, 2), obj.value.shape) + self.assertEqual([1, 2, 3, 4], obj.value.ravel().tolist()) + def test_certain_bct(self): from ..boundcond import bctregy # check that the existance of the most generic abstract BC types. From 1ab3ca9c7fca45062441eaa140cd21e1dffccff7 Mon Sep 17 00:00:00 2001 From: Yung-Yu Chen Date: Tue, 19 Jul 2016 06:57:09 +0800 Subject: [PATCH 3/3] Improve py::array wrapper for LookupTableCore. Attach frequently used numpy API. --- solvcon/march.cpp | 141 +++++++++++++++++++++++----------------------- 1 file changed, 69 insertions(+), 72 deletions(-) diff --git a/solvcon/march.cpp b/solvcon/march.cpp index 8c9f1f81..4d00d78e 100644 --- a/solvcon/march.cpp +++ b/solvcon/march.cpp @@ -17,75 +17,81 @@ using namespace march; using namespace march::mesh; /** - * Helper class to convert march::mesh::LookupTableCore to pybind11::array. + * Decorator of LookupTableCore to convert march::mesh::LookupTableCore to + * pybind11::array and help array operations. */ -class make_array { +class Table { -public: +private: enum array_flavor { FULL = 0, GHOST = 1, BODY = 2 }; - make_array(array_flavor flavor) : m_flavor(flavor) {} +public: - make_array() = delete; - make_array(const make_array &) = delete; - make_array(make_array &&) = delete; - make_array & operator=(const make_array &) = delete; - make_array & operator=(make_array &&) = delete; + Table(LookupTableCore & table) : m_table(table) {} - static py::array full_from(LookupTableCore & tbl) { - static make_array worker(FULL); - return worker.from(tbl); - } + Table(const Table &) = delete; - static py::array ghost_from(LookupTableCore & tbl) { - static make_array worker(GHOST); - return worker.from(tbl); - } + Table(Table &&) = delete; + + Table & operator=(const Table &) = delete; + + Table & operator=(Table &&) = delete; + + py::array full() { return from(FULL); } + + py::array ghost() { return from(GHOST); } - static py::array body_from(LookupTableCore & tbl) { - static make_array worker(BODY); - return worker.from(tbl); + py::array body() { return from(BODY); } + + static int NDIM(py::array arr) { return PyArray_NDIM((PyArrayObject *) arr.ptr()); } + + static npy_intp * DIMS(py::array arr) { return PyArray_DIMS((PyArrayObject *) arr.ptr()); } + + static char * BYTES(py::array arr) { return PyArray_BYTES((PyArrayObject *) arr.ptr()); } + + static int CopyInto(py::array dst, py::array src) { + return PyArray_CopyInto((PyArrayObject *) dst.ptr(), (PyArrayObject *) src.ptr()); } private: /** - * \param tbl The input LookupTableCore. - * \return ndarray object as a view to the input table. + * \param flavor The requested type of array. + * \return ndarray object as a view to the input table. */ - py::array from(LookupTableCore & tbl) const { - npy_intp shape[tbl.ndim()]; - std::copy(tbl.dims().begin(), tbl.dims().end(), shape); + py::array from(array_flavor flavor) { + npy_intp shape[m_table.ndim()]; + std::copy(m_table.dims().begin(), m_table.dims().end(), shape); - npy_intp strides[tbl.ndim()]; - strides[tbl.ndim()-1] = tbl.elsize(); - for (ssize_t it = tbl.ndim()-2; it >= 0; --it) { + npy_intp strides[m_table.ndim()]; + strides[m_table.ndim()-1] = m_table.elsize(); + for (ssize_t it = m_table.ndim()-2; it >= 0; --it) { strides[it] = shape[it+1] * strides[it+1]; } void * data = nullptr; - if (FULL == m_flavor) { - data = tbl.data(); - } else if (GHOST == m_flavor) { - shape[0] = tbl.nghost(); + if (FULL == flavor) { + data = m_table.data(); + } else if (GHOST == flavor) { + shape[0] = m_table.nghost(); strides[0] = -strides[0]; - data = tbl.nghost() > 0 ? tbl.row(-1) : tbl.row(0); - } else if (BODY == m_flavor) { - shape[0] = tbl.nbody(); - data = tbl.row(0); + data = m_table.nghost() > 0 ? m_table.row(-1) : m_table.row(0); + } else if (BODY == flavor) { + shape[0] = m_table.nbody(); + data = m_table.row(0); } else { py::pybind11_fail("NumPy: invalid array type"); } py::object tmp( PyArray_NewFromDescr( - &PyArray_Type, PyArray_DescrFromType(tbl.datatypeid()), tbl.ndim(), + &PyArray_Type, PyArray_DescrFromType(m_table.datatypeid()), m_table.ndim(), shape, strides, data, NPY_ARRAY_WRITEABLE, nullptr), false); if (!tmp) { py::pybind11_fail("NumPy: unable to create array view"); } - py::object buffer = py::cast(tbl.buffer()); + py::object buffer = py::cast(m_table.buffer()); py::array ret; if (PyArray_SetBaseObject((PyArrayObject *)tmp.ptr(), buffer.inc_ref().ptr()) == 0) { ret = tmp; @@ -93,9 +99,9 @@ class make_array { return ret; } - array_flavor m_flavor; + LookupTableCore & m_table; -}; /* end class make_array */ +}; PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr); @@ -143,10 +149,10 @@ PYBIND11_PLUGIN(march) { } }) .def("__getattr__", [](LookupTableCore & tbl, py::object key) { - return py::object(make_array::full_from(tbl).attr(key)); + return py::object(Table(tbl).full().attr(key)); }) .def_property_readonly("_nda", [](LookupTableCore & tbl) { - return make_array::full_from(tbl); + return Table(tbl).full(); }) .def_property_readonly("nghost", &LookupTableCore::nghost) .def_property_readonly("nbody", &LookupTableCore::nbody) @@ -156,27 +162,21 @@ PYBIND11_PLUGIN(march) { "Element offset from the head of the ndarray to where the body starts.") .def_property_readonly( "_ghostaddr", - [](LookupTableCore & tbl) { - return (Py_intptr_t) PyArray_BYTES((PyArrayObject *) make_array::full_from(tbl).ptr()); - }) + [](LookupTableCore & tbl) { return (Py_intptr_t) Table::BYTES(Table(tbl).full()); }) .def_property_readonly( "_bodyaddr", - [](LookupTableCore & tbl) { - return (Py_intptr_t) PyArray_BYTES((PyArrayObject *) make_array::body_from(tbl).ptr()); - }) + [](LookupTableCore & tbl) { return (Py_intptr_t) Table::BYTES(Table(tbl).body()); }) .def_property( "F", - [](LookupTableCore & tbl) { return make_array::full_from(tbl); }, - [](LookupTableCore & tbl, py::array src) { - PyArray_CopyInto((PyArrayObject *) make_array::full_from(tbl).ptr(), (PyArrayObject *) src.ptr()); - }, + [](LookupTableCore & tbl) { return Table(tbl).full(); }, + [](LookupTableCore & tbl, py::array src) { Table::CopyInto(Table(tbl).full(), src); }, "Full array.") .def_property( "G", - [](LookupTableCore & tbl) { return make_array::ghost_from(tbl); }, + [](LookupTableCore & tbl) { return Table(tbl).ghost(); }, [](LookupTableCore & tbl, py::array src) { if (tbl.nghost()) { - PyArray_CopyInto((PyArrayObject *) make_array::ghost_from(tbl).ptr(), (PyArrayObject *) src.ptr()); + Table::CopyInto(Table(tbl).ghost(), src); } else { throw py::index_error("ghost is zero"); } @@ -184,24 +184,21 @@ PYBIND11_PLUGIN(march) { "Ghost-part array.") .def_property_readonly( "_ghostpart", - [](LookupTableCore & tbl) { return make_array::ghost_from(tbl); }, + [](LookupTableCore & tbl) { return Table(tbl).ghost(); }, "Ghost-part array without setter.") .def_property( "B", - [](LookupTableCore & tbl) { return make_array::body_from(tbl); }, - [](LookupTableCore & tbl, py::array src) { - PyArray_CopyInto((PyArrayObject *) make_array::body_from(tbl).ptr(), (PyArrayObject *) src.ptr()); - }, + [](LookupTableCore & tbl) { return Table(tbl).body(); }, + [](LookupTableCore & tbl, py::array src) { Table::CopyInto(Table(tbl).body(), src); }, "Body-part array.") .def_property_readonly( "_bodypart", - [](LookupTableCore & tbl) { return make_array::body_from(tbl); }, + [](LookupTableCore & tbl) { return Table(tbl).body(); }, "Body-part array without setter.") ; py::class_< BoundaryData >(mod, "BoundaryData", "Data of a boundary condition.") - .def("__init__", [](BoundaryData *bnd) { new (bnd) BoundaryData(); }) - .def("__init__", [](BoundaryData *bnd, index_type nvalue) { new (bnd) BoundaryData(nvalue); }) + .def(py::init()) .def_property_readonly_static("BFREL", [](py::object /* self */) { return BoundaryData::BFREL; }) .def_property( "facn", @@ -214,22 +211,22 @@ PYBIND11_PLUGIN(march) { shape, nullptr /* strides */, nullptr /* data */, 0 /* flags */, nullptr), false); } else { - return make_array::body_from(bnd.facn()); + return Table(bnd.facn()).body(); } }, [](BoundaryData & bnd, py::array src) { - if (PyArray_NDIM((PyArrayObject *)src.ptr()) != 2) { + if (Table::NDIM(src) != 2) { throw py::index_error("BoundaryData.facn input array dimension isn't 2"); } - if (PyArray_DIMS((PyArrayObject *)src.ptr())[1] != BoundaryData::BFREL) { + if (Table::DIMS(src)[1] != BoundaryData::BFREL) { throw py::index_error("BoundaryData.facn second axis mismatch"); } - index_type nface = PyArray_DIMS((PyArrayObject *)src.ptr())[0]; + index_type nface = Table::DIMS(src)[0]; if (nface != bnd.facn().nbody()) { bnd.facn() = std::remove_reference::type(0, nface); } if (0 != bnd.facn().nbyte()) { - PyArray_CopyInto((PyArrayObject *) make_array::body_from(bnd.facn()).ptr(), (PyArrayObject *) src.ptr()); + Table::CopyInto(Table(bnd.facn()).body(), src); } }, "List of faces." @@ -245,20 +242,20 @@ PYBIND11_PLUGIN(march) { shape, nullptr /* strides */, nullptr /* data */, 0 /* flags */, nullptr), false); } else { - return make_array::body_from(bnd.values()); + return Table(bnd.values()).body(); } }, [](BoundaryData & bnd, py::array src) { - if (PyArray_NDIM((PyArrayObject *)src.ptr()) != 2) { + if (Table::NDIM(src) != 2) { throw py::index_error("BoundaryData.values input array dimension isn't 2"); } - index_type nface = PyArray_DIMS((PyArrayObject *)src.ptr())[0]; - index_type nvalue = PyArray_DIMS((PyArrayObject *)src.ptr())[1]; + index_type nface = Table::DIMS(src)[0]; + index_type nvalue = Table::DIMS(src)[1]; if (nface != bnd.values().nbody() || nvalue != bnd.values().ncolumn()) { bnd.values() = std::remove_reference::type(0, nface, {nface, nvalue}, type_to::id); } if (0 != bnd.values().nbyte()) { - PyArray_CopyInto((PyArrayObject *) make_array::body_from(bnd.values()).ptr(), (PyArrayObject *) src.ptr()); + Table::CopyInto(Table(bnd.values()).body(), src); } }, "Attached (specified) value for each boundary face."