From aeaefefea1ff1e8b647455b762c8adacac1c071d Mon Sep 17 00:00:00 2001 From: markus holzer Date: Sat, 19 Dec 2020 09:43:48 +0100 Subject: [PATCH 01/10] Added Block Data adder to BlockForest --- src/python_coupling/export/BlockForestExport.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/python_coupling/export/BlockForestExport.cpp b/src/python_coupling/export/BlockForestExport.cpp index 7d2c9d764..9250eccfe 100644 --- a/src/python_coupling/export/BlockForestExport.cpp +++ b/src/python_coupling/export/BlockForestExport.cpp @@ -257,6 +257,19 @@ bool p_blockExistsRemotely1(StructuredBlockForest& s, const std::array( std::bind( &blockDataCreationHelper, std::placeholders::_1, functionPtr ) ); + return res; +} + bool SbF_atDomainXMinBorder(StructuredBlockForest& s, const IBlock* b) { return s.atDomainXMinBorder(*b); } bool SbF_atDomainXMaxBorder(StructuredBlockForest& s, const IBlock* b) { return s.atDomainXMaxBorder(*b); } bool SbF_atDomainYMinBorder(StructuredBlockForest& s, const IBlock* b) { return s.atDomainYMinBorder(*b); } @@ -278,6 +291,7 @@ void exportBlockForest(py::module_& m) py::class_< StructuredBlockForest, std::shared_ptr< StructuredBlockForest > >(m, "StructuredBlockForest") .def("getNumberOfLevels", &StructuredBlockForest::getNumberOfLevels) .def_property_readonly("getDomain", &StructuredBlockForest::getDomain) + .def( "addBlockData", &StructuredBlockForest_addBlockData) .def("mapToPeriodicDomain", &SbF_mapToPeriodicDomain1) .def("mapToPeriodicDomain", &SbF_mapToPeriodicDomain2) .def("mapToPeriodicDomain", &SbF_mapToPeriodicDomain3) -- GitLab From fafb5443943ed13b80df3d4a082ae69248ac4de3 Mon Sep 17 00:00:00 2001 From: markus holzer Date: Sat, 19 Dec 2020 10:07:04 +0100 Subject: [PATCH 02/10] Fixed comparison warning --- src/python_coupling/export/BasicExport.cpp | 8 -------- src/python_coupling/export/BlockForestExport.cpp | 9 +++++++++ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/python_coupling/export/BasicExport.cpp b/src/python_coupling/export/BasicExport.cpp index 279e304e5..c4fad8eb6 100644 --- a/src/python_coupling/export/BasicExport.cpp +++ b/src/python_coupling/export/BasicExport.cpp @@ -55,14 +55,6 @@ # include -// specialize operator== since == is deprecated in pybind11 -template<> -bool walberla::domain_decomposition::internal::BlockData::Data< pybind11::object >::operator==( - const BlockData::DataBase& rhs) const -{ - const Data< pybind11::object >* rhsData = dynamic_cast< const Data< pybind11::object >* >(&rhs); - return (rhsData == &rhs) && (data_->is(*(rhsData->data_))); -} namespace py = pybind11; namespace walberla { diff --git a/src/python_coupling/export/BlockForestExport.cpp b/src/python_coupling/export/BlockForestExport.cpp index 9250eccfe..e4aae6226 100644 --- a/src/python_coupling/export/BlockForestExport.cpp +++ b/src/python_coupling/export/BlockForestExport.cpp @@ -42,6 +42,15 @@ # include "BlockForestExport.h" # include "python_coupling/helper/OwningIterator.h" +// specialize operator== since == is deprecated in pybind11 +template<> +bool walberla::domain_decomposition::internal::BlockData::Data< pybind11::object >::operator==( + const BlockData::DataBase& rhs) const +{ + const Data< pybind11::object >* rhsData = dynamic_cast< const Data< pybind11::object >* >(&rhs); + return (rhsData == &rhs) && (data_->is(*(rhsData->data_))); +} + namespace walberla { namespace blockforest -- GitLab From 395b5a0be724178ed4cd8d13f2844b6800a10efe Mon Sep 17 00:00:00 2001 From: markus holzer Date: Sat, 19 Dec 2020 10:13:25 +0100 Subject: [PATCH 03/10] Updated documentation --- python/waLBerla_docs/modules/core.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/python/waLBerla_docs/modules/core.rst b/python/waLBerla_docs/modules/core.rst index c1253ba29..ee8d985a3 100644 --- a/python/waLBerla_docs/modules/core.rst +++ b/python/waLBerla_docs/modules/core.rst @@ -198,6 +198,10 @@ Block Structure .. py:method:: containsGlobalBlockInformation( ) .. py:method:: blocksOverlappedByAABB( point, aabb ) .. py:method:: blocksContainedWithinAABB( point, aabb ) + + .. py:method:: addBlockData( name, blockdata) + + Adds custom data to the blockforest. This can be a Python Class for example which is then callable on all blocks .. py:method:: blockExists( point ) .. py:method:: blockExistsLocally( point ) -- GitLab From 9742c664d52ef2be6cf6203d510ea3c9b07369d7 Mon Sep 17 00:00:00 2001 From: markus holzer Date: Sat, 19 Dec 2020 11:50:52 +0100 Subject: [PATCH 04/10] test segfault origin --- python/waLBerla_tests/test_field.py | 58 ++++++++++++++--------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/python/waLBerla_tests/test_field.py b/python/waLBerla_tests/test_field.py index 3ab25c418..d18b8e5ab 100644 --- a/python/waLBerla_tests/test_field.py +++ b/python/waLBerla_tests/test_field.py @@ -47,35 +47,35 @@ class FieldModuleTest(unittest.TestCase): view4 = field.toArray(f, with_ghost_layers=[2, False, True]) self.assertEqual(view4[:, :, :, 0].shape, tuple([size[0] + 2 * 2, size[1] + 2 * 0, size[2] + 2 * gl])) - def test_gather(self): - blocks = createUniformBlockGrid(blocks=(10, 4, 3), cellsPerBlock=(2, 2, 2), - periodic=(True, True, True), oneBlockPerProcess=False) - wlb.field.addToStorage(blocks, "test", dtype=np.int, fSize=3) - - for block in blocks: - offset_in_global_domain = blocks.transformLocalToGlobal(block, wlb.Cell(0, 0, 0))[:] - f = wlb.field.toArray(block["test"]) - s = f.shape - for i in range(0, s[0]): - for j in range(0, s[1]): - for k in range(0, s[2]): - f[i, j, k, 0] = i + offset_in_global_domain[0] - f[i, j, k, 1] = j + offset_in_global_domain[1] - f[i, j, k, 2] = k + offset_in_global_domain[2] - - tp = tuple([slice(5, 15), slice(None, None), 0.5]) - f = wlb.field.gather(blocks, "test", tp) - - nparray = wlb.field.toArray(f) - self.assertEqual(nparray.shape, (11, 8, 1, 3)) - - s = nparray.shape - for i in range(0, s[0]): - for j in range(0, s[1]): - for k in range(0, s[2]): - assert(nparray[i, j, k, 0] == i + 5) - assert(nparray[i, j, k, 1] == j) - assert(nparray[i, j, k, 2] == 2) + # def test_gather(self): + # blocks = createUniformBlockGrid(blocks=(10, 4, 3), cellsPerBlock=(2, 2, 2), + # periodic=(True, True, True), oneBlockPerProcess=False) + # wlb.field.addToStorage(blocks, "test", dtype=np.int, fSize=3) + # + # for block in blocks: + # offset_in_global_domain = blocks.transformLocalToGlobal(block, wlb.Cell(0, 0, 0))[:] + # f = wlb.field.toArray(block["test"]) + # s = f.shape + # for i in range(0, s[0]): + # for j in range(0, s[1]): + # for k in range(0, s[2]): + # f[i, j, k, 0] = i + offset_in_global_domain[0] + # f[i, j, k, 1] = j + offset_in_global_domain[1] + # f[i, j, k, 2] = k + offset_in_global_domain[2] + # + # tp = tuple([slice(5, 15), slice(None, None), 0.5]) + # f = wlb.field.gather(blocks, "test", tp) + # + # nparray = wlb.field.toArray(f) + # self.assertEqual(nparray.shape, (11, 8, 1, 3)) + # + # s = nparray.shape + # for i in range(0, s[0]): + # for j in range(0, s[1]): + # for k in range(0, s[2]): + # assert(nparray[i, j, k, 0] == i + 5) + # assert(nparray[i, j, k, 1] == j) + # assert(nparray[i, j, k, 2] == 2) if __name__ == '__main__': -- GitLab From 0bef9163febb7b49c7b5ba031aa2a659bbb46017 Mon Sep 17 00:00:00 2001 From: markus holzer Date: Sun, 20 Dec 2020 08:08:02 +0100 Subject: [PATCH 05/10] Activated gather test case again --- python/waLBerla_tests/test_field.py | 58 ++++++++++++++--------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/python/waLBerla_tests/test_field.py b/python/waLBerla_tests/test_field.py index d18b8e5ab..3ab25c418 100644 --- a/python/waLBerla_tests/test_field.py +++ b/python/waLBerla_tests/test_field.py @@ -47,35 +47,35 @@ class FieldModuleTest(unittest.TestCase): view4 = field.toArray(f, with_ghost_layers=[2, False, True]) self.assertEqual(view4[:, :, :, 0].shape, tuple([size[0] + 2 * 2, size[1] + 2 * 0, size[2] + 2 * gl])) - # def test_gather(self): - # blocks = createUniformBlockGrid(blocks=(10, 4, 3), cellsPerBlock=(2, 2, 2), - # periodic=(True, True, True), oneBlockPerProcess=False) - # wlb.field.addToStorage(blocks, "test", dtype=np.int, fSize=3) - # - # for block in blocks: - # offset_in_global_domain = blocks.transformLocalToGlobal(block, wlb.Cell(0, 0, 0))[:] - # f = wlb.field.toArray(block["test"]) - # s = f.shape - # for i in range(0, s[0]): - # for j in range(0, s[1]): - # for k in range(0, s[2]): - # f[i, j, k, 0] = i + offset_in_global_domain[0] - # f[i, j, k, 1] = j + offset_in_global_domain[1] - # f[i, j, k, 2] = k + offset_in_global_domain[2] - # - # tp = tuple([slice(5, 15), slice(None, None), 0.5]) - # f = wlb.field.gather(blocks, "test", tp) - # - # nparray = wlb.field.toArray(f) - # self.assertEqual(nparray.shape, (11, 8, 1, 3)) - # - # s = nparray.shape - # for i in range(0, s[0]): - # for j in range(0, s[1]): - # for k in range(0, s[2]): - # assert(nparray[i, j, k, 0] == i + 5) - # assert(nparray[i, j, k, 1] == j) - # assert(nparray[i, j, k, 2] == 2) + def test_gather(self): + blocks = createUniformBlockGrid(blocks=(10, 4, 3), cellsPerBlock=(2, 2, 2), + periodic=(True, True, True), oneBlockPerProcess=False) + wlb.field.addToStorage(blocks, "test", dtype=np.int, fSize=3) + + for block in blocks: + offset_in_global_domain = blocks.transformLocalToGlobal(block, wlb.Cell(0, 0, 0))[:] + f = wlb.field.toArray(block["test"]) + s = f.shape + for i in range(0, s[0]): + for j in range(0, s[1]): + for k in range(0, s[2]): + f[i, j, k, 0] = i + offset_in_global_domain[0] + f[i, j, k, 1] = j + offset_in_global_domain[1] + f[i, j, k, 2] = k + offset_in_global_domain[2] + + tp = tuple([slice(5, 15), slice(None, None), 0.5]) + f = wlb.field.gather(blocks, "test", tp) + + nparray = wlb.field.toArray(f) + self.assertEqual(nparray.shape, (11, 8, 1, 3)) + + s = nparray.shape + for i in range(0, s[0]): + for j in range(0, s[1]): + for k in range(0, s[2]): + assert(nparray[i, j, k, 0] == i + 5) + assert(nparray[i, j, k, 1] == j) + assert(nparray[i, j, k, 2] == 2) if __name__ == '__main__': -- GitLab From 1bb7b1130cb3e4008afe6969d4ad8f22ecb1f116 Mon Sep 17 00:00:00 2001 From: markus holzer Date: Tue, 22 Dec 2020 06:52:06 +0100 Subject: [PATCH 06/10] Removed many field combinations --- apps/pythonmodule/PythonModule.cpp | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/apps/pythonmodule/PythonModule.cpp b/apps/pythonmodule/PythonModule.cpp index 419b1b377..a4c562748 100644 --- a/apps/pythonmodule/PythonModule.cpp +++ b/apps/pythonmodule/PythonModule.cpp @@ -40,34 +40,21 @@ using namespace walberla; Field,\ Field,\ Field,\ - Field,\ - Field,\ - Field,\ Field,\ Field,\ Field,\ Field,\ Field,\ - Field,\ - Field,\ Field,\ Field,\ Field,\ - Field,\ - Field,\ - Field,\ - Field + Field #define GPU_FIELD_TYPES \ - GPUField,\ - GPUField,\ + GPUField,\ GPUField,\ - GPUField,\ - GPUField,\ GPUField,\ GPUField,\ - GPUField,\ - GPUField,\ GPUField struct InitObject -- GitLab From 47319f99bbaf04f8f00f2a2ceb6568ae145adc17 Mon Sep 17 00:00:00 2001 From: markus holzer Date: Tue, 22 Dec 2020 07:47:17 +0100 Subject: [PATCH 07/10] Added Fields needed for pystencils and lbmpy --- apps/pythonmodule/PythonModule.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/pythonmodule/PythonModule.cpp b/apps/pythonmodule/PythonModule.cpp index a4c562748..b32f103dd 100644 --- a/apps/pythonmodule/PythonModule.cpp +++ b/apps/pythonmodule/PythonModule.cpp @@ -48,11 +48,14 @@ using namespace walberla; Field,\ Field,\ Field,\ - Field + Field,\ + Field,\ + Field #define GPU_FIELD_TYPES \ GPUField,\ GPUField,\ + GPUField,\ GPUField,\ GPUField,\ GPUField -- GitLab From e7c62d9dc635c319225fd0467d4dbf810aaee557 Mon Sep 17 00:00:00 2001 From: markus holzer Date: Tue, 22 Dec 2020 08:13:05 +0100 Subject: [PATCH 08/10] Fixed test_field --- python/waLBerla_tests/test_field.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/waLBerla_tests/test_field.py b/python/waLBerla_tests/test_field.py index 3ab25c418..04ab5afb4 100644 --- a/python/waLBerla_tests/test_field.py +++ b/python/waLBerla_tests/test_field.py @@ -18,14 +18,14 @@ class FieldModuleTest(unittest.TestCase): def testNumpyConversionWithoutGhostLayers(self): blocks = createUniformBlockGrid(blocks=(1, 1, 1), cellsPerBlock=(1, 2, 3), periodic=(True, False, False)) - field.addToStorage(blocks, 'f1', np.float64, fSize=4, ghostLayers=0, initValue=2.0) - field.addToStorage(blocks, 'f2', np.float64, fSize=5, ghostLayers=0, initValue=2.0) + field.addToStorage(blocks, 'f1', np.float64, fSize=2, ghostLayers=0, initValue=2.0) + field.addToStorage(blocks, 'f2', np.float64, fSize=3, ghostLayers=0, initValue=2.0) f1np = field.toArray(blocks[0]['f1']) f2np = field.toArray(blocks[0]['f2']) self.assertEqual(f1np[0, 0, 0, 0], 2.0) - self.assertEqual(f1np.shape, (1, 2, 3, 4)) - self.assertEqual(f2np.shape, (1, 2, 3, 5)) + self.assertEqual(f1np.shape, (1, 2, 3, 2)) + self.assertEqual(f2np.shape, (1, 2, 3, 3)) def testGhostLayerExtraction(self): size = (10, 5, 4) -- GitLab From ee4024328e299c2b9a20ef7034601f6b5ca6da2f Mon Sep 17 00:00:00 2001 From: markus holzer Date: Mon, 28 Dec 2020 09:04:46 +0100 Subject: [PATCH 09/10] Added stencil restricted packInfo Export --- .../export/FieldCommunicationExport.impl.h | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/src/python_coupling/export/FieldCommunicationExport.impl.h b/src/python_coupling/export/FieldCommunicationExport.impl.h index 0793b26a5..57289631d 100644 --- a/src/python_coupling/export/FieldCommunicationExport.impl.h +++ b/src/python_coupling/export/FieldCommunicationExport.impl.h @@ -51,6 +51,119 @@ namespace internal { namespace py = pybind11; +//=================================================================================================================== +// +// createStencilRestrictedPackInfo Export +// +//=================================================================================================================== + +template< typename FieldType > +typename std::enable_if::type +createStencilRestrictedPackInfoObject( BlockDataID bdId ) +{ + typedef GhostLayerField GlField_T; + using field::communication::StencilRestrictedPackInfo; + return py::cast( make_shared< StencilRestrictedPackInfo >( bdId) ); +} + +template< typename FieldType > +typename std::enable_if::type +createStencilRestrictedPackInfoObject( BlockDataID bdId ) +{ + typedef GhostLayerField GlField_T; + using field::communication::StencilRestrictedPackInfo; + return py::cast( make_shared< StencilRestrictedPackInfo >( bdId) ); +} + +template< typename FieldType > +typename std::enable_if::type +createStencilRestrictedPackInfoObject( BlockDataID bdId ) +{ + typedef GhostLayerField GlField_T; + using field::communication::StencilRestrictedPackInfo; + return py::cast( make_shared< StencilRestrictedPackInfo >( bdId) ); +} + +template< typename FieldType > +typename std::enable_if::type +createStencilRestrictedPackInfoObject( BlockDataID bdId ) +{ + typedef GhostLayerField GlField_T; + using field::communication::StencilRestrictedPackInfo; + return py::cast( make_shared< StencilRestrictedPackInfo >( bdId) ); +} + +template< typename FieldType > +typename std::enable_if::type +createStencilRestrictedPackInfoObject( BlockDataID bdId ) +{ + typedef GhostLayerField GlField_T; + using field::communication::StencilRestrictedPackInfo; + return py::cast( make_shared< StencilRestrictedPackInfo >( bdId) ); +} + +template< typename FieldType > +typename std::enable_if::type +createStencilRestrictedPackInfoObject( BlockDataID ) +{ + throw py::value_error("This works only for fields with fSize in 7, 9, 15, 19 or 27"); +} + +class StencilRestrictedPackInfoExporter +{ + public: + StencilRestrictedPackInfoExporter(const shared_ptr & blocks, BlockDataID fieldId) + : blocks_(blocks), fieldId_(fieldId) + {} + + template< typename FieldType> + void operator() ( python_coupling::NonCopyableWrap ) + { + typedef typename FieldType::value_type T; + const uint_t F_SIZE = FieldType::F_SIZE; + typedef GhostLayerField GlField_T; + IBlock * firstBlock = & ( * blocks_->begin() ); + if( firstBlock->isDataClassOrSubclassOf(fieldId_) ) + { + resultStencilRestrictedPackInfo_ = createStencilRestrictedPackInfoObject(fieldId_); + } + } + py::object getResultStencilRestrictedPackInfo() + { + return resultStencilRestrictedPackInfo_; + } + + private: + py::object resultStencilRestrictedPackInfo_; + shared_ptr< StructuredBlockStorage > blocks_; + BlockDataID fieldId_; +}; + +template +static py::object StencilRestrictedPackInfoWrapper(const shared_ptr & blocks, + const std::string & blockDataName ) +{ + BlockDataID fieldID = python_coupling::blockDataIDFromString( *blocks, blockDataName ); + + if ( blocks->begin() == blocks->end() ) { + // if no blocks are on this field an arbitrary PackInfo can be returned + return py::cast( make_shared< field::communication::StencilRestrictedPackInfo, stencil::D2Q9> >( fieldID ) ); + } + + StencilRestrictedPackInfoExporter exporter(blocks, fieldID); + python_coupling::for_each_noncopyable_type< FieldTypes... > ( std::ref(exporter) ); + if ( ! exporter.getResultStencilRestrictedPackInfo() ) { + throw py::value_error("Failed to create Stencil Restricted PackInfo"); + } + else { + return exporter.getResultStencilRestrictedPackInfo(); + } +} + //=================================================================================================================== // // createPackInfo Export @@ -241,6 +354,14 @@ void exportCommunicationClasses(py::module_& m) return internal::UniformMPIDatatypeInfoWrapper< FieldTypes... >(blocks, blockDataName, numberOfGhostLayers); }, "blocks"_a, "blockDataName"_a, "numberOfGhostLayers"_a = uint_t(0)); + + m2.def( + "createStencilRestrictedPackInfo", + [](const shared_ptr & blocks, + const std::string & blockDataName) { + return internal::StencilRestrictedPackInfoWrapper< FieldTypes... >(blocks, blockDataName); + }, + "blocks"_a, "blockDataName"_a); } } // namespace field -- GitLab From 9cc7a8f874d8eff8974b410dc1449e193a0099a8 Mon Sep 17 00:00:00 2001 From: markus holzer Date: Mon, 28 Dec 2020 21:35:31 +0100 Subject: [PATCH 10/10] Minor Fixes --- python/waLBerla/callbacks.py | 2 +- src/python_coupling/CreateConfig.cpp | 27 ++++++++++++--------------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/python/waLBerla/callbacks.py b/python/waLBerla/callbacks.py index f9153ec5b..07f2ebc0f 100644 --- a/python/waLBerla/callbacks.py +++ b/python/waLBerla/callbacks.py @@ -149,7 +149,7 @@ class ScenarioManager: cfg = None while cfg is None: cfg = get_config_from_scenario(scenario) - # walberla_cpp.log_info_on_root("Simulating Scenario %d of %d :" % (idx + 1, len(self._scenarios))) + walberla_cpp.log_info_on_root("Simulating Scenario %d of %d :" % (idx + 1, len(self._scenarios))) yield cfg except ImportError: diff --git a/src/python_coupling/CreateConfig.cpp b/src/python_coupling/CreateConfig.cpp index c7e3d1b24..5f8f9615c 100644 --- a/src/python_coupling/CreateConfig.cpp +++ b/src/python_coupling/CreateConfig.cpp @@ -70,30 +70,27 @@ shared_ptr< Config > createConfigFromPythonScript(const std::string& scriptFile, class PythonMultipleConfigGenerator : public config::ConfigGenerator { public: - PythonMultipleConfigGenerator(py::list ConfigList) // NOLINT - : ConfigList_(ConfigList), counter(0) // NOLINT + PythonMultipleConfigGenerator(py::object ScenarioConfigGenerator) // NOLINT + : ScenarioConfigGenerator_(ScenarioConfigGenerator) // NOLINT {} shared_ptr< Config > next() override { shared_ptr< Config > config = make_shared< Config >(); - - if ( counter == ConfigList_.size() ) + try + { + py::dict configDict = ScenarioConfigGenerator_.attr("__next__")(); + configFromPythonDict(config->getWritableGlobalBlock(), configDict); + return config; + } + catch (py::error_already_set&) + { return shared_ptr(); - - py::dict configDict = ConfigList_[counter]; - configFromPythonDict(config->getWritableGlobalBlock(), configDict); - - WALBERLA_LOG_INFO_ON_ROOT("Simulating Scenario " << counter + 1 << " of " << ConfigList_.size() << ":") - - counter++; - - return config; + } } private: - py::list ConfigList_; - uint_t counter; + py::object ScenarioConfigGenerator_; }; class PythonSingleConfigGenerator : public config::ConfigGenerator -- GitLab