From 96ff4b538800dacf7a027055f15facfec268fe91 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Thu, 15 Aug 2024 08:51:53 +0200 Subject: [PATCH 01/81] Started data_handler --- src/Makefile.am | 3 +- src/t8_data/t8_data_handler.hxx | 90 +++++++++++++ test/CMakeLists.txt | 1 + test/t8_data/t8_gtest_data_handler.cxx | 179 +++++++++++++++++++++++++ 4 files changed, 272 insertions(+), 1 deletion(-) create mode 100644 src/t8_data/t8_data_handler.hxx create mode 100644 test/t8_data/t8_gtest_data_handler.cxx diff --git a/src/Makefile.am b/src/Makefile.am index 1079fe8f21..6c131c9f1b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -44,7 +44,8 @@ libt8_installed_headers_cmesh = \ src/t8_cmesh/t8_cmesh_types.h \ src/t8_cmesh/t8_cmesh_stash.h libt8_installed_headers_data = \ - src/t8_data/t8_shmem.h src/t8_data/t8_containers.h + src/t8_data/t8_shmem.h src/t8_data/t8_containers.h \ + src/t8_data/t8_data_handler.hxx libt8_installed_headers_forest = \ src/t8_forest/t8_forest.h \ src/t8_forest/t8_forest_general.h \ diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx new file mode 100644 index 0000000000..13e00375c5 --- /dev/null +++ b/src/t8_data/t8_data_handler.hxx @@ -0,0 +1,90 @@ +/* +This file is part of t8code. +t8code is a C library to manage a collection (a forest) of multiple +connected adaptive space-trees of general element classes in parallel. + +Copyright (C) 2024 the developers + +t8code 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 2 of the License, or +(at your option) any later version. + +t8code 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 t8code; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef T8_DATA_HANDLER_HXX +#define T8_DATA_HANDLER_HXX + +#include +#include + +template +class t8_data_handler { + public: + t8_data_handler (); + + int + t8_data_size (sc_MPI_Comm comm); + + int + t8_buffer_size (const int num_data, sc_MPI_Comm comm) + { + const int single_size = t8_data_size (); + const int num_data_size; + int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &num_data_size); + SC_CHECK_MPI (mpiret); + return num_data_size + num_data * single_size; + } + + /** + * Overwrite this routine to describe how data of type T should be packed + * + * \param[in] data Data to be packed via MPI_Pack + * \return the size of the packed data in number of bytes. + */ + void + t8_data_pack (const T &data, const int pos, std::vector &buffer, sc_MPI_Comm comm); + + void + t8_data_pack_vector (const std::vector &data, const int num_data, std::vector &buffer, sc_MPI_Comm comm) + { + int pos = 0; + int size; + T8_ASSERT (buffer.size == t8_buffer_size (num_data, comm)); + + sc_MPI_Pack_size (1, sc_MPI_Int, comm, &size); + sc_MPI_Pack (&num_data, 1, MPI_INT, buffer.data (), buffer.size (), &pos, comm); + pos += size; + + const int single_size = t8_data_size (comm); + for (int idata = 0; idata < num_data; idata++) { + t8_data_pack (data[idata], pos, buffer, comm); + pos += single_size; + } + } + + /** + * Overwrite this routine to describe how data of type T should be unpacked + * + * \param packed_data A void-pointer to the packed Data + * \return T* the unpacked data. + */ + void + t8_data_unpack (const void *packed_data, const int insize, const int outcount, std::vector &unpacked_data, + sc_MPI_Comm comm); + + void + t8_data_unpack_vector (const std::vector &packed_data, std::vector &data, sc_MPI_Comm comm) + { + } +}; + +#endif /* T8_DATA_HANDLER_HXX */ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 975a7de94d..b0df3c02bc 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -46,6 +46,7 @@ add_t8_test( NAME t8_gtest_multiple_attributes SOURCES t8_gtest_main.c add_t8_test( NAME t8_gtest_attribute_gloidx_array SOURCES t8_gtest_main.cxx t8_cmesh/t8_gtest_attribute_gloidx_array.cxx ) add_t8_test( NAME t8_gtest_shmem SOURCES t8_gtest_main.cxx t8_data/t8_gtest_shmem.cxx ) +add_t8_test( NAME t8_gtest_data_pack SOURCES t8_gtest_main.cxx t8_data/t8_gtest_data_handler.cxx) add_t8_test( NAME t8_gtest_element_volume SOURCES t8_gtest_main.cxx t8_forest/t8_gtest_element_volume.cxx ) add_t8_test( NAME t8_gtest_search SOURCES t8_gtest_main.cxx t8_forest/t8_gtest_search.cxx ) diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx new file mode 100644 index 0000000000..1c14b285f3 --- /dev/null +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -0,0 +1,179 @@ +/* +This file is part of t8code. +t8code is a C library to manage a collection (a forest) of multiple +connected adaptive space-trees of general element classes in parallel. + +Copyright (C) 2024 the developers + +t8code 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 2 of the License, or +(at your option) any later version. + +t8code 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 t8code; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include + +template +struct enlarged_data +{ + T data; // original data + int check; // additional data to check against +}; + +template +class data_creator { + data_creator (const int num_data); + + std::vector> data; +}; + +template <> +class data_creator { + data_creator (const int num_data) + { + data.resize (num_data); + + for (int idata = 0; idata < num_data; idata++) { + data[idata].data = 42; + data[idata].check = idata; + } + } + std::vector> data; +}; + +template <> +class data_creator { + data_creator (const int num_data) + { + data.resize (num_data); + + for (int idata = 0; idata < num_data; idata++) { + data[idata].data = 42.42; + data[idata].check = idata; + } + } + std::vector> data; +}; + +template <> +class t8_data_handler> { + int + t8_data_size () + { + int size; + const int mpiret = sc_MPI_Pack_size (2, sc_MPI_INT, comm, &size); + SC_CHECK_MPI (mpiret); + return size; + } + + void + t8_data_pack (const enlarged_data &data, const int pos, std::vector &buffer, comm) + { + int size; + int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &size); + SC_CHECK_MPI (mpiret); + int current_pos = pos; + + mpiret = sc_MPI_PACK (&data.data, 1, sc_MPI_INT, buffer.data (), buffer.size (), ¤t_pos, comm); + SC_CHECK_MPI (mpiret); + + current_pos += size; + sc_MPI_PACK (&data.data, 1, sc_MPI_INT, buffer.data (), buffer.size (), ¤t_pos, comm); + SC_CHECK_MPI (mpiret); + } +} + +template +class data_handler_test: public testing::Test { + protected: + void + SetUp () override + { + data_handler = new t8_data_handler (); + + int mpiret = sc_MPI_Comm_rank (comm, &mpirank); + SC_CHECK_MPI (mpiret); + mpiret = sc_MPI_Comm_size (comm, &mpisize); + SC_CHECK_MPI (mpiret); + } + + void + TearDown () override + { + } + + t8_data_handler *data_handler; + data_creator creator; + int mpirank; + int mpisize; + std::vector> recv_data; + const int max_num_data = 100; + sc_MPI_Comm comm = sc_MPI_COMM_WORLD; +}; + +TYPED_TEST_SUITE_P (data_handler_test); + +TYPED_TEST_P (data_handler_test, single_data) +{ + this->data_creator (1); + + std::vector buffer; + + this->creator (1); + this->data_handler->t8_data_pack (this->creator->data, 1, buffer, this->comm); + + int mpiret = sc_MPI_Send(buffer.data() +} + +TYPED_TEST_P (data_handler_test, vector_of_data) +{ + for (int num_data = 1; num_data < this->max_num_data; num_data++) { + this->creator (num_data); + + std::vector buffer; + this->data_handler->t8_data_pack_vector (this->creator.data, num_data, buffer, this->comm); + + int mpiret + = sc_MPI_Send (buffer.data (), buffer.size (), sc_MPI_PACKED, (this->mpirank + 1) % this->mpisize, 0, this->comm); + SC_CHECK_MPI (mpiret); + + sc_MPI_Status status; + + int recv_from = (this->mpirank == 0) ? (this->mpisize - 1) : (this->mpisize - 1); + + sc_MPI_Probe (recv_from, 0, this->comm, &status); + SC_CHECK_MPI (mpiret); + + int size; + sc_MPI_Get_count (&status, sc_MPI_PACKED, &size); + SC_CHECK_MPI (mpiret); + std::vector packed (size); + + sc_MPI_Recv (packed.data (), packed.size (), sc_MPI_PACKED, recv_from, 0, this->comm, &status); + SC_CHECK_MPI (mpiret); + + this->recv_data.resize (num_data); + this->data_handler->t8_data_unpack (packed.data (), num_data, num_data, this->recv_data, this->comm); + for (int idata = 0; idata < num_data; idata++) { + EXPECT_EQ (this->recv_data[idata].data, this->creator.data[idata].data); + EXPECT_EQ (this->recv_data[idata].check, this->creator.data[idata].check); + } + } +} + +REGISTER_TYPED_TEST_SUITE_P (data_handler_test, single_data, vector_of_data); + +using DataTypes = ::testing::Types; + +INSTANTIATE_TYPED_TEST_SUITE_P (Test_data_handler, data_handler_test, DataTypes, ); From a5f70f3314a760d215456b5ca676b8a6568e3386 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Thu, 15 Aug 2024 14:32:58 +0200 Subject: [PATCH 02/81] progress data_handler --- src/t8_data/t8_data_handler.cxx | 57 ++++++++++++ src/t8_data/t8_data_handler.hxx | 27 ++++-- test/CMakeLists.txt | 2 +- test/t8_data/t8_data_handler_specs.cxx | 36 ++++++++ test/t8_data/t8_data_handler_specs.hxx | 65 +++++++++++++ test/t8_data/t8_gtest_data_handler.cxx | 123 ++++++++----------------- 6 files changed, 214 insertions(+), 96 deletions(-) create mode 100644 src/t8_data/t8_data_handler.cxx create mode 100644 test/t8_data/t8_data_handler_specs.cxx create mode 100644 test/t8_data/t8_data_handler_specs.hxx diff --git a/src/t8_data/t8_data_handler.cxx b/src/t8_data/t8_data_handler.cxx new file mode 100644 index 0000000000..ca08bde80b --- /dev/null +++ b/src/t8_data/t8_data_handler.cxx @@ -0,0 +1,57 @@ +/* +This file is part of t8code. +t8code is a C library to manage a collection (a forest) of multiple +connected adaptive space-trees of general element classes in parallel. + +Copyright (C) 2024 the developers + +t8code 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 2 of the License, or +(at your option) any later version. + +t8code 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 t8code; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include + +template <> +int +t8_data_handler>::t8_data_size (sc_MPI_Comm comm) +{ + int size; + const int mpiret = sc_MPI_Pack_size (2, sc_MPI_INT, comm, &size); + SC_CHECK_MPI (mpiret); + return size; +} + +template <> +void +t8_data_handler>::t8_data_pack (enlarged_data data, int &pos, std::vector &buffer, + sc_MPI_Comm comm) +{ + int mpiret = sc_MPI_Pack (&data.data, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + SC_CHECK_MPI (mpiret); + + mpiret = sc_MPI_Pack (&data.data, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + SC_CHECK_MPI (mpiret); +} + +template <> +void +t8_data_handler>::t8_data_unpack (std::vector &buffer, int &pos, enlarged_data &data, + int &outcount, sc_MPI_Comm comm) +{ + int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &data.data, 1, sc_MPI_INT, comm); + SC_CHECK_MPI (mpiret); + + mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &data.check, 1, sc_MPI_INT, comm); + SC_CHECK_MPI (mpiret); +} diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 13e00375c5..55a3f72684 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -25,6 +25,7 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include +#include template class t8_data_handler { @@ -51,23 +52,18 @@ class t8_data_handler { * \return the size of the packed data in number of bytes. */ void - t8_data_pack (const T &data, const int pos, std::vector &buffer, sc_MPI_Comm comm); + t8_data_pack (T &data, int &pos, std::vector &buffer, sc_MPI_Comm comm); void t8_data_pack_vector (const std::vector &data, const int num_data, std::vector &buffer, sc_MPI_Comm comm) { int pos = 0; - int size; T8_ASSERT (buffer.size == t8_buffer_size (num_data, comm)); - sc_MPI_Pack_size (1, sc_MPI_Int, comm, &size); sc_MPI_Pack (&num_data, 1, MPI_INT, buffer.data (), buffer.size (), &pos, comm); - pos += size; - const int single_size = t8_data_size (comm); for (int idata = 0; idata < num_data; idata++) { t8_data_pack (data[idata], pos, buffer, comm); - pos += single_size; } } @@ -78,13 +74,26 @@ class t8_data_handler { * \return T* the unpacked data. */ void - t8_data_unpack (const void *packed_data, const int insize, const int outcount, std::vector &unpacked_data, - sc_MPI_Comm comm); + t8_data_unpack (std::vector &buffer, int &pos, T &data, sc_MPI_Comm comm); void - t8_data_unpack_vector (const std::vector &packed_data, std::vector &data, sc_MPI_Comm comm) + t8_data_unpack_vector (std::vector &buffer, std::vector &data, int &outcount, sc_MPI_Comm comm) { + int pos = 0; + + int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &outcount, 1, sc_MPI_INT, comm); + SC_CHECK_MPI (mpiret); + T8_ASSERT (outcount >= 0); + + data.resize (outcount); + + for (int ipack = 0; ipack < outcount; ++ipack) { + t8_data_unpack (buffer, pos, data[ipack], comm); + } } }; +template <> +class t8_data_handler>; + #endif /* T8_DATA_HANDLER_HXX */ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b0df3c02bc..09effb7f40 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -46,7 +46,7 @@ add_t8_test( NAME t8_gtest_multiple_attributes SOURCES t8_gtest_main.c add_t8_test( NAME t8_gtest_attribute_gloidx_array SOURCES t8_gtest_main.cxx t8_cmesh/t8_gtest_attribute_gloidx_array.cxx ) add_t8_test( NAME t8_gtest_shmem SOURCES t8_gtest_main.cxx t8_data/t8_gtest_shmem.cxx ) -add_t8_test( NAME t8_gtest_data_pack SOURCES t8_gtest_main.cxx t8_data/t8_gtest_data_handler.cxx) +add_t8_test( NAME t8_gtest_data_pack SOURCES t8_gtest_main.cxx t8_data/t8_gtest_data_handler.cxx t8_data/t8_data_handler_specs.cxx) add_t8_test( NAME t8_gtest_element_volume SOURCES t8_gtest_main.cxx t8_forest/t8_gtest_element_volume.cxx ) add_t8_test( NAME t8_gtest_search SOURCES t8_gtest_main.cxx t8_forest/t8_gtest_search.cxx ) diff --git a/test/t8_data/t8_data_handler_specs.cxx b/test/t8_data/t8_data_handler_specs.cxx new file mode 100644 index 0000000000..eb8389903b --- /dev/null +++ b/test/t8_data/t8_data_handler_specs.cxx @@ -0,0 +1,36 @@ +/* +This file is part of t8code. +t8code is a C library to manage a collection (a forest) of multiple +connected adaptive space-trees of general element classes in parallel. + +Copyright (C) 2024 the developers + +t8code 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 2 of the License, or +(at your option) any later version. + +t8code 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 t8code; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include + +template <> +void +data_creator>::create (const int num_data) +{ + large_data.resize (num_data); + int idata = 0; + for (enlarged_data item : large_data) { + item.data = 42; + item.check = idata++; + } +} diff --git a/test/t8_data/t8_data_handler_specs.hxx b/test/t8_data/t8_data_handler_specs.hxx new file mode 100644 index 0000000000..f7458d8cb7 --- /dev/null +++ b/test/t8_data/t8_data_handler_specs.hxx @@ -0,0 +1,65 @@ +/* +This file is part of t8code. +t8code is a C library to manage a collection (a forest) of multiple +connected adaptive space-trees of general element classes in parallel. + +Copyright (C) 2024 the developers + +t8code 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 2 of the License, or +(at your option) any later version. + +t8code 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 t8code; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef T8_DATA_HANDLER_SPECS_HXX +#define T8_DATA_HANDLER_SPECS_HXX + +#include +#include + +template +struct enlarged_data +{ + T data; // original data + int check; // additional data to check against +}; + +template +class data_creator { + public: + data_creator (); + + void + create (const int num_data); + + std::vector large_data; +}; + +template <> +class data_creator; + +template <> +class data_creator { + void + create (const int num_data) + { + data.resize (num_data); + + for (int idata = 0; idata < num_data; idata++) { + data[idata].data = 42.42; + data[idata].check = idata; + } + } + std::vector> data; +}; + +#endif /* T8_DATA_HANDLER_SPECS_HXX */ diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 1c14b285f3..832fd502c9 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -21,87 +21,16 @@ along with t8code; if not, write to the Free Software Foundation, Inc., */ #include +#include #include #include -template -struct enlarged_data -{ - T data; // original data - int check; // additional data to check against -}; - -template -class data_creator { - data_creator (const int num_data); - - std::vector> data; -}; - -template <> -class data_creator { - data_creator (const int num_data) - { - data.resize (num_data); - - for (int idata = 0; idata < num_data; idata++) { - data[idata].data = 42; - data[idata].check = idata; - } - } - std::vector> data; -}; - -template <> -class data_creator { - data_creator (const int num_data) - { - data.resize (num_data); - - for (int idata = 0; idata < num_data; idata++) { - data[idata].data = 42.42; - data[idata].check = idata; - } - } - std::vector> data; -}; - -template <> -class t8_data_handler> { - int - t8_data_size () - { - int size; - const int mpiret = sc_MPI_Pack_size (2, sc_MPI_INT, comm, &size); - SC_CHECK_MPI (mpiret); - return size; - } - - void - t8_data_pack (const enlarged_data &data, const int pos, std::vector &buffer, comm) - { - int size; - int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &size); - SC_CHECK_MPI (mpiret); - int current_pos = pos; - - mpiret = sc_MPI_PACK (&data.data, 1, sc_MPI_INT, buffer.data (), buffer.size (), ¤t_pos, comm); - SC_CHECK_MPI (mpiret); - - current_pos += size; - sc_MPI_PACK (&data.data, 1, sc_MPI_INT, buffer.data (), buffer.size (), ¤t_pos, comm); - SC_CHECK_MPI (mpiret); - } -} - template class data_handler_test: public testing::Test { protected: void SetUp () override { - data_handler = new t8_data_handler (); - int mpiret = sc_MPI_Comm_rank (comm, &mpirank); SC_CHECK_MPI (mpiret); mpiret = sc_MPI_Comm_size (comm, &mpisize); @@ -113,11 +42,11 @@ class data_handler_test: public testing::Test { { } - t8_data_handler *data_handler; - data_creator creator; + t8_data_handler> data_handler; + data_creator> creator; + std::vector> recv_data; int mpirank; int mpisize; - std::vector> recv_data; const int max_num_data = 100; sc_MPI_Comm comm = sc_MPI_COMM_WORLD; }; @@ -126,20 +55,41 @@ TYPED_TEST_SUITE_P (data_handler_test); TYPED_TEST_P (data_handler_test, single_data) { - this->data_creator (1); - std::vector buffer; - this->creator (1); - this->data_handler->t8_data_pack (this->creator->data, 1, buffer, this->comm); + this->creator.create (1); + this->data_handler->t8_data_pack (this->creator->data[0], 0, buffer, this->comm); + + int mpiret + = sc_MPI_Send (buffer.data (), buffer.size (), sc_MPI_PACKED, (this->mpirank + 1) % this->mpisize, 0, this->comm); + SC_CHECK_MPI (mpiret); + + int recv_from = (this->mpirank == 0) ? (this->mpisize - 1) : (this->mpisize - 1); + + sc_MPI_Status status; + + mpiret = sc_MPI_Probe (recv_from, 0, this->comm, &status); + SC_CHECK_MPI (mpiret); + + int size; + mpiret = sc_MPI_Get_count (&status, sc_MPI_PACKED, &size); + SC_CHECK_MPI (mpiret); + std::vector packed (size); + + mpiret = sc_MPI_Recv (packed.data (), packed.size (), sc_MPI_PACKED, recv_from, 0, this->comm, &status); + SC_CHECK_MPI (mpiret); + + this->recv_data.resize (1); + this->data_handler->t8_data_unpack (packed, this->recv_data[0], this->comm); - int mpiret = sc_MPI_Send(buffer.data() + EXPECT_EQ (this->recv_data[0].data, this->creator[0].data); + EXPECT_EQ (this->recv_data[0].check, this->creator[0].check); } TYPED_TEST_P (data_handler_test, vector_of_data) { for (int num_data = 1; num_data < this->max_num_data; num_data++) { - this->creator (num_data); + this->creator->create (num_data); std::vector buffer; this->data_handler->t8_data_pack_vector (this->creator.data, num_data, buffer, this->comm); @@ -152,19 +102,20 @@ TYPED_TEST_P (data_handler_test, vector_of_data) int recv_from = (this->mpirank == 0) ? (this->mpisize - 1) : (this->mpisize - 1); - sc_MPI_Probe (recv_from, 0, this->comm, &status); + mpiret = sc_MPI_Probe (recv_from, 0, this->comm, &status); SC_CHECK_MPI (mpiret); int size; - sc_MPI_Get_count (&status, sc_MPI_PACKED, &size); + mpiret = sc_MPI_Get_count (&status, sc_MPI_PACKED, &size); SC_CHECK_MPI (mpiret); std::vector packed (size); sc_MPI_Recv (packed.data (), packed.size (), sc_MPI_PACKED, recv_from, 0, this->comm, &status); SC_CHECK_MPI (mpiret); - this->recv_data.resize (num_data); - this->data_handler->t8_data_unpack (packed.data (), num_data, num_data, this->recv_data, this->comm); + int outcount = 0; + this->data_handler->t8_data_unpack_vector (packed, this->recv_data, &outcount, this->comm); + EXPECT_EQ (outcount, num_data); for (int idata = 0; idata < num_data; idata++) { EXPECT_EQ (this->recv_data[idata].data, this->creator.data[idata].data); EXPECT_EQ (this->recv_data[idata].check, this->creator.data[idata].check); @@ -174,6 +125,6 @@ TYPED_TEST_P (data_handler_test, vector_of_data) REGISTER_TYPED_TEST_SUITE_P (data_handler_test, single_data, vector_of_data); -using DataTypes = ::testing::Types; +using DataTypes = ::testing::Types; INSTANTIATE_TYPED_TEST_SUITE_P (Test_data_handler, data_handler_test, DataTypes, ); From cea2b1174bfbeaeb7715babb130312e2d8617ffa Mon Sep 17 00:00:00 2001 From: David Knapp Date: Mon, 19 Aug 2024 15:58:06 +0200 Subject: [PATCH 03/81] Use a base-class --- src/t8_data/t8_data_handler.cxx | 11 ++--- src/t8_data/t8_data_handler.hxx | 62 +++++++++++++------------- test/t8_data/t8_data_handler_specs.cxx | 12 +++++ test/t8_data/t8_data_handler_specs.hxx | 17 ++----- test/t8_data/t8_gtest_data_handler.cxx | 28 +++++++----- 5 files changed, 69 insertions(+), 61 deletions(-) diff --git a/src/t8_data/t8_data_handler.cxx b/src/t8_data/t8_data_handler.cxx index ca08bde80b..017399744d 100644 --- a/src/t8_data/t8_data_handler.cxx +++ b/src/t8_data/t8_data_handler.cxx @@ -21,10 +21,11 @@ along with t8code; if not, write to the Free Software Foundation, Inc., */ #include +#include template <> int -t8_data_handler>::t8_data_size (sc_MPI_Comm comm) +t8_single_data_handler>::t8_data_size (sc_MPI_Comm comm) { int size; const int mpiret = sc_MPI_Pack_size (2, sc_MPI_INT, comm, &size); @@ -34,8 +35,8 @@ t8_data_handler>::t8_data_size (sc_MPI_Comm comm) template <> void -t8_data_handler>::t8_data_pack (enlarged_data data, int &pos, std::vector &buffer, - sc_MPI_Comm comm) +t8_single_data_handler>::t8_data_pack (enlarged_data data, int &pos, std::vector &buffer, + sc_MPI_Comm comm) { int mpiret = sc_MPI_Pack (&data.data, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); SC_CHECK_MPI (mpiret); @@ -46,8 +47,8 @@ t8_data_handler>::t8_data_pack (enlarged_data data, int template <> void -t8_data_handler>::t8_data_unpack (std::vector &buffer, int &pos, enlarged_data &data, - int &outcount, sc_MPI_Comm comm) +t8_single_data_handler>::t8_data_unpack (std::vector &buffer, int &pos, + enlarged_data &data, sc_MPI_Comm comm) { int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &data.data, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 55a3f72684..b2129267e8 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -28,54 +28,59 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include template -class t8_data_handler { +class t8_single_data_handler { public: - t8_data_handler (); - int t8_data_size (sc_MPI_Comm comm); + /** + * Overwrite this routine to describe how data of type T should be packed + * + * \param[in] data Data to be packed via MPI_Pack + * \return the size of the packed data in number of bytes. + */ + void + t8_data_pack (T &data, int &pos, std::vector &buffer, sc_MPI_Comm comm); + + /** + * Overwrite this routine to describe how data of type T should be unpacked + * + * \param packed_data A void-pointer to the packed Data + * \return T* the unpacked data. + */ + void + t8_data_unpack (std::vector &buffer, int &pos, T &data, sc_MPI_Comm comm); +}; + +template <> +class t8_single_data_handler>; + +template +class t8_data_handler: public t8_single_data_handler { + public: int t8_buffer_size (const int num_data, sc_MPI_Comm comm) { - const int single_size = t8_data_size (); - const int num_data_size; + const int single_size = this->t8_data_size (comm); + int num_data_size; int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &num_data_size); SC_CHECK_MPI (mpiret); return num_data_size + num_data * single_size; } - /** - * Overwrite this routine to describe how data of type T should be packed - * - * \param[in] data Data to be packed via MPI_Pack - * \return the size of the packed data in number of bytes. - */ - void - t8_data_pack (T &data, int &pos, std::vector &buffer, sc_MPI_Comm comm); - void - t8_data_pack_vector (const std::vector &data, const int num_data, std::vector &buffer, sc_MPI_Comm comm) + t8_data_pack_vector (std::vector &data, const int num_data, std::vector &buffer, sc_MPI_Comm comm) { int pos = 0; - T8_ASSERT (buffer.size == t8_buffer_size (num_data, comm)); + T8_ASSERT (buffer.size () == t8_buffer_size (num_data, comm)); sc_MPI_Pack (&num_data, 1, MPI_INT, buffer.data (), buffer.size (), &pos, comm); for (int idata = 0; idata < num_data; idata++) { - t8_data_pack (data[idata], pos, buffer, comm); + this->t8_data_pack (data[idata], pos, buffer, comm); } } - /** - * Overwrite this routine to describe how data of type T should be unpacked - * - * \param packed_data A void-pointer to the packed Data - * \return T* the unpacked data. - */ - void - t8_data_unpack (std::vector &buffer, int &pos, T &data, sc_MPI_Comm comm); - void t8_data_unpack_vector (std::vector &buffer, std::vector &data, int &outcount, sc_MPI_Comm comm) { @@ -88,12 +93,9 @@ class t8_data_handler { data.resize (outcount); for (int ipack = 0; ipack < outcount; ++ipack) { - t8_data_unpack (buffer, pos, data[ipack], comm); + this->t8_data_unpack (buffer, pos, data[ipack], comm); } } }; -template <> -class t8_data_handler>; - #endif /* T8_DATA_HANDLER_HXX */ diff --git a/test/t8_data/t8_data_handler_specs.cxx b/test/t8_data/t8_data_handler_specs.cxx index eb8389903b..f658153751 100644 --- a/test/t8_data/t8_data_handler_specs.cxx +++ b/test/t8_data/t8_data_handler_specs.cxx @@ -34,3 +34,15 @@ data_creator>::create (const int num_data) item.check = idata++; } } + +template <> +void +data_creator>::create (const int num_data) +{ + large_data.resize (num_data); + int idata = 0; + for (enlarged_data item : large_data) { + item.data = 42.42; + item.check = idata++; + } +} diff --git a/test/t8_data/t8_data_handler_specs.hxx b/test/t8_data/t8_data_handler_specs.hxx index f7458d8cb7..c8de109b3f 100644 --- a/test/t8_data/t8_data_handler_specs.hxx +++ b/test/t8_data/t8_data_handler_specs.hxx @@ -36,7 +36,8 @@ struct enlarged_data template class data_creator { public: - data_creator (); + data_creator (): large_data (0) {}; + ; void create (const int num_data); @@ -48,18 +49,6 @@ template <> class data_creator; template <> -class data_creator { - void - create (const int num_data) - { - data.resize (num_data); - - for (int idata = 0; idata < num_data; idata++) { - data[idata].data = 42.42; - data[idata].check = idata; - } - } - std::vector> data; -}; +class data_creator; #endif /* T8_DATA_HANDLER_SPECS_HXX */ diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 832fd502c9..e05f830a5a 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -42,8 +42,8 @@ class data_handler_test: public testing::Test { { } - t8_data_handler> data_handler; - data_creator> creator; + t8_data_handler> *data_handler; + data_creator> *creator; std::vector> recv_data; int mpirank; int mpisize; @@ -57,8 +57,9 @@ TYPED_TEST_P (data_handler_test, single_data) { std::vector buffer; - this->creator.create (1); - this->data_handler->t8_data_pack (this->creator->data[0], 0, buffer, this->comm); + this->creator->create (1); + int pos = 0; + this->data_handler->t8_data_pack (this->creator->large_data[0], pos, buffer, this->comm); int mpiret = sc_MPI_Send (buffer.data (), buffer.size (), sc_MPI_PACKED, (this->mpirank + 1) % this->mpisize, 0, this->comm); @@ -76,14 +77,17 @@ TYPED_TEST_P (data_handler_test, single_data) SC_CHECK_MPI (mpiret); std::vector packed (size); - mpiret = sc_MPI_Recv (packed.data (), packed.size (), sc_MPI_PACKED, recv_from, 0, this->comm, &status); + pos = 0; + mpiret = sc_MPI_Recv (packed.data (), packed.size (), sc_MPI_PACKED, recv_from, pos, this->comm, &status); SC_CHECK_MPI (mpiret); this->recv_data.resize (1); - this->data_handler->t8_data_unpack (packed, this->recv_data[0], this->comm); + int outcount = 0; + pos = 0; + this->data_handler->t8_data_unpack (packed, pos, this->recv_data[0], this->comm); - EXPECT_EQ (this->recv_data[0].data, this->creator[0].data); - EXPECT_EQ (this->recv_data[0].check, this->creator[0].check); + EXPECT_EQ (this->recv_data[0].data, this->creator->large_data[0].data); + EXPECT_EQ (this->recv_data[0].check, this->creator->large_data[0].check); } TYPED_TEST_P (data_handler_test, vector_of_data) @@ -92,7 +96,7 @@ TYPED_TEST_P (data_handler_test, vector_of_data) this->creator->create (num_data); std::vector buffer; - this->data_handler->t8_data_pack_vector (this->creator.data, num_data, buffer, this->comm); + this->data_handler->t8_data_pack_vector (this->creator->large_data, num_data, buffer, this->comm); int mpiret = sc_MPI_Send (buffer.data (), buffer.size (), sc_MPI_PACKED, (this->mpirank + 1) % this->mpisize, 0, this->comm); @@ -114,11 +118,11 @@ TYPED_TEST_P (data_handler_test, vector_of_data) SC_CHECK_MPI (mpiret); int outcount = 0; - this->data_handler->t8_data_unpack_vector (packed, this->recv_data, &outcount, this->comm); + this->data_handler->t8_data_unpack_vector (packed, this->recv_data, outcount, this->comm); EXPECT_EQ (outcount, num_data); for (int idata = 0; idata < num_data; idata++) { - EXPECT_EQ (this->recv_data[idata].data, this->creator.data[idata].data); - EXPECT_EQ (this->recv_data[idata].check, this->creator.data[idata].check); + EXPECT_EQ (this->recv_data[idata].data, this->creator->large_data[idata].data); + EXPECT_EQ (this->recv_data[idata].check, this->creator->large_data[idata].check); } } } From 993c979a60260131353e912c8aaceb2ed70fc43b Mon Sep 17 00:00:00 2001 From: David Knapp Date: Mon, 19 Aug 2024 16:13:19 +0200 Subject: [PATCH 04/81] restructuring --- src/t8_data/t8_data_handler.cxx | 37 -------------------------- src/t8_data/t8_data_handler.hxx | 28 ------------------- test/t8_data/t8_gtest_data_handler.cxx | 8 +++--- 3 files changed, 5 insertions(+), 68 deletions(-) diff --git a/src/t8_data/t8_data_handler.cxx b/src/t8_data/t8_data_handler.cxx index 017399744d..d3b671ff8e 100644 --- a/src/t8_data/t8_data_handler.cxx +++ b/src/t8_data/t8_data_handler.cxx @@ -19,40 +19,3 @@ You should have received a copy of the GNU General Public License along with t8code; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include -#include - -template <> -int -t8_single_data_handler>::t8_data_size (sc_MPI_Comm comm) -{ - int size; - const int mpiret = sc_MPI_Pack_size (2, sc_MPI_INT, comm, &size); - SC_CHECK_MPI (mpiret); - return size; -} - -template <> -void -t8_single_data_handler>::t8_data_pack (enlarged_data data, int &pos, std::vector &buffer, - sc_MPI_Comm comm) -{ - int mpiret = sc_MPI_Pack (&data.data, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); - SC_CHECK_MPI (mpiret); - - mpiret = sc_MPI_Pack (&data.data, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); - SC_CHECK_MPI (mpiret); -} - -template <> -void -t8_single_data_handler>::t8_data_unpack (std::vector &buffer, int &pos, - enlarged_data &data, sc_MPI_Comm comm) -{ - int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &data.data, 1, sc_MPI_INT, comm); - SC_CHECK_MPI (mpiret); - - mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &data.check, 1, sc_MPI_INT, comm); - SC_CHECK_MPI (mpiret); -} diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index b2129267e8..1a2c85be4a 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -27,34 +27,6 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include -template -class t8_single_data_handler { - public: - int - t8_data_size (sc_MPI_Comm comm); - - /** - * Overwrite this routine to describe how data of type T should be packed - * - * \param[in] data Data to be packed via MPI_Pack - * \return the size of the packed data in number of bytes. - */ - void - t8_data_pack (T &data, int &pos, std::vector &buffer, sc_MPI_Comm comm); - - /** - * Overwrite this routine to describe how data of type T should be unpacked - * - * \param packed_data A void-pointer to the packed Data - * \return T* the unpacked data. - */ - void - t8_data_unpack (std::vector &buffer, int &pos, T &data, sc_MPI_Comm comm); -}; - -template <> -class t8_single_data_handler>; - template class t8_data_handler: public t8_single_data_handler { public: diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index e05f830a5a..cc265d0199 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -52,7 +52,7 @@ class data_handler_test: public testing::Test { }; TYPED_TEST_SUITE_P (data_handler_test); - +/* TYPED_TEST_P (data_handler_test, single_data) { std::vector buffer; @@ -89,7 +89,7 @@ TYPED_TEST_P (data_handler_test, single_data) EXPECT_EQ (this->recv_data[0].data, this->creator->large_data[0].data); EXPECT_EQ (this->recv_data[0].check, this->creator->large_data[0].check); } - +*/ TYPED_TEST_P (data_handler_test, vector_of_data) { for (int num_data = 1; num_data < this->max_num_data; num_data++) { @@ -127,7 +127,9 @@ TYPED_TEST_P (data_handler_test, vector_of_data) } } -REGISTER_TYPED_TEST_SUITE_P (data_handler_test, single_data, vector_of_data); +REGISTER_TYPED_TEST_SUITE_P (data_handler_test, + // single_data, + vector_of_data); using DataTypes = ::testing::Types; From a03b01ec825c9a861ba53dc068f251c1add72dd9 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Mon, 19 Aug 2024 16:48:42 +0200 Subject: [PATCH 05/81] Working version for enlarged int --- config/t8_vtk.m4 | 2 +- src/t8_data/t8_data_handler.cxx | 21 --------------------- src/t8_data/t8_data_handler.hxx | 3 ++- test/t8_data/t8_data_handler_specs.hxx | 6 ++++-- test/t8_data/t8_gtest_data_handler.cxx | 21 +++++++++++++-------- 5 files changed, 20 insertions(+), 33 deletions(-) delete mode 100644 src/t8_data/t8_data_handler.cxx diff --git a/config/t8_vtk.m4 b/config/t8_vtk.m4 index d3ef812005..8da79a908b 100644 --- a/config/t8_vtk.m4 +++ b/config/t8_vtk.m4 @@ -19,7 +19,7 @@ T8_ARG_WITH([vtk], [vtk library (optionally use --with-vtk=)], [VTK]) - + if test "x$T8_WITH_VTK" != xno ; then if test "x$T8_WITH_VTK_VERSION_MANUALLY_PROVIDED" != xno ; then t8_vtk_version=$T8_WITH_VTK_VERSION_MANUALLY_PROVIDED diff --git a/src/t8_data/t8_data_handler.cxx b/src/t8_data/t8_data_handler.cxx deleted file mode 100644 index d3b671ff8e..0000000000 --- a/src/t8_data/t8_data_handler.cxx +++ /dev/null @@ -1,21 +0,0 @@ -/* -This file is part of t8code. -t8code is a C library to manage a collection (a forest) of multiple -connected adaptive space-trees of general element classes in parallel. - -Copyright (C) 2024 the developers - -t8code 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 2 of the License, or -(at your option) any later version. - -t8code 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 t8code; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 1a2c85be4a..53b532a5d1 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -25,7 +25,8 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include -#include +#include +#include template class t8_data_handler: public t8_single_data_handler { diff --git a/test/t8_data/t8_data_handler_specs.hxx b/test/t8_data/t8_data_handler_specs.hxx index c8de109b3f..baf5c0c962 100644 --- a/test/t8_data/t8_data_handler_specs.hxx +++ b/test/t8_data/t8_data_handler_specs.hxx @@ -36,8 +36,10 @@ struct enlarged_data template class data_creator { public: - data_creator (): large_data (0) {}; - ; + data_creator () + { + large_data = std::vector (0); + }; void create (const int num_data); diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index cc265d0199..4f54568ba3 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -35,6 +35,9 @@ class data_handler_test: public testing::Test { SC_CHECK_MPI (mpiret); mpiret = sc_MPI_Comm_size (comm, &mpisize); SC_CHECK_MPI (mpiret); + + data_handler = new t8_data_handler> (); + creator = new data_creator> (); } void @@ -52,10 +55,10 @@ class data_handler_test: public testing::Test { }; TYPED_TEST_SUITE_P (data_handler_test); -/* + TYPED_TEST_P (data_handler_test, single_data) { - std::vector buffer; + std::vector buffer (this->data_handler->t8_buffer_size (1, this->comm)); this->creator->create (1); int pos = 0; @@ -89,13 +92,14 @@ TYPED_TEST_P (data_handler_test, single_data) EXPECT_EQ (this->recv_data[0].data, this->creator->large_data[0].data); EXPECT_EQ (this->recv_data[0].check, this->creator->large_data[0].check); } -*/ + +/* TYPED_TEST_P (data_handler_test, vector_of_data) { for (int num_data = 1; num_data < this->max_num_data; num_data++) { this->creator->create (num_data); - std::vector buffer; + std::vector buffer(this->data_handler->t8_buffer_size(num_data, this->comm)); this->data_handler->t8_data_pack_vector (this->creator->large_data, num_data, buffer, this->comm); int mpiret @@ -125,12 +129,13 @@ TYPED_TEST_P (data_handler_test, vector_of_data) EXPECT_EQ (this->recv_data[idata].check, this->creator->large_data[idata].check); } } -} +}*/ REGISTER_TYPED_TEST_SUITE_P (data_handler_test, - // single_data, - vector_of_data); + single_data //, + //vector_of_data +); -using DataTypes = ::testing::Types; +using DataTypes = ::testing::Types; INSTANTIATE_TYPED_TEST_SUITE_P (Test_data_handler, data_handler_test, DataTypes, ); From 6ee7851448363f3d11153cdafebb267434799cea Mon Sep 17 00:00:00 2001 From: David Knapp Date: Tue, 20 Aug 2024 09:02:50 +0200 Subject: [PATCH 06/81] Fix communication error --- test/t8_data/t8_gtest_data_handler.cxx | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 4f54568ba3..8f9d015c00 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -64,12 +64,13 @@ TYPED_TEST_P (data_handler_test, single_data) int pos = 0; this->data_handler->t8_data_pack (this->creator->large_data[0], pos, buffer, this->comm); + int send_to = (this->mpirank + 1) % this->mpisize; + int mpiret = sc_MPI_Send (buffer.data (), buffer.size (), sc_MPI_PACKED, (this->mpirank + 1) % this->mpisize, 0, this->comm); SC_CHECK_MPI (mpiret); - int recv_from = (this->mpirank == 0) ? (this->mpisize - 1) : (this->mpisize - 1); - + int recv_from = (this->mpirank == 0) ? (this->mpisize - 1) : (this->mpirank - 1); sc_MPI_Status status; mpiret = sc_MPI_Probe (recv_from, 0, this->comm, &status); @@ -93,13 +94,12 @@ TYPED_TEST_P (data_handler_test, single_data) EXPECT_EQ (this->recv_data[0].check, this->creator->large_data[0].check); } -/* TYPED_TEST_P (data_handler_test, vector_of_data) { for (int num_data = 1; num_data < this->max_num_data; num_data++) { this->creator->create (num_data); - std::vector buffer(this->data_handler->t8_buffer_size(num_data, this->comm)); + std::vector buffer (this->data_handler->t8_buffer_size (num_data, this->comm)); this->data_handler->t8_data_pack_vector (this->creator->large_data, num_data, buffer, this->comm); int mpiret @@ -108,7 +108,7 @@ TYPED_TEST_P (data_handler_test, vector_of_data) sc_MPI_Status status; - int recv_from = (this->mpirank == 0) ? (this->mpisize - 1) : (this->mpisize - 1); + int recv_from = (this->mpirank == 0) ? (this->mpisize - 1) : (this->mpirank - 1); mpiret = sc_MPI_Probe (recv_from, 0, this->comm, &status); SC_CHECK_MPI (mpiret); @@ -129,12 +129,9 @@ TYPED_TEST_P (data_handler_test, vector_of_data) EXPECT_EQ (this->recv_data[idata].check, this->creator->large_data[idata].check); } } -}*/ +} -REGISTER_TYPED_TEST_SUITE_P (data_handler_test, - single_data //, - //vector_of_data -); +REGISTER_TYPED_TEST_SUITE_P (data_handler_test, single_data, vector_of_data); using DataTypes = ::testing::Types; From df3abdf887267b2ecfb9951e9016deaa640d295f Mon Sep 17 00:00:00 2001 From: David Knapp Date: Tue, 20 Aug 2024 09:35:56 +0200 Subject: [PATCH 07/81] Add documentation --- src/t8_data/t8_data_handler.hxx | 38 ++++++++++++++++++++------ test/t8_data/t8_gtest_data_handler.cxx | 37 +++++++++++++++++++------ 2 files changed, 59 insertions(+), 16 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 53b532a5d1..9864631658 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -31,31 +31,53 @@ along with t8code; if not, write to the Free Software Foundation, Inc., template class t8_data_handler: public t8_single_data_handler { public: + /** + * Compute the size of a buffer for \a num_data items of type T + * + * \param[in] num_data Number of items that will be packed into the buffer + * \param[in] comm The communicator that will be used. + * \return The size of the buffer in bytes. + */ int - t8_buffer_size (const int num_data, sc_MPI_Comm comm) + buffer_size (const int num_data, sc_MPI_Comm comm) { - const int single_size = this->t8_data_size (comm); + const int single_size = this->data_size (comm); int num_data_size; int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &num_data_size); SC_CHECK_MPI (mpiret); return num_data_size + num_data * single_size; } + /** + * Pack a vector of items into a buffer. + * + * \param[in] data A vector of items to pack + * \param[in, out] buffer A vector that will be filled with the packed data. + * \param[in] comm The used communicator + */ void - t8_data_pack_vector (std::vector &data, const int num_data, std::vector &buffer, sc_MPI_Comm comm) + data_pack_vector (std::vector &data, std::vector &buffer, sc_MPI_Comm comm) { int pos = 0; - T8_ASSERT (buffer.size () == t8_buffer_size (num_data, comm)); - + T8_ASSERT (buffer.size () == buffer_size (data.size (), comm)); + const int num_data = data.size (); sc_MPI_Pack (&num_data, 1, MPI_INT, buffer.data (), buffer.size (), &pos, comm); for (int idata = 0; idata < num_data; idata++) { - this->t8_data_pack (data[idata], pos, buffer, comm); + this->data_pack (data[idata], pos, buffer, comm); } } + /** + * Unpack a buffer into a vector of items. + * + * \param[in] buffer The input buffer + * \param[in, out] data Vector of type T, that will be filled with the unpacked data. + * \param[in, out] outcount Number of items that were packed + * \param[in] comm The communicator to use. + */ void - t8_data_unpack_vector (std::vector &buffer, std::vector &data, int &outcount, sc_MPI_Comm comm) + data_unpack_vector (std::vector &buffer, std::vector &data, int &outcount, sc_MPI_Comm comm) { int pos = 0; @@ -66,7 +88,7 @@ class t8_data_handler: public t8_single_data_handler { data.resize (outcount); for (int ipack = 0; ipack < outcount; ++ipack) { - this->t8_data_unpack (buffer, pos, data[ipack], comm); + this->data_unpack (buffer, pos, data[ipack], comm); } } }; diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 8f9d015c00..74098ee62e 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -25,6 +25,12 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include +/** + * Templated testing class. Creates enlarged data (original data + a checking integer) and a + * data handler. + * + * @tparam T the type of data + */ template class data_handler_test: public testing::Test { protected: @@ -56,51 +62,66 @@ class data_handler_test: public testing::Test { TYPED_TEST_SUITE_P (data_handler_test); +/** + * Test to pack, send, recv and unpack a single element of type T. + */ TYPED_TEST_P (data_handler_test, single_data) { - std::vector buffer (this->data_handler->t8_buffer_size (1, this->comm)); + /* Send buffer to be filled with the packed data. */ + std::vector buffer (this->data_handler->buffer_size (1, this->comm)); + /* Create enlarged data. */ this->creator->create (1); int pos = 0; - this->data_handler->t8_data_pack (this->creator->large_data[0], pos, buffer, this->comm); - int send_to = (this->mpirank + 1) % this->mpisize; + /* Pack the data into the buffer. */ + this->data_handler->data_pack (this->creator->large_data[0], pos, buffer, this->comm); + /* Send the data in a round robin fashion. */ + int send_to = (this->mpirank + 1) % this->mpisize; int mpiret = sc_MPI_Send (buffer.data (), buffer.size (), sc_MPI_PACKED, (this->mpirank + 1) % this->mpisize, 0, this->comm); SC_CHECK_MPI (mpiret); + /* Compute the rank this rank receives from .*/ int recv_from = (this->mpirank == 0) ? (this->mpisize - 1) : (this->mpirank - 1); sc_MPI_Status status; + /* The first int is the size of all packed items. */ mpiret = sc_MPI_Probe (recv_from, 0, this->comm, &status); SC_CHECK_MPI (mpiret); - int size; mpiret = sc_MPI_Get_count (&status, sc_MPI_PACKED, &size); SC_CHECK_MPI (mpiret); std::vector packed (size); + /* Receive the data. */ pos = 0; mpiret = sc_MPI_Recv (packed.data (), packed.size (), sc_MPI_PACKED, recv_from, pos, this->comm, &status); SC_CHECK_MPI (mpiret); + /* Unpack the data. */ this->recv_data.resize (1); int outcount = 0; pos = 0; - this->data_handler->t8_data_unpack (packed, pos, this->recv_data[0], this->comm); + this->data_handler->data_unpack (packed, pos, this->recv_data[0], this->comm); EXPECT_EQ (this->recv_data[0].data, this->creator->large_data[0].data); EXPECT_EQ (this->recv_data[0].check, this->creator->large_data[0].check); } +/** + * Test to pack, send, recv and unpack a vector of elements of type T. + */ TYPED_TEST_P (data_handler_test, vector_of_data) { + /* Test different sizes. */ for (int num_data = 1; num_data < this->max_num_data; num_data++) { this->creator->create (num_data); - std::vector buffer (this->data_handler->t8_buffer_size (num_data, this->comm)); - this->data_handler->t8_data_pack_vector (this->creator->large_data, num_data, buffer, this->comm); + /* Create send buffer and pack data into it. */ + std::vector buffer (this->data_handler->buffer_size (num_data, this->comm)); + this->data_handler->data_pack_vector (this->creator->large_data, buffer, this->comm); int mpiret = sc_MPI_Send (buffer.data (), buffer.size (), sc_MPI_PACKED, (this->mpirank + 1) % this->mpisize, 0, this->comm); @@ -122,7 +143,7 @@ TYPED_TEST_P (data_handler_test, vector_of_data) SC_CHECK_MPI (mpiret); int outcount = 0; - this->data_handler->t8_data_unpack_vector (packed, this->recv_data, outcount, this->comm); + this->data_handler->data_unpack_vector (packed, this->recv_data, outcount, this->comm); EXPECT_EQ (outcount, num_data); for (int idata = 0; idata < num_data; idata++) { EXPECT_EQ (this->recv_data[idata].data, this->creator->large_data[idata].data); From c985b9e0386fcc476381607c75c5e955dd9a5726 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Tue, 20 Aug 2024 09:36:46 +0200 Subject: [PATCH 08/81] Move single-pack implementation into seperate files. --- src/t8_data/t8_data_handler_base.hxx | 54 ++++++++++ .../t8_data_packs/t8_enlarged_stdtypes.hxx | 98 +++++++++++++++++++ src/t8_data/t8_data_packs/t8_packed_types.hxx | 28 ++++++ 3 files changed, 180 insertions(+) create mode 100644 src/t8_data/t8_data_handler_base.hxx create mode 100644 src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx create mode 100644 src/t8_data/t8_data_packs/t8_packed_types.hxx diff --git a/src/t8_data/t8_data_handler_base.hxx b/src/t8_data/t8_data_handler_base.hxx new file mode 100644 index 0000000000..3d62e6defd --- /dev/null +++ b/src/t8_data/t8_data_handler_base.hxx @@ -0,0 +1,54 @@ +/* +This file is part of t8code. +t8code is a C library to manage a collection (a forest) of multiple +connected adaptive space-trees of general element classes in parallel. + +Copyright (C) 2024 the developers + +t8code 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 2 of the License, or +(at your option) any later version. + +t8code 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 t8code; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef T8_DATA_HANDLER_BASE +#define T8_DATA_HANDLER_BASE + +#include +#include + +template +class t8_single_data_handler { + public: + int + data_size (sc_MPI_Comm comm); + + /** + * Overwrite this routine to describe how data of type T should be packed + * + * \param[in] data Data to be packed via MPI_Pack + * \return the size of the packed data in number of bytes. + */ + void + data_pack (T &data, int &pos, std::vector &buffer, sc_MPI_Comm comm); + + /** + * Overwrite this routine to describe how data of type T should be unpacked + * + * \param packed_data A void-pointer to the packed Data + * \return T* the unpacked data. + */ + void + data_unpack (std::vector &buffer, int &pos, T &data, sc_MPI_Comm comm); +}; + +#endif /* T8_DATA_HANDLER_BASE */ diff --git a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx new file mode 100644 index 0000000000..669ffb5426 --- /dev/null +++ b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx @@ -0,0 +1,98 @@ +/* +This file is part of t8code. +t8code is a C library to manage a collection (a forest) of multiple +connected adaptive space-trees of general element classes in parallel. + +Copyright (C) 2024 the developers + +t8code 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 2 of the License, or +(at your option) any later version. + +t8code 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 t8code; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef T8_ENLARGED_INT +#define T8_ENLARGED_INT + +#include +#include + +template <> +class t8_single_data_handler> { + public: + int + data_size (sc_MPI_Comm comm) + { + int size; + const int mpiret = sc_MPI_Pack_size (2, sc_MPI_INT, comm, &size); + SC_CHECK_MPI (mpiret); + return size; + } + + void + data_pack (enlarged_data data, int &pos, std::vector &buffer, sc_MPI_Comm comm) + { + int mpiret = sc_MPI_Pack (&data.data, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + SC_CHECK_MPI (mpiret); + + mpiret = sc_MPI_Pack (&data.data, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + SC_CHECK_MPI (mpiret); + } + + void + data_unpack (std::vector &buffer, int &pos, enlarged_data &data, sc_MPI_Comm comm) + { + int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &data.data, 1, sc_MPI_INT, comm); + SC_CHECK_MPI (mpiret); + + mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &data.check, 1, sc_MPI_INT, comm); + SC_CHECK_MPI (mpiret); + } +}; + +template <> +class t8_single_data_handler> { + public: + int + data_size (sc_MPI_Comm comm) + { + int int_size; + int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &int_size); + SC_CHECK_MPI (mpiret); + int double_size; + mpiret = sc_MPI_Pack_size (1, sc_MPI_DOUBLE, comm, &double_size); + SC_CHECK_MPI (mpiret); + return int_size + double_size; + } + + void + data_pack (enlarged_data data, int &pos, std::vector &buffer, sc_MPI_Comm comm) + { + int mpiret = sc_MPI_Pack (&data.data, 1, sc_MPI_DOUBLE, buffer.data (), buffer.size (), &pos, comm); + SC_CHECK_MPI (mpiret); + + mpiret = sc_MPI_Pack (&data.data, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + SC_CHECK_MPI (mpiret); + } + + void + data_unpack (std::vector &buffer, int &pos, enlarged_data &data, sc_MPI_Comm comm) + { + int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &data.data, 1, sc_MPI_DOUBLE, comm); + SC_CHECK_MPI (mpiret); + + mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &data.check, 1, sc_MPI_INT, comm); + SC_CHECK_MPI (mpiret); + } +}; + +#endif /* T8_ENLARGED_INT */ diff --git a/src/t8_data/t8_data_packs/t8_packed_types.hxx b/src/t8_data/t8_data_packs/t8_packed_types.hxx new file mode 100644 index 0000000000..05f76544d7 --- /dev/null +++ b/src/t8_data/t8_data_packs/t8_packed_types.hxx @@ -0,0 +1,28 @@ +/* +This file is part of t8code. +t8code is a C library to manage a collection (a forest) of multiple +connected adaptive space-trees of general element classes in parallel. + +Copyright (C) 2024 the developers + +t8code 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 2 of the License, or +(at your option) any later version. + +t8code 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 t8code; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef T8_PACKED_TYPES +#define T8_PACKED_TYPES + +#include + +#endif /* T8_PACKED_TYPES */ From 3d63d86d346957a76244616339142186446a6231 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Tue, 20 Aug 2024 10:01:20 +0200 Subject: [PATCH 09/81] Split tests into packing-tests and a send_recv-test --- src/t8_data/t8_data_handler.hxx | 31 ++++++++++ test/t8_data/t8_gtest_data_handler.cxx | 80 ++++++++++++-------------- 2 files changed, 67 insertions(+), 44 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 9864631658..fd51d9afa0 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -91,6 +91,37 @@ class t8_data_handler: public t8_single_data_handler { this->data_unpack (buffer, pos, data[ipack], comm); } } + + int + data_send (std::vector &data, int dest, int tag, sc_MPI_Comm comm) + { + std::vector buffer (buffer_size (data.size (), comm)); + data_pack_vector (data, buffer, comm); + + const int mpiret = sc_MPI_Send (buffer.data (), buffer.size (), sc_MPI_PACKED, dest, tag, comm); + + return mpiret; + } + + int + data_recv (std::vector &data, int source, int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) + { + int mpiret = sc_MPI_Probe (source, tag, comm, status); + SC_CHECK_MPI (mpiret); + + int size; + mpiret = sc_MPI_Get_count (status, sc_MPI_PACKED, &size); + SC_CHECK_MPI (mpiret); + + std::vector buffer (size); + int pos = 0; + mpiret = sc_MPI_Recv (buffer.data (), buffer.size (), sc_MPI_PACKED, source, pos, comm, status); + SC_CHECK_MPI (mpiret); + + data_unpack_vector (buffer, data, outcount, comm); + + return mpiret; + } }; #endif /* T8_DATA_HANDLER_HXX */ diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 74098ee62e..8ff07b7182 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -63,7 +63,7 @@ class data_handler_test: public testing::Test { TYPED_TEST_SUITE_P (data_handler_test); /** - * Test to pack, send, recv and unpack a single element of type T. + * Test to pack and unpack a single element of type T. */ TYPED_TEST_P (data_handler_test, single_data) { @@ -77,41 +77,21 @@ TYPED_TEST_P (data_handler_test, single_data) /* Pack the data into the buffer. */ this->data_handler->data_pack (this->creator->large_data[0], pos, buffer, this->comm); - /* Send the data in a round robin fashion. */ - int send_to = (this->mpirank + 1) % this->mpisize; - int mpiret - = sc_MPI_Send (buffer.data (), buffer.size (), sc_MPI_PACKED, (this->mpirank + 1) % this->mpisize, 0, this->comm); - SC_CHECK_MPI (mpiret); - /* Compute the rank this rank receives from .*/ int recv_from = (this->mpirank == 0) ? (this->mpisize - 1) : (this->mpirank - 1); sc_MPI_Status status; - /* The first int is the size of all packed items. */ - mpiret = sc_MPI_Probe (recv_from, 0, this->comm, &status); - SC_CHECK_MPI (mpiret); - int size; - mpiret = sc_MPI_Get_count (&status, sc_MPI_PACKED, &size); - SC_CHECK_MPI (mpiret); - std::vector packed (size); - - /* Receive the data. */ - pos = 0; - mpiret = sc_MPI_Recv (packed.data (), packed.size (), sc_MPI_PACKED, recv_from, pos, this->comm, &status); - SC_CHECK_MPI (mpiret); - /* Unpack the data. */ this->recv_data.resize (1); - int outcount = 0; pos = 0; - this->data_handler->data_unpack (packed, pos, this->recv_data[0], this->comm); + this->data_handler->data_unpack (buffer, pos, this->recv_data[0], this->comm); EXPECT_EQ (this->recv_data[0].data, this->creator->large_data[0].data); EXPECT_EQ (this->recv_data[0].check, this->creator->large_data[0].check); } /** - * Test to pack, send, recv and unpack a vector of elements of type T. + * Test to pack and unpack a vector of elements of type T. */ TYPED_TEST_P (data_handler_test, vector_of_data) { @@ -123,27 +103,8 @@ TYPED_TEST_P (data_handler_test, vector_of_data) std::vector buffer (this->data_handler->buffer_size (num_data, this->comm)); this->data_handler->data_pack_vector (this->creator->large_data, buffer, this->comm); - int mpiret - = sc_MPI_Send (buffer.data (), buffer.size (), sc_MPI_PACKED, (this->mpirank + 1) % this->mpisize, 0, this->comm); - SC_CHECK_MPI (mpiret); - - sc_MPI_Status status; - - int recv_from = (this->mpirank == 0) ? (this->mpisize - 1) : (this->mpirank - 1); - - mpiret = sc_MPI_Probe (recv_from, 0, this->comm, &status); - SC_CHECK_MPI (mpiret); - - int size; - mpiret = sc_MPI_Get_count (&status, sc_MPI_PACKED, &size); - SC_CHECK_MPI (mpiret); - std::vector packed (size); - - sc_MPI_Recv (packed.data (), packed.size (), sc_MPI_PACKED, recv_from, 0, this->comm, &status); - SC_CHECK_MPI (mpiret); - int outcount = 0; - this->data_handler->data_unpack_vector (packed, this->recv_data, outcount, this->comm); + this->data_handler->data_unpack_vector (buffer, this->recv_data, outcount, this->comm); EXPECT_EQ (outcount, num_data); for (int idata = 0; idata < num_data; idata++) { EXPECT_EQ (this->recv_data[idata].data, this->creator->large_data[idata].data); @@ -152,7 +113,38 @@ TYPED_TEST_P (data_handler_test, vector_of_data) } } -REGISTER_TYPED_TEST_SUITE_P (data_handler_test, single_data, vector_of_data); +/** + * Use the send and receive routines for packed data. + */ +TYPED_TEST_P (data_handler_test, send_recv) +{ + /* Create the data. */ + this->creator->create (this->max_num_data); + + /* Compute the rank this rank sends to. We send in a round-robin fashion */ + int send_to = (this->mpirank + 1) % this->mpisize; + + /* Pack and send the data. */ + int mpiret = this->data_handler->data_send (this->creator->large_data, send_to, 0, this->comm); + SC_CHECK_MPI (mpiret); + + /* Compute the rank we this rank receives from. */ + int recv_from = (this->mpirank == 0) ? (this->mpisize - 1) : (this->mpirank - 1); + + /* Receive and unpack the data. */ + sc_MPI_Status status; + int outcount; + mpiret = this->data_handler->data_recv (this->recv_data, recv_from, 0, this->comm, &status, outcount); + SC_CHECK_MPI (mpiret); + + EXPECT_EQ (outcount, this->max_num_data); + for (int idata = 0; idata < this->max_num_data; idata++) { + EXPECT_EQ (this->recv_data[idata].data, this->creator->large_data[idata].data); + EXPECT_EQ (this->recv_data[idata].check, this->creator->large_data[idata].check); + } +} + +REGISTER_TYPED_TEST_SUITE_P (data_handler_test, single_data, vector_of_data, send_recv); using DataTypes = ::testing::Types; From 05e4984901e7223afb431ff4f5650275da654651 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Tue, 20 Aug 2024 11:01:23 +0200 Subject: [PATCH 10/81] code simplification --- src/t8_data/t8_data_handler.hxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index fd51d9afa0..d6e791ec41 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -63,8 +63,8 @@ class t8_data_handler: public t8_single_data_handler { const int num_data = data.size (); sc_MPI_Pack (&num_data, 1, MPI_INT, buffer.data (), buffer.size (), &pos, comm); - for (int idata = 0; idata < num_data; idata++) { - this->data_pack (data[idata], pos, buffer, comm); + for (T item : data) { + this->data_pack (item, pos, buffer, comm); } } @@ -87,8 +87,8 @@ class t8_data_handler: public t8_single_data_handler { data.resize (outcount); - for (int ipack = 0; ipack < outcount; ++ipack) { - this->data_unpack (buffer, pos, data[ipack], comm); + for (T item : data) { + this->data_unpack (buffer, pos, item, comm); } } From d28dc55349c8e927e6ee00b0af931065497391f0 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Tue, 20 Aug 2024 11:28:15 +0200 Subject: [PATCH 11/81] Documentation --- src/t8_data/t8_data_handler.hxx | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index d6e791ec41..ee21c99e8f 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -92,6 +92,16 @@ class t8_data_handler: public t8_single_data_handler { } } + /** + * Wrapper around a \a data_pack_vector and an sc_MPI_Send. + * Packs the \a data and sends it to rank \a dest using \a tag via \a comm + * + * \param[in] data The data to pack and send + * \param[in] dest The rank we send to. + * \param[in] tag The tag to use during communication + * \param[in] comm The communicator to use. + * \return The result of the mpi-communication + */ int data_send (std::vector &data, int dest, int tag, sc_MPI_Comm comm) { @@ -103,6 +113,18 @@ class t8_data_handler: public t8_single_data_handler { return mpiret; } + /** + * Wrapper around an \a sc_MPI_Recv and \a data_unpack. + * Receives and unpackes data coming from \a source. + * + * \param[in, out] data The output buffer. Will be filled with the unpacked data. + * \param[in] source The rank we receive data from + * \param[in] tag The tag used during communication + * \param[in] comm The communicator to use. + * \param[in] status Status of the MPI-communication + * \param[in, out] outcount After execution it is the number of items of type \a T received. + * \return The result of the mpi communication. + */ int data_recv (std::vector &data, int source, int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) { From 5376ef7b94c9f09b93802b1e530c98da094ed4f8 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Tue, 20 Aug 2024 11:42:21 +0200 Subject: [PATCH 12/81] documentation --- src/t8_data/t8_data_handler.hxx | 1 + src/t8_data/t8_data_handler_base.hxx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index ee21c99e8f..88c9670db7 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -81,6 +81,7 @@ class t8_data_handler: public t8_single_data_handler { { int pos = 0; + /* Get the number of items we received. */ int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &outcount, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); T8_ASSERT (outcount >= 0); diff --git a/src/t8_data/t8_data_handler_base.hxx b/src/t8_data/t8_data_handler_base.hxx index 3d62e6defd..7699d491e9 100644 --- a/src/t8_data/t8_data_handler_base.hxx +++ b/src/t8_data/t8_data_handler_base.hxx @@ -29,7 +29,7 @@ along with t8code; if not, write to the Free Software Foundation, Inc., template class t8_single_data_handler { public: - int + inline int data_size (sc_MPI_Comm comm); /** From 0c233a2358a24f9831ee16dee699a9a8742df52d Mon Sep 17 00:00:00 2001 From: David Knapp Date: Tue, 20 Aug 2024 13:34:29 +0200 Subject: [PATCH 13/81] fix memory leak --- test/t8_data/t8_gtest_data_handler.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 8ff07b7182..bb4327875e 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -49,6 +49,8 @@ class data_handler_test: public testing::Test { void TearDown () override { + delete (data_handler); + delete (creator); } t8_data_handler> *data_handler; From d37eca1341d14fef5c1a4c97d33783b18ff7d766 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 23 Aug 2024 11:35:34 +0200 Subject: [PATCH 14/81] Fix non-mpi configuration --- src/t8_data/t8_data_handler.hxx | 14 ++++++++++++-- test/t8_data/t8_data_handler_specs.cxx | 6 ++---- test/t8_data/t8_data_handler_specs.hxx | 11 +++++++++-- test/t8_data/t8_gtest_data_handler.cxx | 19 +++++++++++-------- 4 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 88c9670db7..d99fcb047f 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -59,9 +59,9 @@ class t8_data_handler: public t8_single_data_handler { data_pack_vector (std::vector &data, std::vector &buffer, sc_MPI_Comm comm) { int pos = 0; - T8_ASSERT (buffer.size () == buffer_size (data.size (), comm)); + T8_ASSERT (buffer.size () == (long unsigned int) buffer_size (data.size (), comm)); const int num_data = data.size (); - sc_MPI_Pack (&num_data, 1, MPI_INT, buffer.data (), buffer.size (), &pos, comm); + sc_MPI_Pack (&num_data, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); for (T item : data) { this->data_pack (item, pos, buffer, comm); @@ -106,12 +106,17 @@ class t8_data_handler: public t8_single_data_handler { int data_send (std::vector &data, int dest, int tag, sc_MPI_Comm comm) { +#if T8_ENABLE_MPI std::vector buffer (buffer_size (data.size (), comm)); data_pack_vector (data, buffer, comm); const int mpiret = sc_MPI_Send (buffer.data (), buffer.size (), sc_MPI_PACKED, dest, tag, comm); return mpiret; +#else + t8_infof ("Data send only available when configured with --enable-mpi\n"); + return sc_MPI_ERR_OTHER; +#endif } /** @@ -129,6 +134,7 @@ class t8_data_handler: public t8_single_data_handler { int data_recv (std::vector &data, int source, int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) { +#if T8_ENABLE_MPI int mpiret = sc_MPI_Probe (source, tag, comm, status); SC_CHECK_MPI (mpiret); @@ -144,6 +150,10 @@ class t8_data_handler: public t8_single_data_handler { data_unpack_vector (buffer, data, outcount, comm); return mpiret; +#else + t8_infof ("Data recv only available when configured with --enable-mpi\n"); + return sc_MPI_ERR_OTHER; +#endif } }; diff --git a/test/t8_data/t8_data_handler_specs.cxx b/test/t8_data/t8_data_handler_specs.cxx index f658153751..e5356ca537 100644 --- a/test/t8_data/t8_data_handler_specs.cxx +++ b/test/t8_data/t8_data_handler_specs.cxx @@ -30,8 +30,7 @@ data_creator>::create (const int num_data) large_data.resize (num_data); int idata = 0; for (enlarged_data item : large_data) { - item.data = 42; - item.check = idata++; + item.set (42, idata++); } } @@ -42,7 +41,6 @@ data_creator>::create (const int num_data) large_data.resize (num_data); int idata = 0; for (enlarged_data item : large_data) { - item.data = 42.42; - item.check = idata++; + item.set (42.42, idata++); } } diff --git a/test/t8_data/t8_data_handler_specs.hxx b/test/t8_data/t8_data_handler_specs.hxx index baf5c0c962..23dfd39baf 100644 --- a/test/t8_data/t8_data_handler_specs.hxx +++ b/test/t8_data/t8_data_handler_specs.hxx @@ -27,8 +27,15 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include template -struct enlarged_data -{ +class enlarged_data { + public: + void + set (T data, int check) + { + data = data; + check = check; + } + T data; // original data int check; // additional data to check against }; diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index bb4327875e..2d2cf2c2b7 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -67,7 +67,7 @@ TYPED_TEST_SUITE_P (data_handler_test); /** * Test to pack and unpack a single element of type T. */ -TYPED_TEST_P (data_handler_test, single_data) +TYPED_TEST_P (data_handler_test, pack_unpack_single_data) { /* Send buffer to be filled with the packed data. */ std::vector buffer (this->data_handler->buffer_size (1, this->comm)); @@ -79,10 +79,6 @@ TYPED_TEST_P (data_handler_test, single_data) /* Pack the data into the buffer. */ this->data_handler->data_pack (this->creator->large_data[0], pos, buffer, this->comm); - /* Compute the rank this rank receives from .*/ - int recv_from = (this->mpirank == 0) ? (this->mpisize - 1) : (this->mpirank - 1); - sc_MPI_Status status; - /* Unpack the data. */ this->recv_data.resize (1); pos = 0; @@ -95,7 +91,7 @@ TYPED_TEST_P (data_handler_test, single_data) /** * Test to pack and unpack a vector of elements of type T. */ -TYPED_TEST_P (data_handler_test, vector_of_data) +TYPED_TEST_P (data_handler_test, pack_unpack_vector_of_data) { /* Test different sizes. */ for (int num_data = 1; num_data < this->max_num_data; num_data++) { @@ -128,7 +124,11 @@ TYPED_TEST_P (data_handler_test, send_recv) /* Pack and send the data. */ int mpiret = this->data_handler->data_send (this->creator->large_data, send_to, 0, this->comm); +#if T8_ENABLE_MPI SC_CHECK_MPI (mpiret); +#else + EXPECT_EQ (mpiret, sc_MPI_ERR_OTHER); +#endif /* Compute the rank we this rank receives from. */ int recv_from = (this->mpirank == 0) ? (this->mpisize - 1) : (this->mpirank - 1); @@ -137,16 +137,19 @@ TYPED_TEST_P (data_handler_test, send_recv) sc_MPI_Status status; int outcount; mpiret = this->data_handler->data_recv (this->recv_data, recv_from, 0, this->comm, &status, outcount); +#if T8_ENABLE_MPI SC_CHECK_MPI (mpiret); - EXPECT_EQ (outcount, this->max_num_data); for (int idata = 0; idata < this->max_num_data; idata++) { EXPECT_EQ (this->recv_data[idata].data, this->creator->large_data[idata].data); EXPECT_EQ (this->recv_data[idata].check, this->creator->large_data[idata].check); } +#else + EXPECT_EQ (mpiret, sc_MPI_ERR_OTHER); +#endif } -REGISTER_TYPED_TEST_SUITE_P (data_handler_test, single_data, vector_of_data, send_recv); +REGISTER_TYPED_TEST_SUITE_P (data_handler_test, pack_unpack_single_data, pack_unpack_vector_of_data, send_recv); using DataTypes = ::testing::Types; From 060e173a957e3e10dfd229e7c360b4bdf022bb38 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 23 Aug 2024 13:34:13 +0200 Subject: [PATCH 15/81] Add allgather and pack and unpack without prefix for the size --- src/t8_data/t8_data_handler.hxx | 62 ++++++++++++++++++- src/t8_data/t8_data_handler_base.hxx | 4 +- .../t8_data_packs/t8_enlarged_stdtypes.hxx | 8 +-- test/t8_data/t8_gtest_data_handler.cxx | 17 ++++- 4 files changed, 82 insertions(+), 9 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index d99fcb047f..2f35ea83d5 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -56,14 +56,30 @@ class t8_data_handler: public t8_single_data_handler { * \param[in] comm The used communicator */ void - data_pack_vector (std::vector &data, std::vector &buffer, sc_MPI_Comm comm) + data_pack_vector (const std::vector &data, std::vector &buffer, sc_MPI_Comm comm) { int pos = 0; T8_ASSERT (buffer.size () == (long unsigned int) buffer_size (data.size (), comm)); const int num_data = data.size (); sc_MPI_Pack (&num_data, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); - for (T item : data) { + for (const T item : data) { + this->data_pack (item, pos, buffer, comm); + } + } + + /** + * Pack a vector of items into a buffer. + * + * \param[in] data A vector of items to pack + * \param[in, out] buffer A vector that will be filled with the packed data. + * \param[in] comm The used communicator + */ + void + data_pack_vector_no_size (const std::vector &data, std::vector &buffer, sc_MPI_Comm comm) + { + int pos = 0; + for (const T item : data) { this->data_pack (item, pos, buffer, comm); } } @@ -93,6 +109,24 @@ class t8_data_handler: public t8_single_data_handler { } } + /** + * Unpack a buffer into a vector of items. + * + * \param[in] buffer The input buffer + * \param[in, out] data Vector of type T, that will be filled with the unpacked data. The vector is already + * allocated to the proper size. + * \param[in] comm The communicator to use. + */ + void + data_unpack_vector_no_size (const std::vector &buffer, std::vector &data, sc_MPI_Comm comm) + { + int pos = 0; + + for (T item : data) { + this->data_unpack (buffer, pos, item, comm); + } + } + /** * Wrapper around a \a data_pack_vector and an sc_MPI_Send. * Packs the \a data and sends it to rank \a dest using \a tag via \a comm @@ -155,6 +189,30 @@ class t8_data_handler: public t8_single_data_handler { return sc_MPI_ERR_OTHER; #endif } + + int + allgather (const std::vector &send, std::vector &recv, sc_MPI_Comm comm) + { + const int bsize = buffer_size (send.size (), comm); + std::vector buffer (bsize); + data_pack_vector_no_size (send, buffer, comm); + + int mpisize; + int mpiret = sc_MPI_Comm_size (comm, &mpisize); + SC_CHECK_MPI (mpiret); + + const int recv_size = mpisize * bsize; + std::vector recv_buffer (recv_size); + mpiret = sc_MPI_Allgather (buffer.data (), buffer.size (), sc_MPI_PACKED, recv_buffer.data (), buffer.size (), + sc_MPI_PACKED, comm); + SC_CHECK_MPI (mpiret); + + recv.resize (send.size () * mpisize); + + data_unpack_vector_no_size (recv_buffer, recv, comm); + + return mpiret; + } }; #endif /* T8_DATA_HANDLER_HXX */ diff --git a/src/t8_data/t8_data_handler_base.hxx b/src/t8_data/t8_data_handler_base.hxx index 7699d491e9..b8f55ab2e8 100644 --- a/src/t8_data/t8_data_handler_base.hxx +++ b/src/t8_data/t8_data_handler_base.hxx @@ -39,7 +39,7 @@ class t8_single_data_handler { * \return the size of the packed data in number of bytes. */ void - data_pack (T &data, int &pos, std::vector &buffer, sc_MPI_Comm comm); + data_pack (const T &data, int &pos, std::vector &buffer, sc_MPI_Comm comm); /** * Overwrite this routine to describe how data of type T should be unpacked @@ -48,7 +48,7 @@ class t8_single_data_handler { * \return T* the unpacked data. */ void - data_unpack (std::vector &buffer, int &pos, T &data, sc_MPI_Comm comm); + data_unpack (const std::vector &buffer, int &pos, T &data, sc_MPI_Comm comm); }; #endif /* T8_DATA_HANDLER_BASE */ diff --git a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx index 669ffb5426..359afbb4e8 100644 --- a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx +++ b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx @@ -39,7 +39,7 @@ class t8_single_data_handler> { } void - data_pack (enlarged_data data, int &pos, std::vector &buffer, sc_MPI_Comm comm) + data_pack (const enlarged_data data, int &pos, std::vector &buffer, sc_MPI_Comm comm) { int mpiret = sc_MPI_Pack (&data.data, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); SC_CHECK_MPI (mpiret); @@ -49,7 +49,7 @@ class t8_single_data_handler> { } void - data_unpack (std::vector &buffer, int &pos, enlarged_data &data, sc_MPI_Comm comm) + data_unpack (const std::vector &buffer, int &pos, enlarged_data &data, sc_MPI_Comm comm) { int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &data.data, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); @@ -75,7 +75,7 @@ class t8_single_data_handler> { } void - data_pack (enlarged_data data, int &pos, std::vector &buffer, sc_MPI_Comm comm) + data_pack (const enlarged_data data, int &pos, std::vector &buffer, sc_MPI_Comm comm) { int mpiret = sc_MPI_Pack (&data.data, 1, sc_MPI_DOUBLE, buffer.data (), buffer.size (), &pos, comm); SC_CHECK_MPI (mpiret); @@ -85,7 +85,7 @@ class t8_single_data_handler> { } void - data_unpack (std::vector &buffer, int &pos, enlarged_data &data, sc_MPI_Comm comm) + data_unpack (const std::vector &buffer, int &pos, enlarged_data &data, sc_MPI_Comm comm) { int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &data.data, 1, sc_MPI_DOUBLE, comm); SC_CHECK_MPI (mpiret); diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 2d2cf2c2b7..c970b991c4 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -149,7 +149,22 @@ TYPED_TEST_P (data_handler_test, send_recv) #endif } -REGISTER_TYPED_TEST_SUITE_P (data_handler_test, pack_unpack_single_data, pack_unpack_vector_of_data, send_recv); +TYPED_TEST_P (data_handler_test, allgather) +{ + this->creator->create (this->max_num_data); + + const int mpiret = this->data_handler->allgather (this->creator->large_data, this->recv_data, this->comm); + SC_CHECK_MPI (mpiret); + + const int data_size = this->mpisize * this->max_num_data; + for (int idata = 0; idata < data_size; ++idata) { + EXPECT_EQ (this->recv_data[idata].data, this->creator->large_data[idata % this->max_num_data].data); + EXPECT_EQ (this->recv_data[idata].check, this->creator->large_data[idata % this->max_num_data].check); + } +} + +REGISTER_TYPED_TEST_SUITE_P (data_handler_test, pack_unpack_single_data, pack_unpack_vector_of_data, send_recv, + allgather); using DataTypes = ::testing::Types; From 00e19b4aff89e85cb10569c84578203201ed535f Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 23 Aug 2024 13:55:40 +0200 Subject: [PATCH 16/81] improve interface by better naming-scheme --- src/t8_data/t8_data_handler.hxx | 65 ++++++++++++------- src/t8_data/t8_data_handler_base.hxx | 6 +- .../t8_data_packs/t8_enlarged_stdtypes.hxx | 12 ++-- test/t8_data/t8_gtest_data_handler.cxx | 12 ++-- 4 files changed, 56 insertions(+), 39 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 2f35ea83d5..89dca19709 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -41,7 +41,7 @@ class t8_data_handler: public t8_single_data_handler { int buffer_size (const int num_data, sc_MPI_Comm comm) { - const int single_size = this->data_size (comm); + const int single_size = this->size (comm); int num_data_size; int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &num_data_size); SC_CHECK_MPI (mpiret); @@ -49,14 +49,16 @@ class t8_data_handler: public t8_single_data_handler { } /** - * Pack a vector of items into a buffer. + * Pack a vector of items into a buffer. The first integer of the packed data tells how many + * items were packed. * - * \param[in] data A vector of items to pack + * \param[in] data A vector of items to pack * \param[in, out] buffer A vector that will be filled with the packed data. - * \param[in] comm The used communicator + * Adds a prefix-int for the size. + * \param[in] comm The used communicator */ void - data_pack_vector (const std::vector &data, std::vector &buffer, sc_MPI_Comm comm) + pack_vector_prefix (const std::vector &data, std::vector &buffer, sc_MPI_Comm comm) { int pos = 0; T8_ASSERT (buffer.size () == (long unsigned int) buffer_size (data.size (), comm)); @@ -64,28 +66,29 @@ class t8_data_handler: public t8_single_data_handler { sc_MPI_Pack (&num_data, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); for (const T item : data) { - this->data_pack (item, pos, buffer, comm); + this->pack (item, pos, buffer, comm); } } /** - * Pack a vector of items into a buffer. + * Pack a vector of items into a buffer. In contrast to \a pack_vector_sizeprefix no prefix + * to tell how many items have been packed is used. * * \param[in] data A vector of items to pack - * \param[in, out] buffer A vector that will be filled with the packed data. + * \param[in, out] buffer A vector that will be filled with the packed data. * \param[in] comm The used communicator */ void - data_pack_vector_no_size (const std::vector &data, std::vector &buffer, sc_MPI_Comm comm) + pack_vector_no_prefix (const std::vector &data, std::vector &buffer, sc_MPI_Comm comm) { int pos = 0; for (const T item : data) { - this->data_pack (item, pos, buffer, comm); + this->pack (item, pos, buffer, comm); } } /** - * Unpack a buffer into a vector of items. + * Unpack a buffer into a vector of items. Expects a prefix telling how many items of type T have been packed. * * \param[in] buffer The input buffer * \param[in, out] data Vector of type T, that will be filled with the unpacked data. @@ -93,7 +96,7 @@ class t8_data_handler: public t8_single_data_handler { * \param[in] comm The communicator to use. */ void - data_unpack_vector (std::vector &buffer, std::vector &data, int &outcount, sc_MPI_Comm comm) + unpack_vector_prefix (std::vector &buffer, std::vector &data, int &outcount, sc_MPI_Comm comm) { int pos = 0; @@ -105,12 +108,12 @@ class t8_data_handler: public t8_single_data_handler { data.resize (outcount); for (T item : data) { - this->data_unpack (buffer, pos, item, comm); + this->unpack (buffer, pos, item, comm); } } /** - * Unpack a buffer into a vector of items. + * Unpack a buffer into a vector of items. Does not expect a prefix giving any metadata. * * \param[in] buffer The input buffer * \param[in, out] data Vector of type T, that will be filled with the unpacked data. The vector is already @@ -118,12 +121,12 @@ class t8_data_handler: public t8_single_data_handler { * \param[in] comm The communicator to use. */ void - data_unpack_vector_no_size (const std::vector &buffer, std::vector &data, sc_MPI_Comm comm) + unpack_vector_no_prefix (const std::vector &buffer, std::vector &data, sc_MPI_Comm comm) { int pos = 0; for (T item : data) { - this->data_unpack (buffer, pos, item, comm); + this->unpack (buffer, pos, item, comm); } } @@ -138,17 +141,17 @@ class t8_data_handler: public t8_single_data_handler { * \return The result of the mpi-communication */ int - data_send (std::vector &data, int dest, int tag, sc_MPI_Comm comm) + send (std::vector &data, int dest, int tag, sc_MPI_Comm comm) { #if T8_ENABLE_MPI std::vector buffer (buffer_size (data.size (), comm)); - data_pack_vector (data, buffer, comm); + pack_vector_prefix (data, buffer, comm); const int mpiret = sc_MPI_Send (buffer.data (), buffer.size (), sc_MPI_PACKED, dest, tag, comm); return mpiret; #else - t8_infof ("Data send only available when configured with --enable-mpi\n"); + t8_infof ("send only available when configured with --enable-mpi\n"); return sc_MPI_ERR_OTHER; #endif } @@ -166,7 +169,7 @@ class t8_data_handler: public t8_single_data_handler { * \return The result of the mpi communication. */ int - data_recv (std::vector &data, int source, int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) + recv (std::vector &data, int source, int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) { #if T8_ENABLE_MPI int mpiret = sc_MPI_Probe (source, tag, comm, status); @@ -181,21 +184,31 @@ class t8_data_handler: public t8_single_data_handler { mpiret = sc_MPI_Recv (buffer.data (), buffer.size (), sc_MPI_PACKED, source, pos, comm, status); SC_CHECK_MPI (mpiret); - data_unpack_vector (buffer, data, outcount, comm); + unpack_vector_prefix (buffer, data, outcount, comm); return mpiret; #else - t8_infof ("Data recv only available when configured with --enable-mpi\n"); + t8_infof ("recv only available when configured with --enable-mpi\n"); return sc_MPI_ERR_OTHER; #endif } + /** + * Wrapper around an sc_MPI_Allgather, packing the data before sending it and + * unpacking it afterwards. + * + * \param[in] send The data that should be send to all other ranks in the communicator. + * \param[in, out] recv A vector of type \a T to gather the data. Will be set to proper size. + * \param[in] comm The communicator to use. + * \return int + */ int allgather (const std::vector &send, std::vector &recv, sc_MPI_Comm comm) { +#if T8_ENABLE_MPI const int bsize = buffer_size (send.size (), comm); std::vector buffer (bsize); - data_pack_vector_no_size (send, buffer, comm); + pack_vector_no_prefix (send, buffer, comm); int mpisize; int mpiret = sc_MPI_Comm_size (comm, &mpisize); @@ -209,9 +222,13 @@ class t8_data_handler: public t8_single_data_handler { recv.resize (send.size () * mpisize); - data_unpack_vector_no_size (recv_buffer, recv, comm); + unpack_vector_no_prefix (recv_buffer, recv, comm); return mpiret; +#else + t8_infof ("Allgather only available when configured with --enable-mpi\n"); + return sc_MPI_ERR_OTHER; +#endif } }; diff --git a/src/t8_data/t8_data_handler_base.hxx b/src/t8_data/t8_data_handler_base.hxx index b8f55ab2e8..3adc6f5df3 100644 --- a/src/t8_data/t8_data_handler_base.hxx +++ b/src/t8_data/t8_data_handler_base.hxx @@ -30,7 +30,7 @@ template class t8_single_data_handler { public: inline int - data_size (sc_MPI_Comm comm); + size (sc_MPI_Comm comm); /** * Overwrite this routine to describe how data of type T should be packed @@ -39,7 +39,7 @@ class t8_single_data_handler { * \return the size of the packed data in number of bytes. */ void - data_pack (const T &data, int &pos, std::vector &buffer, sc_MPI_Comm comm); + pack (const T &data, int &pos, std::vector &buffer, sc_MPI_Comm comm); /** * Overwrite this routine to describe how data of type T should be unpacked @@ -48,7 +48,7 @@ class t8_single_data_handler { * \return T* the unpacked data. */ void - data_unpack (const std::vector &buffer, int &pos, T &data, sc_MPI_Comm comm); + unpack (const std::vector &buffer, int &pos, T &data, sc_MPI_Comm comm); }; #endif /* T8_DATA_HANDLER_BASE */ diff --git a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx index 359afbb4e8..10b5114407 100644 --- a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx +++ b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx @@ -30,7 +30,7 @@ template <> class t8_single_data_handler> { public: int - data_size (sc_MPI_Comm comm) + size (sc_MPI_Comm comm) { int size; const int mpiret = sc_MPI_Pack_size (2, sc_MPI_INT, comm, &size); @@ -39,7 +39,7 @@ class t8_single_data_handler> { } void - data_pack (const enlarged_data data, int &pos, std::vector &buffer, sc_MPI_Comm comm) + pack (const enlarged_data data, int &pos, std::vector &buffer, sc_MPI_Comm comm) { int mpiret = sc_MPI_Pack (&data.data, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); SC_CHECK_MPI (mpiret); @@ -49,7 +49,7 @@ class t8_single_data_handler> { } void - data_unpack (const std::vector &buffer, int &pos, enlarged_data &data, sc_MPI_Comm comm) + unpack (const std::vector &buffer, int &pos, enlarged_data &data, sc_MPI_Comm comm) { int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &data.data, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); @@ -63,7 +63,7 @@ template <> class t8_single_data_handler> { public: int - data_size (sc_MPI_Comm comm) + size (sc_MPI_Comm comm) { int int_size; int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &int_size); @@ -75,7 +75,7 @@ class t8_single_data_handler> { } void - data_pack (const enlarged_data data, int &pos, std::vector &buffer, sc_MPI_Comm comm) + pack (const enlarged_data data, int &pos, std::vector &buffer, sc_MPI_Comm comm) { int mpiret = sc_MPI_Pack (&data.data, 1, sc_MPI_DOUBLE, buffer.data (), buffer.size (), &pos, comm); SC_CHECK_MPI (mpiret); @@ -85,7 +85,7 @@ class t8_single_data_handler> { } void - data_unpack (const std::vector &buffer, int &pos, enlarged_data &data, sc_MPI_Comm comm) + unpack (const std::vector &buffer, int &pos, enlarged_data &data, sc_MPI_Comm comm) { int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &data.data, 1, sc_MPI_DOUBLE, comm); SC_CHECK_MPI (mpiret); diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index c970b991c4..086f22d76d 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -77,12 +77,12 @@ TYPED_TEST_P (data_handler_test, pack_unpack_single_data) int pos = 0; /* Pack the data into the buffer. */ - this->data_handler->data_pack (this->creator->large_data[0], pos, buffer, this->comm); + this->data_handler->pack (this->creator->large_data[0], pos, buffer, this->comm); /* Unpack the data. */ this->recv_data.resize (1); pos = 0; - this->data_handler->data_unpack (buffer, pos, this->recv_data[0], this->comm); + this->data_handler->unpack (buffer, pos, this->recv_data[0], this->comm); EXPECT_EQ (this->recv_data[0].data, this->creator->large_data[0].data); EXPECT_EQ (this->recv_data[0].check, this->creator->large_data[0].check); @@ -99,10 +99,10 @@ TYPED_TEST_P (data_handler_test, pack_unpack_vector_of_data) /* Create send buffer and pack data into it. */ std::vector buffer (this->data_handler->buffer_size (num_data, this->comm)); - this->data_handler->data_pack_vector (this->creator->large_data, buffer, this->comm); + this->data_handler->pack_vector_prefix (this->creator->large_data, buffer, this->comm); int outcount = 0; - this->data_handler->data_unpack_vector (buffer, this->recv_data, outcount, this->comm); + this->data_handler->unpack_vector_prefix (buffer, this->recv_data, outcount, this->comm); EXPECT_EQ (outcount, num_data); for (int idata = 0; idata < num_data; idata++) { EXPECT_EQ (this->recv_data[idata].data, this->creator->large_data[idata].data); @@ -123,7 +123,7 @@ TYPED_TEST_P (data_handler_test, send_recv) int send_to = (this->mpirank + 1) % this->mpisize; /* Pack and send the data. */ - int mpiret = this->data_handler->data_send (this->creator->large_data, send_to, 0, this->comm); + int mpiret = this->data_handler->send (this->creator->large_data, send_to, 0, this->comm); #if T8_ENABLE_MPI SC_CHECK_MPI (mpiret); #else @@ -136,7 +136,7 @@ TYPED_TEST_P (data_handler_test, send_recv) /* Receive and unpack the data. */ sc_MPI_Status status; int outcount; - mpiret = this->data_handler->data_recv (this->recv_data, recv_from, 0, this->comm, &status, outcount); + mpiret = this->data_handler->recv (this->recv_data, recv_from, 0, this->comm, &status, outcount); #if T8_ENABLE_MPI SC_CHECK_MPI (mpiret); EXPECT_EQ (outcount, this->max_num_data); From e640c3ec8fb7f96b7c071150aa96dd4659fc7c63 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 23 Aug 2024 14:03:07 +0200 Subject: [PATCH 17/81] remove Enable-Mpi-Makros around allgather --- src/t8_data/t8_data_handler.hxx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 89dca19709..02df87a059 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -205,7 +205,6 @@ class t8_data_handler: public t8_single_data_handler { int allgather (const std::vector &send, std::vector &recv, sc_MPI_Comm comm) { -#if T8_ENABLE_MPI const int bsize = buffer_size (send.size (), comm); std::vector buffer (bsize); pack_vector_no_prefix (send, buffer, comm); @@ -225,10 +224,6 @@ class t8_data_handler: public t8_single_data_handler { unpack_vector_no_prefix (recv_buffer, recv, comm); return mpiret; -#else - t8_infof ("Allgather only available when configured with --enable-mpi\n"); - return sc_MPI_ERR_OTHER; -#endif } }; From e4d241396c5f8d53558f127effab25344707cae2 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 23 Aug 2024 15:14:22 +0200 Subject: [PATCH 18/81] add mpi_guards, because sc_MPI_PACKED is not an implemented Datatype --- src/t8_data/t8_data_handler.hxx | 5 +++++ test/t8_data/t8_gtest_data_handler.cxx | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 02df87a059..bdc6ef67d1 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -205,6 +205,7 @@ class t8_data_handler: public t8_single_data_handler { int allgather (const std::vector &send, std::vector &recv, sc_MPI_Comm comm) { +#if T8_ENABLE_MPI const int bsize = buffer_size (send.size (), comm); std::vector buffer (bsize); pack_vector_no_prefix (send, buffer, comm); @@ -224,6 +225,10 @@ class t8_data_handler: public t8_single_data_handler { unpack_vector_no_prefix (recv_buffer, recv, comm); return mpiret; +#else + t8_infof ("recv only available when configured with --enable-mpi\n"); + return sc_MPI_ERR_OTHER; +#endif } }; diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 086f22d76d..0c516b9e95 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -151,9 +151,11 @@ TYPED_TEST_P (data_handler_test, send_recv) TYPED_TEST_P (data_handler_test, allgather) { + this->creator->create (this->max_num_data); const int mpiret = this->data_handler->allgather (this->creator->large_data, this->recv_data, this->comm); +#if T8_ENABLE_MPI SC_CHECK_MPI (mpiret); const int data_size = this->mpisize * this->max_num_data; @@ -161,6 +163,9 @@ TYPED_TEST_P (data_handler_test, allgather) EXPECT_EQ (this->recv_data[idata].data, this->creator->large_data[idata % this->max_num_data].data); EXPECT_EQ (this->recv_data[idata].check, this->creator->large_data[idata % this->max_num_data].check); } +#else + EXPECT_EQ (mpiret, sc_MPI_ERR_OTHER); +#endif } REGISTER_TYPED_TEST_SUITE_P (data_handler_test, pack_unpack_single_data, pack_unpack_vector_of_data, send_recv, From 1a9ecca91a8587652b85efe27d6f98ed3cf99d7e Mon Sep 17 00:00:00 2001 From: David Knapp Date: Thu, 29 Aug 2024 15:34:31 +0200 Subject: [PATCH 19/81] Implementation of a different approach to data handling --- src/t8_data/t8_data_handler.hxx | 119 +++++++++++++------------ src/t8_data/t8_data_handler_base.hxx | 2 +- test/t8_data/t8_gtest_data_handler.cxx | 111 +++++++++++++++-------- 3 files changed, 140 insertions(+), 92 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index bdc6ef67d1..210bb534af 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -28,9 +28,51 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include +class t8_abstract_data_handler { + public: + virtual int + buffer_size (sc_MPI_Comm comm) + = 0; + + virtual void + pack_vector_prefix (std::vector &buffer, sc_MPI_Comm comm) + = 0; + + virtual void + pack_vector_no_prefix (std::vector &buffer, sc_MPI_Comm comm) + = 0; + + virtual void + unpack_vector_prefix (std::vector &buffer, int &outcount, sc_MPI_Comm comm) + = 0; + + virtual void + unpack_vector_no_prefix (std::vector &buffer, sc_MPI_Comm comm) + = 0; + + virtual int + send (int dest, int tag, sc_MPI_Comm comm) + = 0; + + virtual int + recv (int source, int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) + = 0; +}; + template -class t8_data_handler: public t8_single_data_handler { +class t8_data_handler: public t8_abstract_data_handler, public t8_single_data_handler { public: + t8_data_handler (std::vector &data) + { + m_data = data; + }; + + std::vector + get_data () + { + return m_data; + } + /** * Compute the size of a buffer for \a num_data items of type T * @@ -39,13 +81,13 @@ class t8_data_handler: public t8_single_data_handler { * \return The size of the buffer in bytes. */ int - buffer_size (const int num_data, sc_MPI_Comm comm) + buffer_size (sc_MPI_Comm comm) override { const int single_size = this->size (comm); int num_data_size; int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &num_data_size); SC_CHECK_MPI (mpiret); - return num_data_size + num_data * single_size; + return num_data_size + m_data.size () * single_size; } /** @@ -58,14 +100,14 @@ class t8_data_handler: public t8_single_data_handler { * \param[in] comm The used communicator */ void - pack_vector_prefix (const std::vector &data, std::vector &buffer, sc_MPI_Comm comm) + pack_vector_prefix (std::vector &buffer, sc_MPI_Comm comm) override { int pos = 0; - T8_ASSERT (buffer.size () == (long unsigned int) buffer_size (data.size (), comm)); - const int num_data = data.size (); + T8_ASSERT (buffer.size () == (long unsigned int) buffer_size (comm)); + const int num_data = m_data.size (); sc_MPI_Pack (&num_data, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); - for (const T item : data) { + for (const T item : m_data) { this->pack (item, pos, buffer, comm); } } @@ -79,10 +121,10 @@ class t8_data_handler: public t8_single_data_handler { * \param[in] comm The used communicator */ void - pack_vector_no_prefix (const std::vector &data, std::vector &buffer, sc_MPI_Comm comm) + pack_vector_no_prefix (std::vector &buffer, sc_MPI_Comm comm) override { int pos = 0; - for (const T item : data) { + for (const T item : m_data) { this->pack (item, pos, buffer, comm); } } @@ -96,7 +138,7 @@ class t8_data_handler: public t8_single_data_handler { * \param[in] comm The communicator to use. */ void - unpack_vector_prefix (std::vector &buffer, std::vector &data, int &outcount, sc_MPI_Comm comm) + unpack_vector_prefix (std::vector &buffer, int &outcount, sc_MPI_Comm comm) override { int pos = 0; @@ -105,9 +147,9 @@ class t8_data_handler: public t8_single_data_handler { SC_CHECK_MPI (mpiret); T8_ASSERT (outcount >= 0); - data.resize (outcount); + m_data.resize (outcount); - for (T item : data) { + for (T item : m_data) { this->unpack (buffer, pos, item, comm); } } @@ -121,11 +163,11 @@ class t8_data_handler: public t8_single_data_handler { * \param[in] comm The communicator to use. */ void - unpack_vector_no_prefix (const std::vector &buffer, std::vector &data, sc_MPI_Comm comm) + unpack_vector_no_prefix (std::vector &buffer, sc_MPI_Comm comm) override { int pos = 0; - for (T item : data) { + for (T item : m_data) { this->unpack (buffer, pos, item, comm); } } @@ -141,11 +183,11 @@ class t8_data_handler: public t8_single_data_handler { * \return The result of the mpi-communication */ int - send (std::vector &data, int dest, int tag, sc_MPI_Comm comm) + send (int dest, int tag, sc_MPI_Comm comm) override { #if T8_ENABLE_MPI - std::vector buffer (buffer_size (data.size (), comm)); - pack_vector_prefix (data, buffer, comm); + std::vector buffer (buffer_size (comm)); + pack_vector_prefix (buffer, comm); const int mpiret = sc_MPI_Send (buffer.data (), buffer.size (), sc_MPI_PACKED, dest, tag, comm); @@ -169,7 +211,7 @@ class t8_data_handler: public t8_single_data_handler { * \return The result of the mpi communication. */ int - recv (std::vector &data, int source, int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) + recv (int source, int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) override { #if T8_ENABLE_MPI int mpiret = sc_MPI_Probe (source, tag, comm, status); @@ -184,7 +226,7 @@ class t8_data_handler: public t8_single_data_handler { mpiret = sc_MPI_Recv (buffer.data (), buffer.size (), sc_MPI_PACKED, source, pos, comm, status); SC_CHECK_MPI (mpiret); - unpack_vector_prefix (buffer, data, outcount, comm); + unpack_vector_prefix (buffer, outcount, comm); return mpiret; #else @@ -193,43 +235,8 @@ class t8_data_handler: public t8_single_data_handler { #endif } - /** - * Wrapper around an sc_MPI_Allgather, packing the data before sending it and - * unpacking it afterwards. - * - * \param[in] send The data that should be send to all other ranks in the communicator. - * \param[in, out] recv A vector of type \a T to gather the data. Will be set to proper size. - * \param[in] comm The communicator to use. - * \return int - */ - int - allgather (const std::vector &send, std::vector &recv, sc_MPI_Comm comm) - { -#if T8_ENABLE_MPI - const int bsize = buffer_size (send.size (), comm); - std::vector buffer (bsize); - pack_vector_no_prefix (send, buffer, comm); - - int mpisize; - int mpiret = sc_MPI_Comm_size (comm, &mpisize); - SC_CHECK_MPI (mpiret); - - const int recv_size = mpisize * bsize; - std::vector recv_buffer (recv_size); - mpiret = sc_MPI_Allgather (buffer.data (), buffer.size (), sc_MPI_PACKED, recv_buffer.data (), buffer.size (), - sc_MPI_PACKED, comm); - SC_CHECK_MPI (mpiret); - - recv.resize (send.size () * mpisize); - - unpack_vector_no_prefix (recv_buffer, recv, comm); - - return mpiret; -#else - t8_infof ("recv only available when configured with --enable-mpi\n"); - return sc_MPI_ERR_OTHER; -#endif - } + private: + std::vector m_data; }; #endif /* T8_DATA_HANDLER_HXX */ diff --git a/src/t8_data/t8_data_handler_base.hxx b/src/t8_data/t8_data_handler_base.hxx index 3adc6f5df3..94500436f9 100644 --- a/src/t8_data/t8_data_handler_base.hxx +++ b/src/t8_data/t8_data_handler_base.hxx @@ -29,7 +29,7 @@ along with t8code; if not, write to the Free Software Foundation, Inc., template class t8_single_data_handler { public: - inline int + int size (sc_MPI_Comm comm); /** diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 0c516b9e95..e7161366a9 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -41,9 +41,9 @@ class data_handler_test: public testing::Test { SC_CHECK_MPI (mpiret); mpiret = sc_MPI_Comm_size (comm, &mpisize); SC_CHECK_MPI (mpiret); - - data_handler = new t8_data_handler> (); creator = new data_creator> (); + creator->create (max_num_data); + data_handler = new t8_data_handler> (creator->large_data); } void @@ -69,13 +69,12 @@ TYPED_TEST_SUITE_P (data_handler_test); */ TYPED_TEST_P (data_handler_test, pack_unpack_single_data) { - /* Send buffer to be filled with the packed data. */ - std::vector buffer (this->data_handler->buffer_size (1, this->comm)); /* Create enlarged data. */ - this->creator->create (1); int pos = 0; + /* Send buffer to be filled with the packed data. */ + std::vector buffer (this->data_handler->buffer_size (this->comm)); /* Pack the data into the buffer. */ this->data_handler->pack (this->creator->large_data[0], pos, buffer, this->comm); @@ -93,21 +92,19 @@ TYPED_TEST_P (data_handler_test, pack_unpack_single_data) */ TYPED_TEST_P (data_handler_test, pack_unpack_vector_of_data) { - /* Test different sizes. */ - for (int num_data = 1; num_data < this->max_num_data; num_data++) { - this->creator->create (num_data); - - /* Create send buffer and pack data into it. */ - std::vector buffer (this->data_handler->buffer_size (num_data, this->comm)); - this->data_handler->pack_vector_prefix (this->creator->large_data, buffer, this->comm); - - int outcount = 0; - this->data_handler->unpack_vector_prefix (buffer, this->recv_data, outcount, this->comm); - EXPECT_EQ (outcount, num_data); - for (int idata = 0; idata < num_data; idata++) { - EXPECT_EQ (this->recv_data[idata].data, this->creator->large_data[idata].data); - EXPECT_EQ (this->recv_data[idata].check, this->creator->large_data[idata].check); - } + /* Create send buffer and pack data into it. */ + std::vector buffer (this->data_handler->buffer_size (this->comm)); + this->data_handler->pack_vector_prefix (buffer, this->comm); + + int outcount = 0; + this->data_handler->unpack_vector_prefix (buffer, outcount, this->comm); + EXPECT_EQ (outcount, this->max_num_data); + + this->recv_data = this->data_handler->get_data (); + + for (int idata = 0; idata < this->max_num_data; idata++) { + EXPECT_EQ (this->recv_data[idata].data, this->creator->large_data[idata].data); + EXPECT_EQ (this->recv_data[idata].check, this->creator->large_data[idata].check); } } @@ -116,14 +113,11 @@ TYPED_TEST_P (data_handler_test, pack_unpack_vector_of_data) */ TYPED_TEST_P (data_handler_test, send_recv) { - /* Create the data. */ - this->creator->create (this->max_num_data); - /* Compute the rank this rank sends to. We send in a round-robin fashion */ int send_to = (this->mpirank + 1) % this->mpisize; /* Pack and send the data. */ - int mpiret = this->data_handler->send (this->creator->large_data, send_to, 0, this->comm); + int mpiret = this->data_handler->send (send_to, 0, this->comm); #if T8_ENABLE_MPI SC_CHECK_MPI (mpiret); #else @@ -136,7 +130,9 @@ TYPED_TEST_P (data_handler_test, send_recv) /* Receive and unpack the data. */ sc_MPI_Status status; int outcount; - mpiret = this->data_handler->recv (this->recv_data, recv_from, 0, this->comm, &status, outcount); + mpiret = this->data_handler->recv (recv_from, 0, this->comm, &status, outcount); + + this->recv_data = this->data_handler->get_data (); #if T8_ENABLE_MPI SC_CHECK_MPI (mpiret); EXPECT_EQ (outcount, this->max_num_data); @@ -149,27 +145,72 @@ TYPED_TEST_P (data_handler_test, send_recv) #endif } -TYPED_TEST_P (data_handler_test, allgather) +TEST (data_handler_test, multiple_handler) { + sc_MPI_Comm comm = sc_MPI_COMM_WORLD; + int mpirank; + int mpisize; + int mpiret = sc_MPI_Comm_rank (comm, &mpirank); + SC_CHECK_MPI (mpiret); + mpiret = sc_MPI_Comm_size (comm, &mpisize); + SC_CHECK_MPI (mpiret); - this->creator->create (this->max_num_data); + const int num_data = 10; - const int mpiret = this->data_handler->allgather (this->creator->large_data, this->recv_data, this->comm); + std::vector> int_data (num_data); + std::vector> double_data (num_data); + const double fraction = 0.42; + for (int idata = 0; idata < num_data; idata++) { + int_data[idata].data = idata; + int_data[idata].check = mpirank; + double_data[idata].data = (double) idata + fraction; + double_data[idata].check = mpirank; + } + + t8_data_handler> *int_handler = new t8_data_handler> (int_data); + t8_data_handler> *double_handler = new t8_data_handler> (double_data); + + std::vector handler = { int_handler, double_handler }; + + /* Compute the rank this rank sends to. We send in a round-robin fashion */ + int send_to = (mpirank + 1) % mpisize; + int recv_from = (mpirank == 0) ? (mpisize - 1) : (mpirank - 1); + + for (t8_abstract_data_handler *ihandler : handler) { + + mpiret = ihandler->send (send_to, 0, comm); #if T8_ENABLE_MPI - SC_CHECK_MPI (mpiret); + SC_CHECK_MPI (mpiret); +#else + EXPECT_EQ (mpiret, sc_MPI_ERR_OTHER); +#endif + + /* Compute the rank we this rank receives from. */ + + /* Receive and unpack the data. */ + sc_MPI_Status status; + int outcount; + mpiret = ihandler->recv (recv_from, 0, comm, &status, outcount); + } - const int data_size = this->mpisize * this->max_num_data; - for (int idata = 0; idata < data_size; ++idata) { - EXPECT_EQ (this->recv_data[idata].data, this->creator->large_data[idata % this->max_num_data].data); - EXPECT_EQ (this->recv_data[idata].check, this->creator->large_data[idata % this->max_num_data].check); + std::vector> recv_ints = int_handler->get_data (); + std::vector> recv_doubles = double_handler->get_data (); + +#if T8_ENABLE_MPI + SC_CHECK_MPI (mpiret); + for (int idata = 0; idata < num_data; idata++) { + EXPECT_EQ (recv_ints[idata].check, recv_from); + EXPECT_EQ (recv_ints[idata].data, idata); + EXPECT_EQ (recv_doubles[idata].check, recv_from); + EXPECT_NEAR (recv_doubles[idata].data, (double) idata + fraction, T8_PRECISION_EPS); } #else EXPECT_EQ (mpiret, sc_MPI_ERR_OTHER); #endif + /* Pack and send the data. */ } -REGISTER_TYPED_TEST_SUITE_P (data_handler_test, pack_unpack_single_data, pack_unpack_vector_of_data, send_recv, - allgather); +REGISTER_TYPED_TEST_SUITE_P (data_handler_test, pack_unpack_single_data, pack_unpack_vector_of_data, send_recv); using DataTypes = ::testing::Types; From 92b6de653f45f1cd0597ebc0552311f5988b4177 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Thu, 29 Aug 2024 18:43:50 +0200 Subject: [PATCH 20/81] move comments, bugfix --- src/t8_data/t8_data_handler.hxx | 120 ++++++++---------- .../t8_data_packs/t8_enlarged_stdtypes.hxx | 30 +++-- 2 files changed, 76 insertions(+), 74 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 210bb534af..36b95dbdde 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -30,30 +30,84 @@ along with t8code; if not, write to the Free Software Foundation, Inc., class t8_abstract_data_handler { public: + /** + * Compute the size of a buffer for + * + * \param[in] comm The communicator that will be used. + * \return The size of the buffer in bytes. + */ virtual int buffer_size (sc_MPI_Comm comm) = 0; + /** + * Pack a vector of items into a buffer. The first integer of the packed data tells how many + * items were packed. + * + * \param[in, out] buffer A vector that will be filled with the packed data. + * Adds a prefix-int for the size. + * \param[in] comm The used communicator + */ virtual void pack_vector_prefix (std::vector &buffer, sc_MPI_Comm comm) = 0; + /** + * Pack a vector of items into a buffer. In contrast to \a pack_vector_sizeprefix no prefix + * to tell how many items have been packed is used. + * + * \param[in, out] buffer A vector that will be filled with the packed data. + * \param[in] comm The used communicator + */ virtual void pack_vector_no_prefix (std::vector &buffer, sc_MPI_Comm comm) = 0; + /** + * Unpack a buffer into a vector of items. Expects a prefix telling how many items of type T have been packed. + * + * \param[in] buffer The input buffer + * \param[in, out] outcount Number of items that were packed + * \param[in] comm The communicator to use. + */ virtual void unpack_vector_prefix (std::vector &buffer, int &outcount, sc_MPI_Comm comm) = 0; + /** + * Unpack a buffer into a vector of items. Does not expect a prefix giving any metadata. + * + * \param[in] buffer The input buffer + * \param[in] comm The communicator to use. + */ virtual void unpack_vector_no_prefix (std::vector &buffer, sc_MPI_Comm comm) = 0; + /** + * Wrapper around a \a data_pack_vector and an sc_MPI_Send. + * Packs the \a data and sends it to rank \a dest using \a tag via \a comm + * + * \param[in] dest The rank we send to. + * \param[in] tag The tag to use during communication + * \param[in] comm The communicator to use. + * \return The result of the mpi-communication + */ virtual int send (int dest, int tag, sc_MPI_Comm comm) = 0; + /** + * Wrapper around an \a sc_MPI_Recv and \a data_unpack. + * Receives and unpackes data coming from \a source. + * + * \param[in] source The rank we receive data from + * \param[in] tag The tag used during communication + * \param[in] comm The communicator to use. + * \param[in] status Status of the MPI-communication + * \param[in, out] outcount After execution it is the number of items of type \a T received. + * \return The result of the mpi communication. + */ virtual int recv (int source, int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) = 0; @@ -73,13 +127,6 @@ class t8_data_handler: public t8_abstract_data_handler, public t8_single_data_ha return m_data; } - /** - * Compute the size of a buffer for \a num_data items of type T - * - * \param[in] num_data Number of items that will be packed into the buffer - * \param[in] comm The communicator that will be used. - * \return The size of the buffer in bytes. - */ int buffer_size (sc_MPI_Comm comm) override { @@ -90,15 +137,6 @@ class t8_data_handler: public t8_abstract_data_handler, public t8_single_data_ha return num_data_size + m_data.size () * single_size; } - /** - * Pack a vector of items into a buffer. The first integer of the packed data tells how many - * items were packed. - * - * \param[in] data A vector of items to pack - * \param[in, out] buffer A vector that will be filled with the packed data. - * Adds a prefix-int for the size. - * \param[in] comm The used communicator - */ void pack_vector_prefix (std::vector &buffer, sc_MPI_Comm comm) override { @@ -112,14 +150,6 @@ class t8_data_handler: public t8_abstract_data_handler, public t8_single_data_ha } } - /** - * Pack a vector of items into a buffer. In contrast to \a pack_vector_sizeprefix no prefix - * to tell how many items have been packed is used. - * - * \param[in] data A vector of items to pack - * \param[in, out] buffer A vector that will be filled with the packed data. - * \param[in] comm The used communicator - */ void pack_vector_no_prefix (std::vector &buffer, sc_MPI_Comm comm) override { @@ -129,14 +159,6 @@ class t8_data_handler: public t8_abstract_data_handler, public t8_single_data_ha } } - /** - * Unpack a buffer into a vector of items. Expects a prefix telling how many items of type T have been packed. - * - * \param[in] buffer The input buffer - * \param[in, out] data Vector of type T, that will be filled with the unpacked data. - * \param[in, out] outcount Number of items that were packed - * \param[in] comm The communicator to use. - */ void unpack_vector_prefix (std::vector &buffer, int &outcount, sc_MPI_Comm comm) override { @@ -149,39 +171,21 @@ class t8_data_handler: public t8_abstract_data_handler, public t8_single_data_ha m_data.resize (outcount); - for (T item : m_data) { + for (T &item : m_data) { this->unpack (buffer, pos, item, comm); } } - /** - * Unpack a buffer into a vector of items. Does not expect a prefix giving any metadata. - * - * \param[in] buffer The input buffer - * \param[in, out] data Vector of type T, that will be filled with the unpacked data. The vector is already - * allocated to the proper size. - * \param[in] comm The communicator to use. - */ void unpack_vector_no_prefix (std::vector &buffer, sc_MPI_Comm comm) override { int pos = 0; - for (T item : m_data) { + for (T &item : m_data) { this->unpack (buffer, pos, item, comm); } } - /** - * Wrapper around a \a data_pack_vector and an sc_MPI_Send. - * Packs the \a data and sends it to rank \a dest using \a tag via \a comm - * - * \param[in] data The data to pack and send - * \param[in] dest The rank we send to. - * \param[in] tag The tag to use during communication - * \param[in] comm The communicator to use. - * \return The result of the mpi-communication - */ int send (int dest, int tag, sc_MPI_Comm comm) override { @@ -198,18 +202,6 @@ class t8_data_handler: public t8_abstract_data_handler, public t8_single_data_ha #endif } - /** - * Wrapper around an \a sc_MPI_Recv and \a data_unpack. - * Receives and unpackes data coming from \a source. - * - * \param[in, out] data The output buffer. Will be filled with the unpacked data. - * \param[in] source The rank we receive data from - * \param[in] tag The tag used during communication - * \param[in] comm The communicator to use. - * \param[in] status Status of the MPI-communication - * \param[in, out] outcount After execution it is the number of items of type \a T received. - * \return The result of the mpi communication. - */ int recv (int source, int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) override { diff --git a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx index 10b5114407..9c16a8f215 100644 --- a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx +++ b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx @@ -39,23 +39,28 @@ class t8_single_data_handler> { } void - pack (const enlarged_data data, int &pos, std::vector &buffer, sc_MPI_Comm comm) + pack (const enlarged_data &data, int &pos, std::vector &buffer, sc_MPI_Comm comm) { - int mpiret = sc_MPI_Pack (&data.data, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + int mpiret = sc_MPI_Pack (&(data.data), 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); SC_CHECK_MPI (mpiret); - mpiret = sc_MPI_Pack (&data.data, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + mpiret = sc_MPI_Pack (&(data.check), 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); SC_CHECK_MPI (mpiret); } void unpack (const std::vector &buffer, int &pos, enlarged_data &data, sc_MPI_Comm comm) { - int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &data.data, 1, sc_MPI_INT, comm); + int recv_data; + int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &recv_data, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); - mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &data.check, 1, sc_MPI_INT, comm); + int recv_check; + mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &recv_check, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); + + data.data = recv_data; + data.check = recv_check; } }; @@ -75,23 +80,28 @@ class t8_single_data_handler> { } void - pack (const enlarged_data data, int &pos, std::vector &buffer, sc_MPI_Comm comm) + pack (const enlarged_data &data, int &pos, std::vector &buffer, sc_MPI_Comm comm) { - int mpiret = sc_MPI_Pack (&data.data, 1, sc_MPI_DOUBLE, buffer.data (), buffer.size (), &pos, comm); + int mpiret = sc_MPI_Pack (&(data.data), 1, sc_MPI_DOUBLE, buffer.data (), buffer.size (), &pos, comm); SC_CHECK_MPI (mpiret); - mpiret = sc_MPI_Pack (&data.data, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + mpiret = sc_MPI_Pack (&(data.check), 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); SC_CHECK_MPI (mpiret); } void unpack (const std::vector &buffer, int &pos, enlarged_data &data, sc_MPI_Comm comm) { - int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &data.data, 1, sc_MPI_DOUBLE, comm); + double recv_data; + int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &recv_data, 1, sc_MPI_DOUBLE, comm); SC_CHECK_MPI (mpiret); - mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &data.check, 1, sc_MPI_INT, comm); + int recv_check; + mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &recv_check, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); + + data.data = recv_data; + data.check = recv_check; } }; From f66ca3d6cd48ff2656197186b3ac1ab2e31eb05b Mon Sep 17 00:00:00 2001 From: David Knapp Date: Thu, 29 Aug 2024 18:46:04 +0200 Subject: [PATCH 21/81] simplify code --- .../t8_data_packs/t8_enlarged_stdtypes.hxx | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx index 9c16a8f215..1ee32e0a6e 100644 --- a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx +++ b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx @@ -51,16 +51,11 @@ class t8_single_data_handler> { void unpack (const std::vector &buffer, int &pos, enlarged_data &data, sc_MPI_Comm comm) { - int recv_data; - int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &recv_data, 1, sc_MPI_INT, comm); + int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &(data.data), 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); - int recv_check; - mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &recv_check, 1, sc_MPI_INT, comm); + mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &(data.check), 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); - - data.data = recv_data; - data.check = recv_check; } }; @@ -92,16 +87,11 @@ class t8_single_data_handler> { void unpack (const std::vector &buffer, int &pos, enlarged_data &data, sc_MPI_Comm comm) { - double recv_data; - int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &recv_data, 1, sc_MPI_DOUBLE, comm); + int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &(data.data), 1, sc_MPI_DOUBLE, comm); SC_CHECK_MPI (mpiret); - int recv_check; - mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &recv_check, 1, sc_MPI_INT, comm); + mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &(data.check), 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); - - data.data = recv_data; - data.check = recv_check; } }; From a3b1b716da1d63cd1f19321b5f566f7905033322 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Tue, 3 Sep 2024 09:10:49 +0200 Subject: [PATCH 22/81] Start implementing tree dependant data currently failing --- src/t8_data/t8_data_handler.hxx | 110 ++++++++++----- src/t8_data/t8_data_handler_base.hxx | 34 +++-- .../t8_data_packs/t8_enlarged_stdtypes.hxx | 132 +++++++++++++++++- test/t8_data/t8_data_handler_specs.hxx | 7 + test/t8_data/t8_gtest_data_handler.cxx | 111 ++++++++++----- 5 files changed, 310 insertions(+), 84 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 36b95dbdde..362a0168ca 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -26,7 +26,6 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include #include -#include class t8_abstract_data_handler { public: @@ -40,6 +39,10 @@ class t8_abstract_data_handler { buffer_size (sc_MPI_Comm comm) = 0; + virtual int + buffer_size_no_prefix (sc_MPI_Comm comm) + = 0; + /** * Pack a vector of items into a buffer. The first integer of the packed data tells how many * items were packed. @@ -49,7 +52,7 @@ class t8_abstract_data_handler { * \param[in] comm The used communicator */ virtual void - pack_vector_prefix (std::vector &buffer, sc_MPI_Comm comm) + pack_vector_prefix (std::vector &buffer, int &pos, sc_MPI_Comm comm) = 0; /** @@ -60,7 +63,7 @@ class t8_abstract_data_handler { * \param[in] comm The used communicator */ virtual void - pack_vector_no_prefix (std::vector &buffer, sc_MPI_Comm comm) + pack_vector_no_prefix (std::vector &buffer, int &pos, sc_MPI_Comm comm) = 0; /** @@ -71,7 +74,7 @@ class t8_abstract_data_handler { * \param[in] comm The communicator to use. */ virtual void - unpack_vector_prefix (std::vector &buffer, int &outcount, sc_MPI_Comm comm) + unpack_vector_prefix (const std::vector &buffer, int &outcount, int &pos, sc_MPI_Comm comm) = 0; /** @@ -81,7 +84,7 @@ class t8_abstract_data_handler { * \param[in] comm The communicator to use. */ virtual void - unpack_vector_no_prefix (std::vector &buffer, sc_MPI_Comm comm) + unpack_vector_no_prefix (const std::vector &buffer, int &pos, sc_MPI_Comm comm) = 0; /** @@ -94,7 +97,7 @@ class t8_abstract_data_handler { * \return The result of the mpi-communication */ virtual int - send (int dest, int tag, sc_MPI_Comm comm) + send (const int dest, const int tag, sc_MPI_Comm comm) = 0; /** @@ -109,13 +112,27 @@ class t8_abstract_data_handler { * \return The result of the mpi communication. */ virtual int - recv (int source, int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) + recv (const int source, const int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) + = 0; + + virtual int + type () + = 0; + + virtual t8_abstract_data_handler * + new_handler (const int type) = 0; + + virtual ~t8_abstract_data_handler () {}; }; template -class t8_data_handler: public t8_abstract_data_handler, public t8_single_data_handler { +class t8_data_handler: public t8_abstract_data_handler { public: + t8_data_handler () + { + } + t8_data_handler (std::vector &data) { m_data = data; @@ -127,43 +144,48 @@ class t8_data_handler: public t8_abstract_data_handler, public t8_single_data_ha return m_data; } + int + buffer_size_no_prefix (sc_MPI_Comm comm) override + { + int total_size = 0; + for (const T &item : m_data) { + total_size += single_handler.size (item, comm); + } + return total_size; + } + int buffer_size (sc_MPI_Comm comm) override { - const int single_size = this->size (comm); - int num_data_size; - int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &num_data_size); + int total_size = 0; + int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &total_size); SC_CHECK_MPI (mpiret); - return num_data_size + m_data.size () * single_size; + return total_size + buffer_size_no_prefix (comm); } void - pack_vector_prefix (std::vector &buffer, sc_MPI_Comm comm) override + pack_vector_prefix (std::vector &buffer, int &pos, sc_MPI_Comm comm) override { - int pos = 0; T8_ASSERT (buffer.size () == (long unsigned int) buffer_size (comm)); const int num_data = m_data.size (); sc_MPI_Pack (&num_data, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); - for (const T item : m_data) { - this->pack (item, pos, buffer, comm); + for (const T &item : m_data) { + single_handler.pack (item, pos, buffer, comm); } } void - pack_vector_no_prefix (std::vector &buffer, sc_MPI_Comm comm) override + pack_vector_no_prefix (std::vector &buffer, int &pos, sc_MPI_Comm comm) override { - int pos = 0; - for (const T item : m_data) { - this->pack (item, pos, buffer, comm); + for (const T &item : m_data) { + single_handler.pack (item, pos, buffer, comm); } } void - unpack_vector_prefix (std::vector &buffer, int &outcount, sc_MPI_Comm comm) override + unpack_vector_prefix (const std::vector &buffer, int &pos, int &outcount, sc_MPI_Comm comm) override { - int pos = 0; - /* Get the number of items we received. */ int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &outcount, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); @@ -172,26 +194,25 @@ class t8_data_handler: public t8_abstract_data_handler, public t8_single_data_ha m_data.resize (outcount); for (T &item : m_data) { - this->unpack (buffer, pos, item, comm); + single_handler.unpack (buffer, pos, item, comm); } } void - unpack_vector_no_prefix (std::vector &buffer, sc_MPI_Comm comm) override + unpack_vector_no_prefix (const std::vector &buffer, int &pos, sc_MPI_Comm comm) override { - int pos = 0; - for (T &item : m_data) { - this->unpack (buffer, pos, item, comm); + single_handler.unpack (buffer, pos, item, comm); } } int - send (int dest, int tag, sc_MPI_Comm comm) override + send (const int dest, const int tag, sc_MPI_Comm comm) override { #if T8_ENABLE_MPI + int pos = 0; std::vector buffer (buffer_size (comm)); - pack_vector_prefix (buffer, comm); + pack_vector_prefix (buffer, pos, comm); const int mpiret = sc_MPI_Send (buffer.data (), buffer.size (), sc_MPI_PACKED, dest, tag, comm); @@ -203,9 +224,10 @@ class t8_data_handler: public t8_abstract_data_handler, public t8_single_data_ha } int - recv (int source, int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) override + recv (const int source, const int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) override { #if T8_ENABLE_MPI + int pos = 0; int mpiret = sc_MPI_Probe (source, tag, comm, status); SC_CHECK_MPI (mpiret); @@ -214,11 +236,11 @@ class t8_data_handler: public t8_abstract_data_handler, public t8_single_data_ha SC_CHECK_MPI (mpiret); std::vector buffer (size); - int pos = 0; + mpiret = sc_MPI_Recv (buffer.data (), buffer.size (), sc_MPI_PACKED, source, pos, comm, status); SC_CHECK_MPI (mpiret); - - unpack_vector_prefix (buffer, outcount, comm); + int vector_pos = 0; + unpack_vector_prefix (buffer, vector_pos, outcount, comm); return mpiret; #else @@ -227,8 +249,28 @@ class t8_data_handler: public t8_abstract_data_handler, public t8_single_data_ha #endif } + int + type () + { + return this->type (); + } + + t8_abstract_data_handler * + new_handler (const int type) + { + if (type < 0) { + SC_ABORTF ("[D] place-holder for t8code types"); + return NULL; + } + else { + t8_abstract_data_handler *new_handler = (t8_abstract_data_handler *) single_handler.new_user_handler (type); + return new_handler; + } + } + private: std::vector m_data; + t8_single_data_handler single_handler; }; #endif /* T8_DATA_HANDLER_HXX */ diff --git a/src/t8_data/t8_data_handler_base.hxx b/src/t8_data/t8_data_handler_base.hxx index 94500436f9..92b95e9e7d 100644 --- a/src/t8_data/t8_data_handler_base.hxx +++ b/src/t8_data/t8_data_handler_base.hxx @@ -24,31 +24,41 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #define T8_DATA_HANDLER_BASE #include -#include +#include template class t8_single_data_handler { public: + t8_single_data_handler () {}; + int - size (sc_MPI_Comm comm); + size (const T &data, sc_MPI_Comm comm); /** - * Overwrite this routine to describe how data of type T should be packed - * - * \param[in] data Data to be packed via MPI_Pack - * \return the size of the packed data in number of bytes. - */ + * Overwrite this routine to describe how data of type T should be packed + * + * \param[in] data Data to be packed via MPI_Pack + * \return the size of the packed data in number of bytes. + */ void pack (const T &data, int &pos, std::vector &buffer, sc_MPI_Comm comm); /** - * Overwrite this routine to describe how data of type T should be unpacked - * - * \param packed_data A void-pointer to the packed Data - * \return T* the unpacked data. - */ + * Overwrite this routine to describe how data of type T should be unpacked + * + * \param packed_data A void-pointer to the packed Data + * \return T* the unpacked data. + */ void unpack (const std::vector &buffer, int &pos, T &data, sc_MPI_Comm comm); + + int + type (); + + void * + new_user_handler (const int type); + + ~t8_single_data_handler () {}; }; #endif /* T8_DATA_HANDLER_BASE */ diff --git a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx index 1ee32e0a6e..f1bf6b8dcb 100644 --- a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx +++ b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx @@ -20,17 +20,19 @@ along with t8code; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef T8_ENLARGED_INT -#define T8_ENLARGED_INT +#ifndef T8_ENLARGED_STDTYPES +#define T8_ENLARGED_STDTYPES #include #include +enum pseudo_types { T8_ENLARGED_INT = 0, T8_ENLARGED_DOUBLE = 1 }; + template <> class t8_single_data_handler> { public: int - size (sc_MPI_Comm comm) + size (const enlarged_data &item, sc_MPI_Comm comm) { int size; const int mpiret = sc_MPI_Pack_size (2, sc_MPI_INT, comm, &size); @@ -57,13 +59,25 @@ class t8_single_data_handler> { mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &(data.check), 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); } + + int + type () + { + return T8_ENLARGED_INT; + } + + void * + new_user_handler (const int type) + { + return new t8_data_handler> (); + } }; template <> class t8_single_data_handler> { public: int - size (sc_MPI_Comm comm) + size (const enlarged_data &item, sc_MPI_Comm comm) { int int_size; int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &int_size); @@ -93,6 +107,114 @@ class t8_single_data_handler> { mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &(data.check), 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); } + + int + type () + { + return T8_ENLARGED_DOUBLE; + } + + void * + new_user_handler (const int type) + { + return new t8_data_handler> (); + } +}; + +template <> +class t8_single_data_handler { + public: + int + size (const pseudo_tree &item, sc_MPI_Comm comm) + { + int int_size = 0; + const int topo_data_size = item.topo_data.size () + 1; + + const int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &int_size); + SC_CHECK_MPI (mpiret); + int total_size = topo_data_size * int_size; + + /* tree_data_size */ + total_size += int_size; + + for (t8_abstract_data_handler *handler : item.tree_data) { + /* type_size */ + total_size += int_size; + /* Extra int to send type of the data. */ + total_size += handler->buffer_size (comm); + } + return total_size; + } + + void + pack (const pseudo_tree &data, int &pos, std::vector &buffer, sc_MPI_Comm comm) + { + int data_size = data.topo_data.size (); + int mpiret = sc_MPI_Pack (&data_size, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + SC_CHECK_MPI (mpiret); + for (int topo_item : data.topo_data) { + mpiret = sc_MPI_Pack (&topo_item, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + SC_CHECK_MPI (mpiret); + } + int tree_data_size = data.tree_data.size (); + mpiret = sc_MPI_Pack (&tree_data_size, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + SC_CHECK_MPI (mpiret); + + for (t8_abstract_data_handler *handler : data.tree_data) { + int type = handler->type (); + mpiret = sc_MPI_Pack (&type, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + SC_CHECK_MPI (mpiret); + handler->pack_vector_prefix (buffer, pos, comm); + } + } + + void + unpack (const std::vector &buffer, int &pos, pseudo_tree &data, sc_MPI_Comm comm) + { + int topo_data_size = 0; + int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &topo_data_size, 1, sc_MPI_INT, comm); + SC_CHECK_MPI (mpiret); + + data.topo_data.resize (topo_data_size); + for (int &topo_item : data.topo_data) { + mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &topo_item, 1, sc_MPI_INT, comm); + SC_CHECK_MPI (mpiret); + } + + int num_handler = 0; + mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &num_handler, 1, sc_MPI_INT, comm); + SC_CHECK_MPI (mpiret); + + data.tree_data.resize (num_handler); + + for (t8_abstract_data_handler *handler : data.tree_data) { + int type; + mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &type, 1, sc_MPI_INT, comm); + handler = (t8_abstract_data_handler *) handler->new_handler (type); + int outcount = 0; + handler->unpack_vector_prefix (buffer, pos, outcount, comm); + } + } + + int + type () + { + return -1; + } + + void * + new_user_handler (const int type) + { + switch (type) { + case T8_ENLARGED_INT: + return new t8_data_handler> (); + case T8_ENLARGED_DOUBLE: + return new t8_data_handler> (); + default: + SC_ABORT_NOT_REACHED (); + break; + } + } }; -#endif /* T8_ENLARGED_INT */ +#endif /* T8_ENLARGED_STDTYPES */ diff --git a/test/t8_data/t8_data_handler_specs.hxx b/test/t8_data/t8_data_handler_specs.hxx index 23dfd39baf..c28b069495 100644 --- a/test/t8_data/t8_data_handler_specs.hxx +++ b/test/t8_data/t8_data_handler_specs.hxx @@ -25,6 +25,13 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include +#include + +class pseudo_tree { + public: + std::vector topo_data; + std::vector tree_data; +}; template class enlarged_data { diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index e7161366a9..2369fb55ed 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -21,9 +21,11 @@ along with t8code; if not, write to the Free Software Foundation, Inc., */ #include +#include #include #include #include +#include /** * Templated testing class. Creates enlarged data (original data + a checking integer) and a @@ -64,40 +66,19 @@ class data_handler_test: public testing::Test { TYPED_TEST_SUITE_P (data_handler_test); -/** - * Test to pack and unpack a single element of type T. - */ -TYPED_TEST_P (data_handler_test, pack_unpack_single_data) -{ - - /* Create enlarged data. */ - int pos = 0; - - /* Send buffer to be filled with the packed data. */ - std::vector buffer (this->data_handler->buffer_size (this->comm)); - /* Pack the data into the buffer. */ - this->data_handler->pack (this->creator->large_data[0], pos, buffer, this->comm); - - /* Unpack the data. */ - this->recv_data.resize (1); - pos = 0; - this->data_handler->unpack (buffer, pos, this->recv_data[0], this->comm); - - EXPECT_EQ (this->recv_data[0].data, this->creator->large_data[0].data); - EXPECT_EQ (this->recv_data[0].check, this->creator->large_data[0].check); -} - /** * Test to pack and unpack a vector of elements of type T. */ TYPED_TEST_P (data_handler_test, pack_unpack_vector_of_data) { /* Create send buffer and pack data into it. */ + int pos = 0; std::vector buffer (this->data_handler->buffer_size (this->comm)); - this->data_handler->pack_vector_prefix (buffer, this->comm); + this->data_handler->pack_vector_prefix (buffer, pos, this->comm); int outcount = 0; - this->data_handler->unpack_vector_prefix (buffer, outcount, this->comm); + pos = 0; + this->data_handler->unpack_vector_prefix (buffer, pos, outcount, this->comm); EXPECT_EQ (outcount, this->max_num_data); this->recv_data = this->data_handler->get_data (); @@ -155,7 +136,7 @@ TEST (data_handler_test, multiple_handler) mpiret = sc_MPI_Comm_size (comm, &mpisize); SC_CHECK_MPI (mpiret); - const int num_data = 10; + const int num_data = 1000; std::vector> int_data (num_data); std::vector> double_data (num_data); @@ -174,23 +155,22 @@ TEST (data_handler_test, multiple_handler) /* Compute the rank this rank sends to. We send in a round-robin fashion */ int send_to = (mpirank + 1) % mpisize; + /* Compute the rank this rank receives from. */ int recv_from = (mpirank == 0) ? (mpisize - 1) : (mpirank - 1); + t8_debugf ("[D] computed recv from %i\n", recv_from); for (t8_abstract_data_handler *ihandler : handler) { mpiret = ihandler->send (send_to, 0, comm); #if T8_ENABLE_MPI SC_CHECK_MPI (mpiret); -#else - EXPECT_EQ (mpiret, sc_MPI_ERR_OTHER); -#endif - - /* Compute the rank we this rank receives from. */ - /* Receive and unpack the data. */ sc_MPI_Status status; int outcount; mpiret = ihandler->recv (recv_from, 0, comm, &status, outcount); +#else + EXPECT_EQ (mpiret, sc_MPI_ERR_OTHER); +#endif } std::vector> recv_ints = int_handler->get_data (); @@ -207,10 +187,75 @@ TEST (data_handler_test, multiple_handler) #else EXPECT_EQ (mpiret, sc_MPI_ERR_OTHER); #endif + + delete (int_handler); + delete (double_handler); /* Pack and send the data. */ } -REGISTER_TYPED_TEST_SUITE_P (data_handler_test, pack_unpack_single_data, pack_unpack_vector_of_data, send_recv); +TEST (data_handler_test, tree_test) +{ + sc_MPI_Comm comm = sc_MPI_COMM_WORLD; + int mpirank; + int mpisize; + int mpiret = sc_MPI_Comm_rank (comm, &mpirank); + SC_CHECK_MPI (mpiret); + mpiret = sc_MPI_Comm_size (comm, &mpisize); + SC_CHECK_MPI (mpiret); + + const int num_trees = mpirank % 4 * 10; + const int num_data = 100; + + std::vector trees (100); + const int num_topo_data = ((mpirank % 2) + 1) * 100; + std::vector> int_data (num_data); + std::vector> double_data (num_data); + const double fraction = 0.42; + for (int idata = 0; idata < num_data; idata++) { + int_data[idata].data = idata; + int_data[idata].check = mpirank; + double_data[idata].data = (double) idata + fraction; + double_data[idata].check = mpirank; + } + + for (int itree = 0; itree < num_trees; itree++) { + std::vector topo_data (num_topo_data); + std::iota (topo_data.begin (), topo_data.end (), 0); + const int num_tree_data = (mpirank + itree) % 3; + std::vector tree_data (num_data); + + for (int idata = 0; idata < num_tree_data - 1; idata++) { + if (idata == 0) { + tree_data[0] = new t8_data_handler> (int_data); + } + if (idata == 1) { + tree_data[1] = new t8_data_handler> (double_data); + } + } + trees[itree].topo_data = topo_data; + trees[itree].tree_data = tree_data; + } + + t8_data_handler *tree_handler = new t8_data_handler (trees); + + /* Compute the rank this rank sends to. We send in a round-robin fashion */ + int send_to = (mpirank + 1) % mpisize; + int recv_from = (mpirank == 0) ? (mpisize - 1) : (mpirank - 1); + + mpiret = tree_handler->send (send_to, 0, comm); + +#if T8_ENABLE_MPI + SC_CHECK_MPI (mpiret); +#else + EXPECT_EQ (mpiret, sc_MPI_ERR_OTHER); +#endif + /* Receive and unpack the data. */ + sc_MPI_Status status; + int outcount; + tree_handler->recv (recv_from, 0, comm, &status, outcount); +} + +REGISTER_TYPED_TEST_SUITE_P (data_handler_test, pack_unpack_vector_of_data, send_recv); using DataTypes = ::testing::Types; From 43a4cb001d48096135e1c753b494202d31bf2012 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 6 Sep 2024 11:39:38 +0200 Subject: [PATCH 23/81] fix tree-data-handling --- src/t8_data/t8_data_handler.hxx | 20 ++++++++++---------- src/t8_data/t8_data_handler_base.hxx | 3 --- test/t8_data/t8_gtest_data_handler.cxx | 12 ++++-------- 3 files changed, 14 insertions(+), 21 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 5ab40d8289..8d679b6ad4 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -60,7 +60,7 @@ class t8_abstract_data_handler { * \param[in] comm The communicator to use. */ virtual void - unpack_vector_prefix (const std::vector &buffer, int &outcount, int &pos, sc_MPI_Comm comm) + unpack_vector_prefix (const std::vector &buffer, int &pos, int &outcount, sc_MPI_Comm comm) = 0; /** @@ -91,6 +91,12 @@ class t8_abstract_data_handler { recv (const int source, const int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) = 0; + /** + * Return the type (as an int) that is handled by this data handler. + * Can be used to call pack/unpack from other data-handlers. + * + * \return int + */ virtual int type () = 0; @@ -107,23 +113,19 @@ class t8_data_handler: public t8_abstract_data_handler { t8_data_handler (const t8_data_handler &other) { - t8_debugf ("[D] copy constructor\n"); single_handler = other.single_handler; m_data.resize (other.m_data.size ()); for (int idata = 0; idata < other.m_data.size (); idata++) { m_data[idata] = T (other.m_data[idata]); } - t8_debugf ("[D] copy constructor\n"); } t8_data_handler (std::vector &data) { m_data.resize (data.size ()); - t8_debugf ("[D] copy handler\n"); for (int idata = 0; idata < data.size (); idata++) { m_data[idata] = T (data[idata]); } - t8_debugf ("[D] copy finished\n"); }; std::vector & @@ -148,7 +150,6 @@ class t8_data_handler: public t8_abstract_data_handler { void pack_vector_prefix (std::vector &buffer, int &pos, sc_MPI_Comm comm) override { - T8_ASSERT (buffer.size () == (long unsigned int) buffer_size (comm)); const int num_data = m_data.size (); sc_MPI_Pack (&num_data, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); @@ -163,9 +164,9 @@ class t8_data_handler: public t8_abstract_data_handler { /* Get the number of items we received. */ int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &outcount, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); + T8_ASSERT (outcount >= 0); - t8_debugf ("[D] outcount: %i\n", outcount); m_data.resize (outcount); for (T &item : m_data) { @@ -206,8 +207,7 @@ class t8_data_handler: public t8_abstract_data_handler { mpiret = sc_MPI_Recv (buffer.data (), buffer.size (), sc_MPI_PACKED, source, pos, comm, status); SC_CHECK_MPI (mpiret); - int vector_pos = 0; - unpack_vector_prefix (buffer, vector_pos, outcount, comm); + unpack_vector_prefix (buffer, pos, outcount, comm); return mpiret; #else @@ -219,7 +219,7 @@ class t8_data_handler: public t8_abstract_data_handler { int type () { - return this->type (); + return single_handler.type (); } private: diff --git a/src/t8_data/t8_data_handler_base.hxx b/src/t8_data/t8_data_handler_base.hxx index f2ef9f96fd..170fb4ccef 100644 --- a/src/t8_data/t8_data_handler_base.hxx +++ b/src/t8_data/t8_data_handler_base.hxx @@ -54,9 +54,6 @@ class t8_single_data_handler { int type (); - void * - new_user_handler (const int type); - ~t8_single_data_handler () {}; }; diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 3186969e30..46420c8908 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -259,6 +259,7 @@ TEST (data_handler_test, tree_test) std::iota (tree.topo_data.begin (), tree.topo_data.end (), 0); const int num_tree_data = (mpirank + itree) % 2; + tree.tree_data.resize (num_tree_data); for (int itree_data = 0; itree_data < num_tree_data; itree_data++) { if (itree_data == 0) { std::vector> int_data (num_data); @@ -266,16 +267,14 @@ TEST (data_handler_test, tree_test) int_data[idata].check = mpirank; int_data[idata].data = idata; } - t8_data_handler> int_handler (int_data); - tree.tree_data.push_back (&int_handler); + tree.tree_data[itree_data] = new t8_data_handler> (int_data); } else { std::vector> double_data (num_data); for (int idata = 0; idata < num_data; idata++) { double_data[idata].check = mpirank; double_data[idata].data = (double) idata + fraction; - t8_data_handler> double_handler (double_data); - tree.tree_data.push_back (&double_handler); + tree.tree_data[itree_data] = new t8_data_handler> (double_data); } } } @@ -295,19 +294,16 @@ TEST (data_handler_test, tree_test) std::vector recv_trees = tree_handler.get_data (); ASSERT_EQ (recv_trees.size (), ((recv_from) % 4) * 10); - t8_debugf ("[D] received %i trees from %i\n", recv_trees.size (), recv_from); for (int itree = 0; itree < recv_trees.size (); itree++) { ASSERT_EQ (recv_trees[itree].topo_data.size (), ((recv_from % 3) + 1) * 10); - t8_debugf ("[D] tree %i has %i topo_data \n", itree, recv_from); for (int itopo_data = 0; itopo_data < recv_trees[itree].topo_data.size (); itopo_data++) { - EXPECT_EQ (recv_trees[itree].topo_data[itopo_data], recv_trees[itree].topo_data.size ()); + EXPECT_EQ (recv_trees[itree].topo_data[itopo_data], itopo_data); } const int num_recv_tree_data = recv_trees[itree].tree_data.size (); ASSERT_EQ (num_recv_tree_data, (recv_from + itree) % 2); - t8_debugf ("[D] tree %i has %i tree_data \n", itree, num_recv_tree_data); for (int itree_data = 0; itree_data < num_recv_tree_data; itree_data++) { if (itree_data == 0) { std::vector> recv_ints From f21bba449f0cfc6a0a6a27e2f13327f327a1bd2c Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 6 Sep 2024 11:46:17 +0200 Subject: [PATCH 24/81] Add pseudo-trees --- test/t8_data/t8_pseudo_trees.hxx | 132 +++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 test/t8_data/t8_pseudo_trees.hxx diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx new file mode 100644 index 0000000000..1cf6e8e8f2 --- /dev/null +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -0,0 +1,132 @@ +/* +This file is part of t8code. +t8code is a C library to manage a collection (a forest) of multiple +connected adaptive space-trees of general element classes in parallel. + +Copyright (C) 2024 the developers + +t8code 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 2 of the License, or +(at your option) any later version. + +t8code 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 t8code; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef T8_PSEUDO_TREES_HXX +#define T8_PSEUDO_TREES_HXX + +#include +#include +#include +#include +#include + +class pseudo_tree { + public: + std::vector topo_data; + std::vector tree_data; +}; + +template <> +class t8_single_data_handler { + public: + int + size (const pseudo_tree &item, sc_MPI_Comm comm) + { + int int_size = 0; + const int topo_data_size = item.topo_data.size () + 1; + + const int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &int_size); + SC_CHECK_MPI (mpiret); + int total_size = topo_data_size * int_size; + + /* tree_data_size */ + total_size += int_size; + if (item.tree_data.size () > 0) { + for (auto ihandler : item.tree_data) { + total_size += ihandler->buffer_size (comm) + int_size; + } + } + return total_size; + } + + void + pack (const pseudo_tree &data, int &pos, std::vector &buffer, sc_MPI_Comm comm) + { + int data_size = data.topo_data.size (); + /* Pack number of topological data */ + int mpiret = sc_MPI_Pack (&data_size, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + SC_CHECK_MPI (mpiret); + for (int topo_item : data.topo_data) { + /* Pack each topological data*/ + mpiret = sc_MPI_Pack (&topo_item, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + SC_CHECK_MPI (mpiret); + } + + /* Pack number of tree-specific data*/ + int tree_data_size = data.tree_data.size (); + mpiret = sc_MPI_Pack (&tree_data_size, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + SC_CHECK_MPI (mpiret); + + for (auto handler : data.tree_data) { + int type = handler->type (); + /* Pack type of tree data */ + mpiret = sc_MPI_Pack (&type, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + SC_CHECK_MPI (mpiret); + /* Pack each data. */ + handler->pack_vector_prefix (buffer, pos, comm); + } + } + + void + unpack (const std::vector &buffer, int &pos, pseudo_tree &data, sc_MPI_Comm comm) + { + /* Unpack number of topological data */ + int topo_data_size = 0; + int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &topo_data_size, 1, sc_MPI_INT, comm); + SC_CHECK_MPI (mpiret); + data.topo_data.resize (topo_data_size); + for (int &topo_item : data.topo_data) { + /* Unpack each topological item */ + mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &topo_item, 1, sc_MPI_INT, comm); + SC_CHECK_MPI (mpiret); + } + /* Unpack number of tree-specific data */ + int num_handler = 0; + mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &num_handler, 1, sc_MPI_INT, comm); + SC_CHECK_MPI (mpiret); + data.tree_data.resize (num_handler); + + for (int ihandler = 0; ihandler < data.tree_data.size (); ihandler++) { + /* Unpack type of tree data*/ + int type; + mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &type, 1, sc_MPI_INT, comm); + int outcount = 0; + if (type == 0) { + data.tree_data[ihandler] = new t8_data_handler> (); + } + else { + data.tree_data[ihandler] = new t8_data_handler> (); + } + + /* Unpack tree data*/ + data.tree_data[ihandler]->unpack_vector_prefix (buffer, pos, outcount, comm); + } + } + + int + type () + { + return -1; + } +}; + +#endif /* T8_PSEUDO_TREES_HXX */ From 00bfae6cf90d9c58a4a5320fd546770c9baed357 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 6 Sep 2024 12:12:23 +0200 Subject: [PATCH 25/81] Encapsulate test only run when mpi is enabled --- test/t8_data/t8_gtest_data_handler.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 46420c8908..e85525c8ba 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -235,6 +235,7 @@ TEST (data_handler_test, pseudo_tree_test) } } +#if T8_ENABLE_MPI TEST (data_handler_test, tree_test) { sc_MPI_Comm comm = sc_MPI_COMM_WORLD; @@ -326,6 +327,7 @@ TEST (data_handler_test, tree_test) } } } +#endif REGISTER_TYPED_TEST_SUITE_P (data_handler_test, pack_unpack_vector_of_data, send_recv); From fb549c81e790b6fa4f505ef8cdcbbabd3ff1a548 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 6 Sep 2024 12:29:25 +0200 Subject: [PATCH 26/81] Clean-up --- src/t8_data/t8_data_handler.hxx | 4 +--- test/t8_data/t8_gtest_data_handler.cxx | 16 +++++++++------- test/t8_data/t8_pseudo_trees.hxx | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 8d679b6ad4..452d89c98d 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -123,9 +123,7 @@ class t8_data_handler: public t8_abstract_data_handler { t8_data_handler (std::vector &data) { m_data.resize (data.size ()); - for (int idata = 0; idata < data.size (); idata++) { - m_data[idata] = T (data[idata]); - } + std::copy (data.begin (), data.end (), m_data.begin ()); }; std::vector & diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index e85525c8ba..a4927b78c3 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -158,7 +158,6 @@ TEST (data_handler_test, multiple_handler) int send_to = (mpirank + 1) % mpisize; /* Compute the rank this rank receives from. */ int recv_from = (mpirank == 0) ? (mpisize - 1) : (mpirank - 1); - t8_debugf ("[D] computed recv from %i\n", recv_from); for (t8_abstract_data_handler *ihandler : handler) { @@ -294,12 +293,15 @@ TEST (data_handler_test, tree_test) std::vector recv_trees = tree_handler.get_data (); - ASSERT_EQ (recv_trees.size (), ((recv_from) % 4) * 10); + const int num_recv_trees = recv_trees.size (); - for (int itree = 0; itree < recv_trees.size (); itree++) { - ASSERT_EQ (recv_trees[itree].topo_data.size (), ((recv_from % 3) + 1) * 10); + ASSERT_EQ (num_recv_trees, ((recv_from) % 4) * 10); - for (int itopo_data = 0; itopo_data < recv_trees[itree].topo_data.size (); itopo_data++) { + for (int itree = 0; itree < num_recv_trees; itree++) { + const int num_recv_tree_topo_size = recv_trees[itree].topo_data.size (); + ASSERT_EQ (num_recv_tree_topo_size, ((recv_from % 3) + 1) * 10); + + for (int itopo_data = 0; itopo_data < num_recv_tree_topo_size; itopo_data++) { EXPECT_EQ (recv_trees[itree].topo_data[itopo_data], itopo_data); } @@ -309,7 +311,7 @@ TEST (data_handler_test, tree_test) if (itree_data == 0) { std::vector> recv_ints = ((t8_data_handler> *) (recv_trees[itree].tree_data[itree_data]))->get_data (); - ASSERT_EQ (recv_ints.size (), num_data); + ASSERT_EQ ((const int) recv_ints.size (), num_data); for (int idata = 0; idata < num_data; idata++) { EXPECT_EQ (recv_ints[idata].data, idata); EXPECT_EQ (recv_ints[idata].check, recv_from); @@ -318,7 +320,7 @@ TEST (data_handler_test, tree_test) else { std::vector> recv_double = ((t8_data_handler> *) (recv_trees[itree].tree_data[itree_data]))->get_data (); - ASSERT_EQ (recv_double.size (), num_data); + ASSERT_EQ ((const int) recv_double.size (), num_data); for (int idata = 0; idata < num_data; idata++) { EXPECT_EQ (recv_double[idata].data, (double) idata + fraction); EXPECT_EQ (recv_double[idata].check, recv_from); diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index 1cf6e8e8f2..5d5201aa30 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -105,7 +105,7 @@ class t8_single_data_handler { SC_CHECK_MPI (mpiret); data.tree_data.resize (num_handler); - for (int ihandler = 0; ihandler < data.tree_data.size (); ihandler++) { + for (int ihandler = 0; ihandler < num_handler; ihandler++) { /* Unpack type of tree data*/ int type; mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &type, 1, sc_MPI_INT, comm); From 7bf372ecb5703808a8ab665e522ee8739fed7069 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 6 Sep 2024 12:38:06 +0200 Subject: [PATCH 27/81] Clean-up --- src/t8_data/t8_data_handler.hxx | 12 +----------- test/t8_data/t8_pseudo_trees.hxx | 17 +++++++---------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 452d89c98d..b33ba5cd0c 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -111,15 +111,6 @@ class t8_data_handler: public t8_abstract_data_handler { { } - t8_data_handler (const t8_data_handler &other) - { - single_handler = other.single_handler; - m_data.resize (other.m_data.size ()); - for (int idata = 0; idata < other.m_data.size (); idata++) { - m_data[idata] = T (other.m_data[idata]); - } - } - t8_data_handler (std::vector &data) { m_data.resize (data.size ()); @@ -160,9 +151,8 @@ class t8_data_handler: public t8_abstract_data_handler { unpack_vector_prefix (const std::vector &buffer, int &pos, int &outcount, sc_MPI_Comm comm) override { /* Get the number of items we received. */ - int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &outcount, 1, sc_MPI_INT, comm); + const int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &outcount, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); - T8_ASSERT (outcount >= 0); m_data.resize (outcount); diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index 5d5201aa30..0e0e4ce12a 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -61,7 +61,7 @@ class t8_single_data_handler { void pack (const pseudo_tree &data, int &pos, std::vector &buffer, sc_MPI_Comm comm) { - int data_size = data.topo_data.size (); + const int data_size = data.topo_data.size (); /* Pack number of topological data */ int mpiret = sc_MPI_Pack (&data_size, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); SC_CHECK_MPI (mpiret); @@ -70,14 +70,13 @@ class t8_single_data_handler { mpiret = sc_MPI_Pack (&topo_item, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); SC_CHECK_MPI (mpiret); } - /* Pack number of tree-specific data*/ - int tree_data_size = data.tree_data.size (); + const int tree_data_size = data.tree_data.size (); mpiret = sc_MPI_Pack (&tree_data_size, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); SC_CHECK_MPI (mpiret); for (auto handler : data.tree_data) { - int type = handler->type (); + const int type = handler->type (); /* Pack type of tree data */ mpiret = sc_MPI_Pack (&type, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); SC_CHECK_MPI (mpiret); @@ -105,20 +104,18 @@ class t8_single_data_handler { SC_CHECK_MPI (mpiret); data.tree_data.resize (num_handler); - for (int ihandler = 0; ihandler < num_handler; ihandler++) { - /* Unpack type of tree data*/ + for (auto &ihandler : data.tree_data) { int type; mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &type, 1, sc_MPI_INT, comm); int outcount = 0; if (type == 0) { - data.tree_data[ihandler] = new t8_data_handler> (); + ihandler = new t8_data_handler> (); } else { - data.tree_data[ihandler] = new t8_data_handler> (); + ihandler = new t8_data_handler> (); } - /* Unpack tree data*/ - data.tree_data[ihandler]->unpack_vector_prefix (buffer, pos, outcount, comm); + ihandler->unpack_vector_prefix (buffer, pos, outcount, comm); } } From bbd680cbc7e07081209a35a17b3099696bd100c9 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 6 Sep 2024 12:47:45 +0200 Subject: [PATCH 28/81] use recv_from only if MPI is enabled --- src/t8_data/t8_data_handler.hxx | 1 - test/t8_data/t8_gtest_data_handler.cxx | 3 ++- test/t8_data/t8_pseudo_trees.hxx | 10 ++++------ 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index b33ba5cd0c..2ba3720eb0 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -190,7 +190,6 @@ class t8_data_handler: public t8_abstract_data_handler { int size; mpiret = sc_MPI_Get_count (status, sc_MPI_PACKED, &size); SC_CHECK_MPI (mpiret); - std::vector buffer (size); mpiret = sc_MPI_Recv (buffer.data (), buffer.size (), sc_MPI_PACKED, source, pos, comm, status); diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index a4927b78c3..958fe3ad0c 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -156,9 +156,10 @@ TEST (data_handler_test, multiple_handler) /* Compute the rank this rank sends to. We send in a round-robin fashion */ int send_to = (mpirank + 1) % mpisize; +#if T8_ENABLE_MPI /* Compute the rank this rank receives from. */ int recv_from = (mpirank == 0) ? (mpisize - 1) : (mpirank - 1); - +#endif for (t8_abstract_data_handler *ihandler : handler) { mpiret = ihandler->send (send_to, 0, comm); diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index 0e0e4ce12a..137a0b2420 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -50,10 +50,8 @@ class t8_single_data_handler { /* tree_data_size */ total_size += int_size; - if (item.tree_data.size () > 0) { - for (auto ihandler : item.tree_data) { - total_size += ihandler->buffer_size (comm) + int_size; - } + for (auto ihandler : item.tree_data) { + total_size += ihandler->buffer_size (comm) + int_size; } return total_size; } @@ -65,7 +63,7 @@ class t8_single_data_handler { /* Pack number of topological data */ int mpiret = sc_MPI_Pack (&data_size, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); SC_CHECK_MPI (mpiret); - for (int topo_item : data.topo_data) { + for (const int &topo_item : data.topo_data) { /* Pack each topological data*/ mpiret = sc_MPI_Pack (&topo_item, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); SC_CHECK_MPI (mpiret); @@ -75,7 +73,7 @@ class t8_single_data_handler { mpiret = sc_MPI_Pack (&tree_data_size, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); SC_CHECK_MPI (mpiret); - for (auto handler : data.tree_data) { + for (auto &handler : data.tree_data) { const int type = handler->type (); /* Pack type of tree data */ mpiret = sc_MPI_Pack (&type, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); From 7100f816563dc496ce1e8ca5973af2376cedb18e Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 6 Sep 2024 13:40:53 +0200 Subject: [PATCH 29/81] remove for-loop --- test/t8_data/t8_pseudo_trees.hxx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index 137a0b2420..26370ed5db 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -63,11 +63,9 @@ class t8_single_data_handler { /* Pack number of topological data */ int mpiret = sc_MPI_Pack (&data_size, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); SC_CHECK_MPI (mpiret); - for (const int &topo_item : data.topo_data) { - /* Pack each topological data*/ - mpiret = sc_MPI_Pack (&topo_item, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); - SC_CHECK_MPI (mpiret); - } + /* Pack each topological data*/ + mpiret = sc_MPI_Pack ((data.topo_data.data ()), data_size, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + SC_CHECK_MPI (mpiret); /* Pack number of tree-specific data*/ const int tree_data_size = data.tree_data.size (); mpiret = sc_MPI_Pack (&tree_data_size, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); From c45ac31ec057f19f028790b615159d30e3f34ab4 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Mon, 9 Sep 2024 09:27:47 +0200 Subject: [PATCH 30/81] start working on memory-leak that occurs when running in parallel --- src/t8_data/t8_data_handler.hxx | 1 + test/t8_data/t8_gtest_data_handler.cxx | 7 ++++--- test/t8_data/t8_pseudo_trees.hxx | 24 ++++++++++++++++++++---- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 2ba3720eb0..9bc330cef7 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -155,6 +155,7 @@ class t8_data_handler: public t8_abstract_data_handler { SC_CHECK_MPI (mpiret); T8_ASSERT (outcount >= 0); + m_data.clear (); m_data.resize (outcount); for (T &item : m_data) { diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 958fe3ad0c..42b55a823d 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -260,7 +260,7 @@ TEST (data_handler_test, tree_test) std::iota (tree.topo_data.begin (), tree.topo_data.end (), 0); const int num_tree_data = (mpirank + itree) % 2; - tree.tree_data.resize (num_tree_data); + t8_abstract_data_handler *new_handler = NULL; for (int itree_data = 0; itree_data < num_tree_data; itree_data++) { if (itree_data == 0) { std::vector> int_data (num_data); @@ -268,16 +268,17 @@ TEST (data_handler_test, tree_test) int_data[idata].check = mpirank; int_data[idata].data = idata; } - tree.tree_data[itree_data] = new t8_data_handler> (int_data); + new_handler = new t8_data_handler> (int_data); } else { std::vector> double_data (num_data); for (int idata = 0; idata < num_data; idata++) { double_data[idata].check = mpirank; double_data[idata].data = (double) idata + fraction; - tree.tree_data[itree_data] = new t8_data_handler> (double_data); + new_handler = new t8_data_handler> (double_data); } } + tree.tree_data.push_back (new_handler); } trees.push_back (tree); } diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index 26370ed5db..fa8646a88f 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -31,6 +31,13 @@ along with t8code; if not, write to the Free Software Foundation, Inc., class pseudo_tree { public: + ~pseudo_tree () + { + for (auto &handler : tree_data) { + delete (handler); + } + } + std::vector topo_data; std::vector tree_data; }; @@ -98,20 +105,29 @@ class t8_single_data_handler { int num_handler = 0; mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &num_handler, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); - data.tree_data.resize (num_handler); for (auto &ihandler : data.tree_data) { + delete (ihandler); + ihandler = nullptr; + } + + for (int ihandler = 0; ihandler < num_handler; ihandler++) { + t8_abstract_data_handler *new_handler = NULL; int type; mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &type, 1, sc_MPI_INT, comm); int outcount = 0; if (type == 0) { - ihandler = new t8_data_handler> (); + new_handler = new t8_data_handler> (); + } + else if (type == 1) { + new_handler = new t8_data_handler> (); } else { - ihandler = new t8_data_handler> (); + SC_ABORT_NOT_REACHED (); } /* Unpack tree data*/ - ihandler->unpack_vector_prefix (buffer, pos, outcount, comm); + new_handler->unpack_vector_prefix (buffer, pos, outcount, comm); + data.tree_data.push_back (new_handler); } } From 9ab1fe48885b664b20d296ff9584b6a94e26ebc0 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Wed, 11 Sep 2024 12:16:04 +0200 Subject: [PATCH 31/81] Use void* instead of std::vector for buffer --- src/t8_data/t8_data_handler.hxx | 37 ++++++++++--------- src/t8_data/t8_data_handler_base.hxx | 4 +- .../t8_data_packs/t8_enlarged_stdtypes.hxx | 24 ++++++------ test/t8_data/t8_gtest_data_handler.cxx | 9 +++-- test/t8_data/t8_pseudo_trees.hxx | 24 ++++++------ 5 files changed, 52 insertions(+), 46 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 9bc330cef7..a5427c7136 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -49,7 +49,7 @@ class t8_abstract_data_handler { * \param[in] comm The used communicator */ virtual void - pack_vector_prefix (std::vector &buffer, int &pos, sc_MPI_Comm comm) + pack_vector_prefix (void *buffer, const int num_bytes, int &pos, sc_MPI_Comm comm) = 0; /** @@ -60,7 +60,7 @@ class t8_abstract_data_handler { * \param[in] comm The communicator to use. */ virtual void - unpack_vector_prefix (const std::vector &buffer, int &pos, int &outcount, sc_MPI_Comm comm) + unpack_vector_prefix (const void *buffer, const int num_bytes, int &pos, int &outcount, sc_MPI_Comm comm) = 0; /** @@ -137,21 +137,21 @@ class t8_data_handler: public t8_abstract_data_handler { } void - pack_vector_prefix (std::vector &buffer, int &pos, sc_MPI_Comm comm) override + pack_vector_prefix (void *buffer, const int num_bytes, int &pos, sc_MPI_Comm comm) override { const int num_data = m_data.size (); - sc_MPI_Pack (&num_data, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + sc_MPI_Pack (&num_data, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); for (const T &item : m_data) { - single_handler.pack (item, pos, buffer, comm); + single_handler.pack (item, pos, buffer, num_bytes, comm); } } void - unpack_vector_prefix (const std::vector &buffer, int &pos, int &outcount, sc_MPI_Comm comm) override + unpack_vector_prefix (const void *buffer, const int num_bytes, int &pos, int &outcount, sc_MPI_Comm comm) override { /* Get the number of items we received. */ - const int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &outcount, 1, sc_MPI_INT, comm); + const int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &outcount, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); T8_ASSERT (outcount >= 0); @@ -159,7 +159,7 @@ class t8_data_handler: public t8_abstract_data_handler { m_data.resize (outcount); for (T &item : m_data) { - single_handler.unpack (buffer, pos, item, comm); + single_handler.unpack (buffer, num_bytes, pos, item, comm); } } @@ -168,11 +168,13 @@ class t8_data_handler: public t8_abstract_data_handler { { #if T8_ENABLE_MPI int pos = 0; - std::vector buffer (buffer_size (comm)); - pack_vector_prefix (buffer, pos, comm); + const int num_bytes = buffer_size (comm); + void *buffer = malloc (num_bytes); + pack_vector_prefix (buffer, num_bytes, pos, comm); - const int mpiret = sc_MPI_Send (buffer.data (), buffer.size (), sc_MPI_PACKED, dest, tag, comm); + const int mpiret = sc_MPI_Send (buffer, num_bytes, sc_MPI_PACKED, dest, tag, comm); + free (buffer); return mpiret; #else t8_infof ("send only available when configured with --enable-mpi\n"); @@ -188,15 +190,16 @@ class t8_data_handler: public t8_abstract_data_handler { int mpiret = sc_MPI_Probe (source, tag, comm, status); SC_CHECK_MPI (mpiret); - int size; - mpiret = sc_MPI_Get_count (status, sc_MPI_PACKED, &size); + int num_bytes; + mpiret = sc_MPI_Get_count (status, sc_MPI_PACKED, &num_bytes); SC_CHECK_MPI (mpiret); - std::vector buffer (size); + void *buffer = malloc (num_bytes); + T8_ASSERT (buffer != NULL); - mpiret = sc_MPI_Recv (buffer.data (), buffer.size (), sc_MPI_PACKED, source, pos, comm, status); + mpiret = sc_MPI_Recv (buffer, num_bytes, sc_MPI_PACKED, source, pos, comm, status); SC_CHECK_MPI (mpiret); - unpack_vector_prefix (buffer, pos, outcount, comm); - + unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); + free (buffer); return mpiret; #else t8_infof ("recv only available when configured with --enable-mpi\n"); diff --git a/src/t8_data/t8_data_handler_base.hxx b/src/t8_data/t8_data_handler_base.hxx index 170fb4ccef..8bd0deddef 100644 --- a/src/t8_data/t8_data_handler_base.hxx +++ b/src/t8_data/t8_data_handler_base.hxx @@ -40,7 +40,7 @@ class t8_single_data_handler { * \return the size of the packed data in number of bytes. */ void - pack (const T &data, int &pos, std::vector &buffer, sc_MPI_Comm comm); + pack (const T &data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm); /** * Overwrite this routine to describe how data of type T should be unpacked @@ -49,7 +49,7 @@ class t8_single_data_handler { * \return T* the unpacked data. */ void - unpack (const std::vector &buffer, int &pos, T &data, sc_MPI_Comm comm); + unpack (const void *buffer, const int num_bytes, int &pos, T &data, sc_MPI_Comm comm); int type (); diff --git a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx index 43f5bc062b..30c06ea344 100644 --- a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx +++ b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx @@ -41,22 +41,22 @@ class t8_single_data_handler> { } void - pack (const enlarged_data &data, int &pos, std::vector &buffer, sc_MPI_Comm comm) + pack (const enlarged_data &data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm) { - int mpiret = sc_MPI_Pack (&(data.data), 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + int mpiret = sc_MPI_Pack (&(data.data), 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); - mpiret = sc_MPI_Pack (&(data.check), 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + mpiret = sc_MPI_Pack (&(data.check), 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); } void - unpack (const std::vector &buffer, int &pos, enlarged_data &data, sc_MPI_Comm comm) + unpack (const void *buffer, const int num_bytes, int &pos, enlarged_data &data, sc_MPI_Comm comm) { - int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &(data.data), 1, sc_MPI_INT, comm); + int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &(data.data), 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); - mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &(data.check), 1, sc_MPI_INT, comm); + mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &(data.check), 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); } @@ -83,22 +83,22 @@ class t8_single_data_handler> { } void - pack (const enlarged_data &data, int &pos, std::vector &buffer, sc_MPI_Comm comm) + pack (const enlarged_data &data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm) { - int mpiret = sc_MPI_Pack (&(data.data), 1, sc_MPI_DOUBLE, buffer.data (), buffer.size (), &pos, comm); + int mpiret = sc_MPI_Pack (&(data.data), 1, sc_MPI_DOUBLE, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); - mpiret = sc_MPI_Pack (&(data.check), 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + mpiret = sc_MPI_Pack (&(data.check), 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); } void - unpack (const std::vector &buffer, int &pos, enlarged_data &data, sc_MPI_Comm comm) + unpack (const void *buffer, const int num_bytes, int &pos, enlarged_data &data, sc_MPI_Comm comm) { - int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &(data.data), 1, sc_MPI_DOUBLE, comm); + int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &(data.data), 1, sc_MPI_DOUBLE, comm); SC_CHECK_MPI (mpiret); - mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &(data.check), 1, sc_MPI_INT, comm); + mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &(data.check), 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); } diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 42b55a823d..421a543a79 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -74,12 +74,13 @@ TYPED_TEST_P (data_handler_test, pack_unpack_vector_of_data) { /* Create send buffer and pack data into it. */ int pos = 0; - std::vector buffer (this->data_handler->buffer_size (this->comm)); - this->data_handler->pack_vector_prefix (buffer, pos, this->comm); + const int num_bytes = this->data_handler->buffer_size (this->comm); + void *buffer = malloc (num_bytes); + this->data_handler->pack_vector_prefix (buffer, num_bytes, pos, this->comm); int outcount = 0; pos = 0; - this->data_handler->unpack_vector_prefix (buffer, pos, outcount, this->comm); + this->data_handler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, this->comm); EXPECT_EQ (outcount, this->max_num_data); this->recv_data = this->data_handler->get_data (); @@ -88,6 +89,8 @@ TYPED_TEST_P (data_handler_test, pack_unpack_vector_of_data) EXPECT_EQ (this->recv_data[idata].data, this->creator->large_data[idata].data); EXPECT_EQ (this->recv_data[idata].check, this->creator->large_data[idata].check); } + + free (buffer); } /** diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index fa8646a88f..b408e822e3 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -64,46 +64,46 @@ class t8_single_data_handler { } void - pack (const pseudo_tree &data, int &pos, std::vector &buffer, sc_MPI_Comm comm) + pack (const pseudo_tree &data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm) { const int data_size = data.topo_data.size (); /* Pack number of topological data */ - int mpiret = sc_MPI_Pack (&data_size, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + int mpiret = sc_MPI_Pack (&data_size, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); /* Pack each topological data*/ - mpiret = sc_MPI_Pack ((data.topo_data.data ()), data_size, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + mpiret = sc_MPI_Pack ((data.topo_data.data ()), data_size, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); /* Pack number of tree-specific data*/ const int tree_data_size = data.tree_data.size (); - mpiret = sc_MPI_Pack (&tree_data_size, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + mpiret = sc_MPI_Pack (&tree_data_size, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); for (auto &handler : data.tree_data) { const int type = handler->type (); /* Pack type of tree data */ - mpiret = sc_MPI_Pack (&type, 1, sc_MPI_INT, buffer.data (), buffer.size (), &pos, comm); + mpiret = sc_MPI_Pack (&type, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); /* Pack each data. */ - handler->pack_vector_prefix (buffer, pos, comm); + handler->pack_vector_prefix (buffer, num_bytes, pos, comm); } } void - unpack (const std::vector &buffer, int &pos, pseudo_tree &data, sc_MPI_Comm comm) + unpack (const void *buffer, const int num_bytes, int &pos, pseudo_tree &data, sc_MPI_Comm comm) { /* Unpack number of topological data */ int topo_data_size = 0; - int mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &topo_data_size, 1, sc_MPI_INT, comm); + int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &topo_data_size, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); data.topo_data.resize (topo_data_size); for (int &topo_item : data.topo_data) { /* Unpack each topological item */ - mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &topo_item, 1, sc_MPI_INT, comm); + mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &topo_item, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); } /* Unpack number of tree-specific data */ int num_handler = 0; - mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &num_handler, 1, sc_MPI_INT, comm); + mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &num_handler, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); for (auto &ihandler : data.tree_data) { @@ -114,7 +114,7 @@ class t8_single_data_handler { for (int ihandler = 0; ihandler < num_handler; ihandler++) { t8_abstract_data_handler *new_handler = NULL; int type; - mpiret = sc_MPI_Unpack (buffer.data (), buffer.size (), &pos, &type, 1, sc_MPI_INT, comm); + mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &type, 1, sc_MPI_INT, comm); int outcount = 0; if (type == 0) { new_handler = new t8_data_handler> (); @@ -126,7 +126,7 @@ class t8_single_data_handler { SC_ABORT_NOT_REACHED (); } /* Unpack tree data*/ - new_handler->unpack_vector_prefix (buffer, pos, outcount, comm); + new_handler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); data.tree_data.push_back (new_handler); } } From 1cae747c3d86853a4ad0d7853d8f893efb58b2cc Mon Sep 17 00:00:00 2001 From: David Knapp Date: Mon, 23 Sep 2024 11:28:15 +0200 Subject: [PATCH 32/81] dirty commit --- src/t8_data/t8_data_handler.hxx | 25 +++++++++++++- test/t8_data/t8_gtest_data_handler.cxx | 9 ++--- test/t8_data/t8_pseudo_trees.hxx | 48 ++++++++++++++++++-------- 3 files changed, 61 insertions(+), 21 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index a5427c7136..5882689b98 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -111,6 +111,25 @@ class t8_data_handler: public t8_abstract_data_handler { { } + t8_data_handler( const t8_data_handler &other) : single_handler(other.single_handler){ + m_data.resize(other.m_data.size()); + std::copy(other.m_data.begin(), other.m_data.end(), m_data.begin()); + } + + t8_data_handler& operator= (const t8_data_handler &other){ + if(this != &other){ + single_handler = other.single_handler; + + for(T *item : m_data){ + delete item; + } + m_data.clear(); + m_data.resize(other.m_data.size()); + std::copy(other.m_data.begin(), other.m_data.end(), m_data); + } + return *this; + } + t8_data_handler (std::vector &data) { m_data.resize (data.size ()); @@ -155,7 +174,6 @@ class t8_data_handler: public t8_abstract_data_handler { SC_CHECK_MPI (mpiret); T8_ASSERT (outcount >= 0); - m_data.clear (); m_data.resize (outcount); for (T &item : m_data) { @@ -175,6 +193,7 @@ class t8_data_handler: public t8_abstract_data_handler { const int mpiret = sc_MPI_Send (buffer, num_bytes, sc_MPI_PACKED, dest, tag, comm); free (buffer); + m_data.resize(0); return mpiret; #else t8_infof ("send only available when configured with --enable-mpi\n"); @@ -213,6 +232,10 @@ class t8_data_handler: public t8_abstract_data_handler { return single_handler.type (); } + ~t8_data_handler(){ + m_data.clear(); + } + private: std::vector m_data; t8_single_data_handler single_handler; diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 421a543a79..88e1c81a1e 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -75,7 +75,7 @@ TYPED_TEST_P (data_handler_test, pack_unpack_vector_of_data) /* Create send buffer and pack data into it. */ int pos = 0; const int num_bytes = this->data_handler->buffer_size (this->comm); - void *buffer = malloc (num_bytes); + void *buffer = malloc(num_bytes); this->data_handler->pack_vector_prefix (buffer, num_bytes, pos, this->comm); int outcount = 0; @@ -90,7 +90,7 @@ TYPED_TEST_P (data_handler_test, pack_unpack_vector_of_data) EXPECT_EQ (this->recv_data[idata].check, this->creator->large_data[idata].check); } - free (buffer); + free(buffer); } /** @@ -191,10 +191,6 @@ TEST (data_handler_test, multiple_handler) #else EXPECT_EQ (mpiret, sc_MPI_ERR_OTHER); #endif - - delete (int_handler); - delete (double_handler); - /* Pack and send the data. */ } TEST (data_handler_test, pseudo_tree_test) @@ -224,6 +220,7 @@ TEST (data_handler_test, pseudo_tree_test) EXPECT_EQ (copied_data[idata].check, int_data[idata].check); } + pseudo_tree tree_equal = tree_copy; EXPECT_EQ (tree.topo_data.size (), tree_equal.topo_data.size ()); diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index b408e822e3..3a13cbe90d 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -31,11 +31,32 @@ along with t8code; if not, write to the Free Software Foundation, Inc., class pseudo_tree { public: - ~pseudo_tree () - { - for (auto &handler : tree_data) { - delete (handler); + pseudo_tree(){} + + pseudo_tree(const pseudo_tree &other) : topo_data(other.topo_data){ + tree_data.resize(other.tree_data.size()); + std::copy(other.tree_data.begin(), other.tree_data.end(), tree_data.begin()); + } + + pseudo_tree& operator= (const pseudo_tree &other){ + if( this != &other){ + for (t8_abstract_data_handler* handler : tree_data) { + delete handler; + } + tree_data.clear(); + topo_data = other.topo_data; + + if(tree_data.size() != other.tree_data.size()){ + tree_data.resize(other.tree_data.size()); + + std::copy(other.tree_data.begin(), other.tree_data.end(), tree_data.begin()); + } } + return *this; + } + + ~pseudo_tree(){ + tree_data.clear(); } std::vector topo_data; @@ -106,28 +127,27 @@ class t8_single_data_handler { mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &num_handler, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); - for (auto &ihandler : data.tree_data) { - delete (ihandler); - ihandler = nullptr; - } + for (int ihandler = 0; ihandler < num_handler; ihandler++) { - t8_abstract_data_handler *new_handler = NULL; int type; + + delete data.tree_data[ihandler]; mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &type, 1, sc_MPI_INT, comm); int outcount = 0; if (type == 0) { - new_handler = new t8_data_handler> (); + t8_data_handler> *new_handler = new t8_data_handler> (); + new_handler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); + data.tree_data.push_back(new_handler); } else if (type == 1) { - new_handler = new t8_data_handler> (); + t8_data_handler> *new_handler = new t8_data_handler> (); + new_handler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); + data.tree_data.push_back(new_handler); } else { SC_ABORT_NOT_REACHED (); } - /* Unpack tree data*/ - new_handler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); - data.tree_data.push_back (new_handler); } } From af26edf6112eeecc57818939342cdbaa359b917e Mon Sep 17 00:00:00 2001 From: David Knapp Date: Thu, 26 Sep 2024 16:59:21 +0200 Subject: [PATCH 33/81] Fix memory leak in serial --- src/t8_data/t8_data_handler.hxx | 83 +++++++++++++------ src/t8_data/t8_data_handler_base.hxx | 2 +- .../t8_data_packs/t8_enlarged_stdtypes.hxx | 28 +++---- test/t8_data/t8_gtest_data_handler.cxx | 62 +++++++------- test/t8_data/t8_pseudo_trees.hxx | 65 ++++++++------- 5 files changed, 137 insertions(+), 103 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 5882689b98..7e4f86b016 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -111,35 +111,53 @@ class t8_data_handler: public t8_abstract_data_handler { { } - t8_data_handler( const t8_data_handler &other) : single_handler(other.single_handler){ - m_data.resize(other.m_data.size()); - std::copy(other.m_data.begin(), other.m_data.end(), m_data.begin()); + t8_data_handler (const t8_data_handler &other): single_handler (other.single_handler), m_data (other.m_data.size ()) + { + for (size_t i = 0; i < other.m_data.size (); ++i) { + m_data[i] = new T (*other.m_data[i]); // Deep copy + } } - t8_data_handler& operator= (const t8_data_handler &other){ - if(this != &other){ + t8_data_handler & + operator= (const t8_data_handler &other) + { + if (this != &other) { single_handler = other.single_handler; - for(T *item : m_data){ + for (T *item : m_data) { delete item; } - m_data.clear(); - m_data.resize(other.m_data.size()); - std::copy(other.m_data.begin(), other.m_data.end(), m_data); + m_data.clear (); + m_data.resize (other.m_data.size ()); + for (size_t i = 0; i < other.m_data.size (); ++i) { + m_data[i] = new T (*other.m_data[i]); // Deep copy + } } return *this; } t8_data_handler (std::vector &data) { + // Clear existing data to avoid memory leaks + for (T *item : m_data) { + delete item; + } + m_data.clear (); + + // Resize and copy new data m_data.resize (data.size ()); - std::copy (data.begin (), data.end (), m_data.begin ()); - }; + for (size_t i = 0; i < data.size (); ++i) { + m_data[i] = new T (data[i]); // Create new instances of T + } + } - std::vector & - get_data () + void + get_data (std::vector &data) { - return m_data; + data.resize (m_data.size ()); + for (size_t i = 0; i < m_data.size (); ++i) { + data[i] = *m_data[i]; + } } int @@ -148,7 +166,7 @@ class t8_data_handler: public t8_abstract_data_handler { int total_size = 0; int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &total_size); SC_CHECK_MPI (mpiret); - for (const T &item : m_data) { + for (const auto item : m_data) { const int size = single_handler.size (item, comm); total_size += size; } @@ -159,9 +177,10 @@ class t8_data_handler: public t8_abstract_data_handler { pack_vector_prefix (void *buffer, const int num_bytes, int &pos, sc_MPI_Comm comm) override { const int num_data = m_data.size (); - sc_MPI_Pack (&num_data, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); + int mpiret = sc_MPI_Pack (&num_data, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); + SC_CHECK_MPI (mpiret); - for (const T &item : m_data) { + for (const auto item : m_data) { single_handler.pack (item, pos, buffer, num_bytes, comm); } } @@ -174,10 +193,14 @@ class t8_data_handler: public t8_abstract_data_handler { SC_CHECK_MPI (mpiret); T8_ASSERT (outcount >= 0); + for (T *item : m_data) { + delete item; + } + m_data.clear (); m_data.resize (outcount); - - for (T &item : m_data) { - single_handler.unpack (buffer, num_bytes, pos, item, comm); + for (int i = 0; i < outcount; ++i) { + m_data[i] = new T (); + single_handler.unpack (buffer, num_bytes, pos, m_data[i], comm); } } @@ -191,9 +214,12 @@ class t8_data_handler: public t8_abstract_data_handler { pack_vector_prefix (buffer, num_bytes, pos, comm); const int mpiret = sc_MPI_Send (buffer, num_bytes, sc_MPI_PACKED, dest, tag, comm); - + SC_CHECK_MPI (mpiret); free (buffer); - m_data.resize(0); + for (T *item : m_data) { + delete item; + } + m_data.clear (); return mpiret; #else t8_infof ("send only available when configured with --enable-mpi\n"); @@ -215,7 +241,7 @@ class t8_data_handler: public t8_abstract_data_handler { void *buffer = malloc (num_bytes); T8_ASSERT (buffer != NULL); - mpiret = sc_MPI_Recv (buffer, num_bytes, sc_MPI_PACKED, source, pos, comm, status); + mpiret = sc_MPI_Recv (buffer, num_bytes, sc_MPI_PACKED, source, tag, comm, status); SC_CHECK_MPI (mpiret); unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); free (buffer); @@ -227,17 +253,20 @@ class t8_data_handler: public t8_abstract_data_handler { } int - type () + type () override { return single_handler.type (); } - ~t8_data_handler(){ - m_data.clear(); + ~t8_data_handler () override + { + for (T *item : m_data) { + delete item; + } } private: - std::vector m_data; + std::vector m_data; t8_single_data_handler single_handler; }; diff --git a/src/t8_data/t8_data_handler_base.hxx b/src/t8_data/t8_data_handler_base.hxx index 8bd0deddef..88344a31c8 100644 --- a/src/t8_data/t8_data_handler_base.hxx +++ b/src/t8_data/t8_data_handler_base.hxx @@ -49,7 +49,7 @@ class t8_single_data_handler { * \return T* the unpacked data. */ void - unpack (const void *buffer, const int num_bytes, int &pos, T &data, sc_MPI_Comm comm); + unpack (const void *buffer, const int num_bytes, int &pos, T *data, sc_MPI_Comm comm); int type (); diff --git a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx index 30c06ea344..16f8479e1f 100644 --- a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx +++ b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx @@ -32,7 +32,7 @@ template <> class t8_single_data_handler> { public: int - size (const enlarged_data &item, sc_MPI_Comm comm) + size (const enlarged_data *item, sc_MPI_Comm comm) { int size; const int mpiret = sc_MPI_Pack_size (2, sc_MPI_INT, comm, &size); @@ -41,22 +41,22 @@ class t8_single_data_handler> { } void - pack (const enlarged_data &data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm) + pack (const enlarged_data *data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm) { - int mpiret = sc_MPI_Pack (&(data.data), 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); + int mpiret = sc_MPI_Pack (&(data->data), 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); - mpiret = sc_MPI_Pack (&(data.check), 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); + mpiret = sc_MPI_Pack (&(data->check), 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); } void - unpack (const void *buffer, const int num_bytes, int &pos, enlarged_data &data, sc_MPI_Comm comm) + unpack (const void *buffer, const int num_bytes, int &pos, enlarged_data *data, sc_MPI_Comm comm) { - int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &(data.data), 1, sc_MPI_INT, comm); + int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &(data->data), 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); - mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &(data.check), 1, sc_MPI_INT, comm); + mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &(data->check), 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); } @@ -71,7 +71,7 @@ template <> class t8_single_data_handler> { public: int - size (const enlarged_data &item, sc_MPI_Comm comm) + size (const enlarged_data *item, sc_MPI_Comm comm) { int int_size; int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &int_size); @@ -83,22 +83,22 @@ class t8_single_data_handler> { } void - pack (const enlarged_data &data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm) + pack (const enlarged_data *data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm) { - int mpiret = sc_MPI_Pack (&(data.data), 1, sc_MPI_DOUBLE, buffer, num_bytes, &pos, comm); + int mpiret = sc_MPI_Pack (&(data->data), 1, sc_MPI_DOUBLE, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); - mpiret = sc_MPI_Pack (&(data.check), 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); + mpiret = sc_MPI_Pack (&(data->check), 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); } void - unpack (const void *buffer, const int num_bytes, int &pos, enlarged_data &data, sc_MPI_Comm comm) + unpack (const void *buffer, const int num_bytes, int &pos, enlarged_data *data, sc_MPI_Comm comm) { - int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &(data.data), 1, sc_MPI_DOUBLE, comm); + int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &(data->data), 1, sc_MPI_DOUBLE, comm); SC_CHECK_MPI (mpiret); - mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &(data.check), 1, sc_MPI_INT, comm); + mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &(data->check), 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); } diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 88e1c81a1e..72723bf19d 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -44,20 +44,19 @@ class data_handler_test: public testing::Test { SC_CHECK_MPI (mpiret); mpiret = sc_MPI_Comm_size (comm, &mpisize); SC_CHECK_MPI (mpiret); - creator = new data_creator> (); - creator->create (max_num_data); - data_handler = new t8_data_handler> (creator->large_data); + creator = data_creator> (); + creator.create (max_num_data); + data_handler = new t8_data_handler> (creator.large_data); } void TearDown () override { - delete (data_handler); - delete (creator); + delete data_handler; } t8_data_handler> *data_handler; - data_creator> *creator; + data_creator> creator; std::vector> recv_data; int mpirank; int mpisize; @@ -75,7 +74,7 @@ TYPED_TEST_P (data_handler_test, pack_unpack_vector_of_data) /* Create send buffer and pack data into it. */ int pos = 0; const int num_bytes = this->data_handler->buffer_size (this->comm); - void *buffer = malloc(num_bytes); + void *buffer = malloc (num_bytes); this->data_handler->pack_vector_prefix (buffer, num_bytes, pos, this->comm); int outcount = 0; @@ -83,14 +82,14 @@ TYPED_TEST_P (data_handler_test, pack_unpack_vector_of_data) this->data_handler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, this->comm); EXPECT_EQ (outcount, this->max_num_data); - this->recv_data = this->data_handler->get_data (); + this->data_handler->get_data (this->recv_data); for (int idata = 0; idata < this->max_num_data; idata++) { - EXPECT_EQ (this->recv_data[idata].data, this->creator->large_data[idata].data); - EXPECT_EQ (this->recv_data[idata].check, this->creator->large_data[idata].check); + EXPECT_EQ (this->recv_data[idata].data, this->creator.large_data[idata].data); + EXPECT_EQ (this->recv_data[idata].check, this->creator.large_data[idata].check); } - free(buffer); + free (buffer); } /** @@ -117,13 +116,13 @@ TYPED_TEST_P (data_handler_test, send_recv) int outcount; mpiret = this->data_handler->recv (recv_from, 0, this->comm, &status, outcount); - this->recv_data = this->data_handler->get_data (); + this->data_handler->get_data (this->recv_data); #if T8_ENABLE_MPI SC_CHECK_MPI (mpiret); EXPECT_EQ (outcount, this->max_num_data); for (int idata = 0; idata < this->max_num_data; idata++) { - EXPECT_EQ (this->recv_data[idata].data, this->creator->large_data[idata].data); - EXPECT_EQ (this->recv_data[idata].check, this->creator->large_data[idata].check); + EXPECT_EQ (this->recv_data[idata].data, this->creator.large_data[idata].data); + EXPECT_EQ (this->recv_data[idata].check, this->creator.large_data[idata].check); } #else EXPECT_EQ (mpiret, sc_MPI_ERR_OTHER); @@ -151,11 +150,12 @@ TEST (data_handler_test, multiple_handler) double_data[idata].data = (double) idata + fraction; double_data[idata].check = mpirank; } + t8_data_handler> int_handler (int_data); + t8_data_handler> double_handler (double_data); + std::vector handler; - t8_data_handler> *int_handler = new t8_data_handler> (int_data); - t8_data_handler> *double_handler = new t8_data_handler> (double_data); - - std::vector handler = { int_handler, double_handler }; + handler.push_back (&int_handler); + handler.push_back (&double_handler); /* Compute the rank this rank sends to. We send in a round-robin fashion */ int send_to = (mpirank + 1) % mpisize; @@ -177,8 +177,10 @@ TEST (data_handler_test, multiple_handler) #endif } - std::vector> recv_ints = int_handler->get_data (); - std::vector> recv_doubles = double_handler->get_data (); + std::vector> recv_ints; + std::vector> recv_doubles; + ((t8_data_handler> *) (handler[0]))->get_data (recv_ints); + ((t8_data_handler> *) (handler[1]))->get_data (recv_doubles); #if T8_ENABLE_MPI SC_CHECK_MPI (mpiret); @@ -212,22 +214,21 @@ TEST (data_handler_test, pseudo_tree_test) EXPECT_EQ (tree.topo_data.size (), tree_copy.topo_data.size ()); EXPECT_EQ (tree.tree_data.size (), tree_copy.tree_data.size ()); - std::vector> copied_data - = ((t8_data_handler> *) (tree_copy.tree_data[0]))->get_data (); + std::vector> copied_data; + ((t8_data_handler> *) (tree_copy.tree_data[0]))->get_data (copied_data); for (int idata = 0; idata < num_data; idata++) { EXPECT_EQ (copied_data[idata].data, int_data[idata].data); EXPECT_EQ (copied_data[idata].check, int_data[idata].check); } - pseudo_tree tree_equal = tree_copy; EXPECT_EQ (tree.topo_data.size (), tree_equal.topo_data.size ()); EXPECT_EQ (tree.tree_data.size (), tree_equal.tree_data.size ()); - std::vector> equal_data - = ((t8_data_handler> *) (tree_equal.tree_data[0]))->get_data (); + std::vector> equal_data; + ((t8_data_handler> *) (tree_equal.tree_data[0]))->get_data (equal_data); for (int idata = 0; idata < num_data; idata++) { EXPECT_EQ (equal_data[idata].data, int_data[idata].data); @@ -293,7 +294,8 @@ TEST (data_handler_test, tree_test) int outcount; mpiret = tree_handler.recv (recv_from, 0, comm, &status, outcount); - std::vector recv_trees = tree_handler.get_data (); + std::vector recv_trees; + tree_handler.get_data (recv_trees); const int num_recv_trees = recv_trees.size (); @@ -311,8 +313,8 @@ TEST (data_handler_test, tree_test) ASSERT_EQ (num_recv_tree_data, (recv_from + itree) % 2); for (int itree_data = 0; itree_data < num_recv_tree_data; itree_data++) { if (itree_data == 0) { - std::vector> recv_ints - = ((t8_data_handler> *) (recv_trees[itree].tree_data[itree_data]))->get_data (); + std::vector> recv_ints; + ((t8_data_handler> *) (recv_trees[itree].tree_data[itree_data]))->get_data (recv_ints); ASSERT_EQ ((const int) recv_ints.size (), num_data); for (int idata = 0; idata < num_data; idata++) { EXPECT_EQ (recv_ints[idata].data, idata); @@ -320,8 +322,8 @@ TEST (data_handler_test, tree_test) } } else { - std::vector> recv_double - = ((t8_data_handler> *) (recv_trees[itree].tree_data[itree_data]))->get_data (); + std::vector> recv_double; + ((t8_data_handler> *) (recv_trees[itree].tree_data[itree_data]))->get_data (recv_double); ASSERT_EQ ((const int) recv_double.size (), num_data); for (int idata = 0; idata < num_data; idata++) { EXPECT_EQ (recv_double[idata].data, (double) idata + fraction); diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index 3a13cbe90d..38050e0bae 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -31,32 +31,39 @@ along with t8code; if not, write to the Free Software Foundation, Inc., class pseudo_tree { public: - pseudo_tree(){} + pseudo_tree () + { + } - pseudo_tree(const pseudo_tree &other) : topo_data(other.topo_data){ - tree_data.resize(other.tree_data.size()); - std::copy(other.tree_data.begin(), other.tree_data.end(), tree_data.begin()); + pseudo_tree (const pseudo_tree &other): topo_data (other.topo_data) + { + tree_data.resize (other.tree_data.size ()); + for (size_t i = 0; i < other.tree_data.size (); ++i) { + tree_data[i] = other.tree_data[i]; + } } - pseudo_tree& operator= (const pseudo_tree &other){ - if( this != &other){ - for (t8_abstract_data_handler* handler : tree_data) { + pseudo_tree & + operator= (const pseudo_tree &other) + { + if (this != &other) { + for (t8_abstract_data_handler *handler : tree_data) { delete handler; } - tree_data.clear(); + tree_data.clear (); topo_data = other.topo_data; - if(tree_data.size() != other.tree_data.size()){ - tree_data.resize(other.tree_data.size()); - - std::copy(other.tree_data.begin(), other.tree_data.end(), tree_data.begin()); + tree_data.resize (other.tree_data.size ()); + for (size_t i = 0; i < other.tree_data.size (); ++i) { + tree_data[i] = other.tree_data[i]; } } return *this; } - ~pseudo_tree(){ - tree_data.clear(); + ~pseudo_tree () + { + tree_data.clear (); } std::vector topo_data; @@ -67,10 +74,10 @@ template <> class t8_single_data_handler { public: int - size (const pseudo_tree &item, sc_MPI_Comm comm) + size (const pseudo_tree *item, sc_MPI_Comm comm) { int int_size = 0; - const int topo_data_size = item.topo_data.size () + 1; + const int topo_data_size = item->topo_data.size () + 1; const int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &int_size); SC_CHECK_MPI (mpiret); @@ -78,28 +85,28 @@ class t8_single_data_handler { /* tree_data_size */ total_size += int_size; - for (auto ihandler : item.tree_data) { + for (auto ihandler : item->tree_data) { total_size += ihandler->buffer_size (comm) + int_size; } return total_size; } void - pack (const pseudo_tree &data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm) + pack (const pseudo_tree *data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm) { - const int data_size = data.topo_data.size (); + const int data_size = data->topo_data.size (); /* Pack number of topological data */ int mpiret = sc_MPI_Pack (&data_size, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); /* Pack each topological data*/ - mpiret = sc_MPI_Pack ((data.topo_data.data ()), data_size, sc_MPI_INT, buffer, num_bytes, &pos, comm); + mpiret = sc_MPI_Pack ((data->topo_data.data ()), data_size, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); /* Pack number of tree-specific data*/ - const int tree_data_size = data.tree_data.size (); + const int tree_data_size = data->tree_data.size (); mpiret = sc_MPI_Pack (&tree_data_size, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); - for (auto &handler : data.tree_data) { + for (auto &handler : data->tree_data) { const int type = handler->type (); /* Pack type of tree data */ mpiret = sc_MPI_Pack (&type, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); @@ -110,14 +117,14 @@ class t8_single_data_handler { } void - unpack (const void *buffer, const int num_bytes, int &pos, pseudo_tree &data, sc_MPI_Comm comm) + unpack (const void *buffer, const int num_bytes, int &pos, pseudo_tree *data, sc_MPI_Comm comm) { /* Unpack number of topological data */ int topo_data_size = 0; int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &topo_data_size, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); - data.topo_data.resize (topo_data_size); - for (int &topo_item : data.topo_data) { + data->topo_data.resize (topo_data_size); + for (int &topo_item : data->topo_data) { /* Unpack each topological item */ mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &topo_item, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); @@ -127,23 +134,19 @@ class t8_single_data_handler { mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &num_handler, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); - - for (int ihandler = 0; ihandler < num_handler; ihandler++) { int type; - - delete data.tree_data[ihandler]; mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &type, 1, sc_MPI_INT, comm); int outcount = 0; if (type == 0) { t8_data_handler> *new_handler = new t8_data_handler> (); new_handler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); - data.tree_data.push_back(new_handler); + data->tree_data.push_back (new_handler); } else if (type == 1) { t8_data_handler> *new_handler = new t8_data_handler> (); new_handler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); - data.tree_data.push_back(new_handler); + data->tree_data.push_back (new_handler); } else { SC_ABORT_NOT_REACHED (); From b5fcd22058423db218f6230a44064b6feb6643cc Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 27 Sep 2024 10:03:55 +0200 Subject: [PATCH 34/81] fix memory leak --- src/t8_data/t8_data_handler.hxx | 147 +++++++------------------ test/t8_data/t8_gtest_data_handler.cxx | 14 ++- test/t8_data/t8_pseudo_trees.hxx | 29 ++--- 3 files changed, 62 insertions(+), 128 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 7e4f86b016..5b93b583d2 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -27,94 +27,44 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include #include +#include class t8_abstract_data_handler { public: - /** - * Compute the size of a buffer for - * - * \param[in] comm The communicator that will be used. - * \return The size of the buffer in bytes. - */ virtual int buffer_size (sc_MPI_Comm comm) = 0; - - /** - * Pack a vector of items into a buffer. The first integer of the packed data tells how many - * items were packed. - * - * \param[in, out] buffer A vector that will be filled with the packed data. - * Adds a prefix-int for the size. - * \param[in] comm The used communicator - */ + virtual t8_abstract_data_handler * + clone () const + = 0; virtual void pack_vector_prefix (void *buffer, const int num_bytes, int &pos, sc_MPI_Comm comm) = 0; - - /** - * Unpack a buffer into a vector of items. Expects a prefix telling how many items of type T have been packed. - * - * \param[in] buffer The input buffer - * \param[in, out] outcount Number of items that were packed - * \param[in] comm The communicator to use. - */ virtual void unpack_vector_prefix (const void *buffer, const int num_bytes, int &pos, int &outcount, sc_MPI_Comm comm) = 0; - - /** - * Wrapper around a \a data_pack_vector and an sc_MPI_Send. - * Packs the \a data and sends it to rank \a dest using \a tag via \a comm - * - * \param[in] dest The rank we send to. - * \param[in] tag The tag to use during communication - * \param[in] comm The communicator to use. - * \return The result of the mpi-communication - */ virtual int send (const int dest, const int tag, sc_MPI_Comm comm) = 0; - - /** - * Wrapper around an \a sc_MPI_Recv and \a data_unpack. - * Receives and unpackes data coming from \a source. - * - * \param[in] source The rank we receive data from - * \param[in] tag The tag used during communication - * \param[in] comm The communicator to use. - * \param[in] status Status of the MPI-communication - * \param[in, out] outcount After execution it is the number of items of type \a T received. - * \return The result of the mpi communication. - */ virtual int recv (const int source, const int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) = 0; - - /** - * Return the type (as an int) that is handled by this data handler. - * Can be used to call pack/unpack from other data-handlers. - * - * \return int - */ virtual int type () = 0; - virtual ~t8_abstract_data_handler () {}; }; template class t8_data_handler: public t8_abstract_data_handler { public: - t8_data_handler () - { - } + t8_data_handler () = default; - t8_data_handler (const t8_data_handler &other): single_handler (other.single_handler), m_data (other.m_data.size ()) + t8_data_handler (const t8_data_handler &other) { - for (size_t i = 0; i < other.m_data.size (); ++i) { - m_data[i] = new T (*other.m_data[i]); // Deep copy + m_data.reserve (other.m_data.size ()); + for (const auto &item : other.m_data) { + m_data.emplace_back (std::make_unique (*item)); } } @@ -122,32 +72,26 @@ class t8_data_handler: public t8_abstract_data_handler { operator= (const t8_data_handler &other) { if (this != &other) { - single_handler = other.single_handler; - - for (T *item : m_data) { - delete item; - } m_data.clear (); - m_data.resize (other.m_data.size ()); - for (size_t i = 0; i < other.m_data.size (); ++i) { - m_data[i] = new T (*other.m_data[i]); // Deep copy + m_data.reserve (other.m_data.size ()); + for (const auto &item : other.m_data) { + m_data.emplace_back (std::make_unique (*item)); } } return *this; } - t8_data_handler (std::vector &data) + t8_abstract_data_handler * + clone () const override { - // Clear existing data to avoid memory leaks - for (T *item : m_data) { - delete item; - } - m_data.clear (); + return new t8_data_handler (*this); + } - // Resize and copy new data - m_data.resize (data.size ()); - for (size_t i = 0; i < data.size (); ++i) { - m_data[i] = new T (data[i]); // Create new instances of T + t8_data_handler (std::vector &data) + { + m_data.reserve (data.size ()); + for (const auto &item : data) { + m_data.emplace_back (std::make_unique (item)); } } @@ -166,8 +110,8 @@ class t8_data_handler: public t8_abstract_data_handler { int total_size = 0; int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &total_size); SC_CHECK_MPI (mpiret); - for (const auto item : m_data) { - const int size = single_handler.size (item, comm); + for (const auto &item : m_data) { + const int size = single_handler.size (item.get (), comm); total_size += size; } return total_size; @@ -180,27 +124,24 @@ class t8_data_handler: public t8_abstract_data_handler { int mpiret = sc_MPI_Pack (&num_data, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); - for (const auto item : m_data) { - single_handler.pack (item, pos, buffer, num_bytes, comm); + for (const auto &item : m_data) { + single_handler.pack (item.get (), pos, buffer, num_bytes, comm); } } void unpack_vector_prefix (const void *buffer, const int num_bytes, int &pos, int &outcount, sc_MPI_Comm comm) override { - /* Get the number of items we received. */ - const int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &outcount, 1, sc_MPI_INT, comm); + int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &outcount, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); T8_ASSERT (outcount >= 0); - for (T *item : m_data) { - delete item; - } m_data.clear (); - m_data.resize (outcount); + m_data.reserve (outcount); for (int i = 0; i < outcount; ++i) { - m_data[i] = new T (); - single_handler.unpack (buffer, num_bytes, pos, m_data[i], comm); + auto item = std::make_unique (); + single_handler.unpack (buffer, num_bytes, pos, item.get (), comm); + m_data.emplace_back (std::move (item)); } } @@ -210,16 +151,11 @@ class t8_data_handler: public t8_abstract_data_handler { #if T8_ENABLE_MPI int pos = 0; const int num_bytes = buffer_size (comm); - void *buffer = malloc (num_bytes); - pack_vector_prefix (buffer, num_bytes, pos, comm); + std::vector buffer (num_bytes); + pack_vector_prefix (buffer.data (), num_bytes, pos, comm); - const int mpiret = sc_MPI_Send (buffer, num_bytes, sc_MPI_PACKED, dest, tag, comm); + int mpiret = sc_MPI_Send (buffer.data (), num_bytes, sc_MPI_PACKED, dest, tag, comm); SC_CHECK_MPI (mpiret); - free (buffer); - for (T *item : m_data) { - delete item; - } - m_data.clear (); return mpiret; #else t8_infof ("send only available when configured with --enable-mpi\n"); @@ -238,13 +174,11 @@ class t8_data_handler: public t8_abstract_data_handler { int num_bytes; mpiret = sc_MPI_Get_count (status, sc_MPI_PACKED, &num_bytes); SC_CHECK_MPI (mpiret); - void *buffer = malloc (num_bytes); - T8_ASSERT (buffer != NULL); + std::vector buffer (num_bytes); - mpiret = sc_MPI_Recv (buffer, num_bytes, sc_MPI_PACKED, source, tag, comm, status); + mpiret = sc_MPI_Recv (buffer.data (), num_bytes, sc_MPI_PACKED, source, tag, comm, status); SC_CHECK_MPI (mpiret); - unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); - free (buffer); + unpack_vector_prefix (buffer.data (), num_bytes, pos, outcount, comm); return mpiret; #else t8_infof ("recv only available when configured with --enable-mpi\n"); @@ -258,15 +192,10 @@ class t8_data_handler: public t8_abstract_data_handler { return single_handler.type (); } - ~t8_data_handler () override - { - for (T *item : m_data) { - delete item; - } - } + ~t8_data_handler () override = default; private: - std::vector m_data; + std::vector> m_data; t8_single_data_handler single_handler; }; diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 72723bf19d..c34dafe6b0 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -208,14 +208,14 @@ TEST (data_handler_test, pseudo_tree_test) std::iota (tree.topo_data.begin (), tree.topo_data.end (), 0); t8_data_handler> int_handler (int_data); - tree.tree_data.push_back (&int_handler); + tree.tree_data.push_back (std::make_unique>> (int_handler)); pseudo_tree tree_copy (tree); EXPECT_EQ (tree.topo_data.size (), tree_copy.topo_data.size ()); EXPECT_EQ (tree.tree_data.size (), tree_copy.tree_data.size ()); std::vector> copied_data; - ((t8_data_handler> *) (tree_copy.tree_data[0]))->get_data (copied_data); + ((t8_data_handler> *) (tree_copy.tree_data[0].get ()))->get_data (copied_data); for (int idata = 0; idata < num_data; idata++) { EXPECT_EQ (copied_data[idata].data, int_data[idata].data); @@ -228,7 +228,7 @@ TEST (data_handler_test, pseudo_tree_test) EXPECT_EQ (tree.tree_data.size (), tree_equal.tree_data.size ()); std::vector> equal_data; - ((t8_data_handler> *) (tree_equal.tree_data[0]))->get_data (equal_data); + ((t8_data_handler> *) (tree_equal.tree_data[0].get ()))->get_data (equal_data); for (int idata = 0; idata < num_data; idata++) { EXPECT_EQ (equal_data[idata].data, int_data[idata].data); @@ -279,7 +279,7 @@ TEST (data_handler_test, tree_test) new_handler = new t8_data_handler> (double_data); } } - tree.tree_data.push_back (new_handler); + tree.tree_data.push_back (std::unique_ptr (new_handler)); } trees.push_back (tree); } @@ -314,7 +314,8 @@ TEST (data_handler_test, tree_test) for (int itree_data = 0; itree_data < num_recv_tree_data; itree_data++) { if (itree_data == 0) { std::vector> recv_ints; - ((t8_data_handler> *) (recv_trees[itree].tree_data[itree_data]))->get_data (recv_ints); + ((t8_data_handler> *) (recv_trees[itree].tree_data[itree_data].get ())) + ->get_data (recv_ints); ASSERT_EQ ((const int) recv_ints.size (), num_data); for (int idata = 0; idata < num_data; idata++) { EXPECT_EQ (recv_ints[idata].data, idata); @@ -323,7 +324,8 @@ TEST (data_handler_test, tree_test) } else { std::vector> recv_double; - ((t8_data_handler> *) (recv_trees[itree].tree_data[itree_data]))->get_data (recv_double); + dynamic_cast> *> (recv_trees[itree].tree_data[itree_data].get ()) + ->get_data (recv_double); ASSERT_EQ ((const int) recv_double.size (), num_data); for (int idata = 0; idata < num_data; idata++) { EXPECT_EQ (recv_double[idata].data, (double) idata + fraction); diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index 38050e0bae..109dc2852e 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -29,6 +29,8 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include +#include + class pseudo_tree { public: pseudo_tree () @@ -39,7 +41,7 @@ class pseudo_tree { { tree_data.resize (other.tree_data.size ()); for (size_t i = 0; i < other.tree_data.size (); ++i) { - tree_data[i] = other.tree_data[i]; + tree_data[i] = std::unique_ptr (other.tree_data[i]->clone ()); } } @@ -47,27 +49,21 @@ class pseudo_tree { operator= (const pseudo_tree &other) { if (this != &other) { - for (t8_abstract_data_handler *handler : tree_data) { - delete handler; - } tree_data.clear (); topo_data = other.topo_data; tree_data.resize (other.tree_data.size ()); for (size_t i = 0; i < other.tree_data.size (); ++i) { - tree_data[i] = other.tree_data[i]; + tree_data[i] = std::unique_ptr (other.tree_data[i]->clone ()); } } return *this; } - ~pseudo_tree () - { - tree_data.clear (); - } + ~pseudo_tree () = default; std::vector topo_data; - std::vector tree_data; + std::vector> tree_data; }; template <> @@ -85,7 +81,7 @@ class t8_single_data_handler { /* tree_data_size */ total_size += int_size; - for (auto ihandler : item->tree_data) { + for (const auto &ihandler : item->tree_data) { total_size += ihandler->buffer_size (comm) + int_size; } return total_size; @@ -119,6 +115,13 @@ class t8_single_data_handler { void unpack (const void *buffer, const int num_bytes, int &pos, pseudo_tree *data, sc_MPI_Comm comm) { + /* Clear existing tree data */ + for (const auto &handler_ptr : data->tree_data) { + t8_abstract_data_handler *handler = handler_ptr.get (); + delete handler; + } + data->tree_data.clear (); + /* Unpack number of topological data */ int topo_data_size = 0; int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &topo_data_size, 1, sc_MPI_INT, comm); @@ -141,12 +144,12 @@ class t8_single_data_handler { if (type == 0) { t8_data_handler> *new_handler = new t8_data_handler> (); new_handler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); - data->tree_data.push_back (new_handler); + data->tree_data.push_back (std::unique_ptr (new_handler)); } else if (type == 1) { t8_data_handler> *new_handler = new t8_data_handler> (); new_handler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); - data->tree_data.push_back (new_handler); + data->tree_data.push_back (std::unique_ptr (new_handler)); } else { SC_ABORT_NOT_REACHED (); From cfbf37c4f04215c24fd19324dfddb00bb3514218 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 27 Sep 2024 10:31:28 +0200 Subject: [PATCH 35/81] add documentation --- src/t8_data/t8_data_handler.hxx | 90 ++++++++++++++++++++++++++++ src/t8_data/t8_data_handler_base.hxx | 37 ++++++++---- 2 files changed, 117 insertions(+), 10 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 5b93b583d2..07a58454c2 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -31,30 +31,120 @@ along with t8code; if not, write to the Free Software Foundation, Inc., class t8_abstract_data_handler { public: + /** + * Pure virtual function to determine the buffer size. + * + * This function must be implemented by derived classes to calculate + * the size of the buffer required for communication. + * + * \param[in] comm The MPI communicator. + * \return The size of the buffer. + */ virtual int buffer_size (sc_MPI_Comm comm) = 0; + + /** + * Creates a copy of the current data handler. + * + * This pure virtual function must be implemented by derived classes to + * provide a mechanism for cloning the data handler. The cloned object + * should be a deep copy, ensuring that all relevant data is duplicated. + * + * \return A pointer to the newly cloned t8_abstract_data_handler object. + */ virtual t8_abstract_data_handler * clone () const = 0; + + /** + * Packs a vector into a buffer. The vector data will be prefixed with the number of elements in the vector. + * + * This pure virtual function is responsible for packing a vector prefix into the provided buffer. + * + * \param[in, out] buffer A pointer to the buffer where the vector prefix will be packed. + * \param[in] num_bytes The number of bytes to be packed. + * \param[in] pos A reference to an integer representing the current position in the buffer. This will be updated as bytes are packed. + * \param[in] comm The MPI communicator used for the operation. + */ virtual void pack_vector_prefix (void *buffer, const int num_bytes, int &pos, sc_MPI_Comm comm) = 0; + + /** + * Unpacks a vector from a buffer. Expected to be prefixed with the number of elements in the vector. + * + * This pure virtual function is responsible for unpacking a vector prefix from the provided buffer. + * + * \param[in] buffer Pointer to the buffer containing the packed data. + * \param[in] num_bytes The number of bytes in the buffer. + * \param[in] pos Reference to an integer representing the current position in the buffer. This will be updated as data is unpacked. + * \param[in] outcount Reference to an integer where the count of unpacked elements will be stored. + * \param[in] comm The MPI communicator used for the operation. + */ virtual void unpack_vector_prefix (const void *buffer, const int num_bytes, int &pos, int &outcount, sc_MPI_Comm comm) = 0; + + /** + * Pure virtual function to send data to a specified destination. + * + * This function is responsible for packing and sending data to a given destination + * with a specific tag using the provided MPI communicator. + * + * \param[in] dest The destination rank to which the data will be sent. + * \param[in] tag The tag associated with the message to be sent. + * \param[in] comm The MPI communicator used for the communication. + * \return An integer indicating the status of the send operation. + */ virtual int send (const int dest, const int tag, sc_MPI_Comm comm) = 0; + + /** + * Receives a message from a specified source. + * + * This pure virtual function is responsible for receiving and unpacking a message from a given source + * with a specific tag within the provided MPI communicator. The function will also + * update the status and output count of the received message. + * + * \param[in] source The rank of the source process from which the message is received. + * \param[in] tag The tag of the message to be received. + * \param[in] comm The MPI communicator within which the message is received. + * \param[in] status A pointer to an MPI status object that will be updated with the status of the received message. + * \param[in] outcount A reference to an integer that will be updated with the count of received elements. + * \return An integer indicating the success or failure of the receive operation. + */ virtual int recv (const int source, const int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) = 0; + + /** + * Pure virtual function to get the type. + * + * This function must be overridden in derived classes to return the type. + * + * \return An integer representing the type. + */ virtual int type () = 0; + virtual ~t8_abstract_data_handler () {}; }; +/** + * \class t8_data_handler + * A data handler class that manages a collection of data items. + * + * This class provides functionalities to handle a collection of data items + * of type T. It supports cloning, packing, unpacking, sending, and receiving + * data using MPI. + * + * \tparam T The type of data items managed by this handler. + * + * \note This class requires MPI to be enabled for send and receive operations. + */ template class t8_data_handler: public t8_abstract_data_handler { public: diff --git a/src/t8_data/t8_data_handler_base.hxx b/src/t8_data/t8_data_handler_base.hxx index 88344a31c8..c3d17482c5 100644 --- a/src/t8_data/t8_data_handler_base.hxx +++ b/src/t8_data/t8_data_handler_base.hxx @@ -34,23 +34,40 @@ class t8_single_data_handler { size (const T &data, sc_MPI_Comm comm); /** - * Overwrite this routine to describe how data of type T should be packed - * - * \param[in] data Data to be packed via MPI_Pack - * \return the size of the packed data in number of bytes. - */ + * Packs the given data into a buffer for communication. + * + * \tparam T The type of the data to be packed. + * \param[in] data The data to be packed. + * \param[in] pos The current position in the buffer where the data should be packed. + * \param[in, out] buffer The buffer where the data will be packed. + * \param[in] num_bytes The number of bytes available in the buffer. + * \param[in] comm The MPI communicator used for communication. + */ void pack (const T &data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm); /** - * Overwrite this routine to describe how data of type T should be unpacked - * - * \param packed_data A void-pointer to the packed Data - * \return T* the unpacked data. - */ + * Unpacks data from a buffer. + * + * This function unpacks data from a given buffer into the provided data structure. + * + * \tparam T The type of the data to be unpacked. + * \param[in] buffer A pointer to the buffer containing the packed data. + * \param[in] num_bytes The number of bytes in the buffer. + * \param[in] pos A reference to an integer representing the current position in the buffer. + * \param[in, out] data A pointer to the data structure where the unpacked data will be stored. + * \param[in] comm The MPI communicator used for communication. + */ void unpack (const void *buffer, const int num_bytes, int &pos, T *data, sc_MPI_Comm comm); + /** + * Returns the type of the data handler. + * + * This function returns the type of the data handler. + * + * \return An integer representing the type. + */ int type (); From 49cf6ab9d158dd001118eb7969b5c77d3e258a73 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 27 Sep 2024 13:21:47 +0200 Subject: [PATCH 36/81] started to implement different behaviour depending on type --- src/t8_data/t8_data_handler.hxx | 90 +++++++++++++------ src/t8_data/t8_data_handler_base.hxx | 2 +- .../t8_data_packs/t8_enlarged_stdtypes.hxx | 28 +++--- test/t8_data/t8_gtest_data_handler.cxx | 18 ++-- test/t8_data/t8_pseudo_trees.hxx | 47 ++++++---- 5 files changed, 119 insertions(+), 66 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 07a58454c2..5894983e3d 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -28,6 +28,7 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include #include +#include class t8_abstract_data_handler { public: @@ -152,9 +153,14 @@ class t8_data_handler: public t8_abstract_data_handler { t8_data_handler (const t8_data_handler &other) { - m_data.reserve (other.m_data.size ()); - for (const auto &item : other.m_data) { - m_data.emplace_back (std::make_unique (*item)); + if (std::is_pointer_v) { + m_data.reserve (other.m_data.size ()); + for (const auto &item : other.m_data) { + m_data.emplace_back (item); + } + } + else { + m_data = other.m_data; } } @@ -162,10 +168,15 @@ class t8_data_handler: public t8_abstract_data_handler { operator= (const t8_data_handler &other) { if (this != &other) { - m_data.clear (); - m_data.reserve (other.m_data.size ()); - for (const auto &item : other.m_data) { - m_data.emplace_back (std::make_unique (*item)); + if constexpr (std::is_pointer_v) { + m_data.clear (); + m_data.reserve (other.m_data.size ()); + for (const auto &item : other.m_data) { + m_data.emplace_back (item); + } + } + else { + m_data = other.m_data; } } return *this; @@ -179,18 +190,28 @@ class t8_data_handler: public t8_abstract_data_handler { t8_data_handler (std::vector &data) { - m_data.reserve (data.size ()); - for (const auto &item : data) { - m_data.emplace_back (std::make_unique (item)); + if constexpr (std::is_pointer_v) { + m_data.reserve (data.size ()); + for (const auto &item : data) { + m_data.emplace_back (item); + } + } + else { + m_data = data; } } void get_data (std::vector &data) { - data.resize (m_data.size ()); - for (size_t i = 0; i < m_data.size (); ++i) { - data[i] = *m_data[i]; + if constexpr (std::is_pointer_v) { + data.resize (m_data.size ()); + for (size_t i = 0; i < m_data.size (); ++i) { + data[i] = *m_data[i]; + } + } + else { + data = m_data; } } @@ -199,11 +220,21 @@ class t8_data_handler: public t8_abstract_data_handler { { int total_size = 0; int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &total_size); - SC_CHECK_MPI (mpiret); - for (const auto &item : m_data) { - const int size = single_handler.size (item.get (), comm); - total_size += size; + if constexpr (std::is_pointer_v) { + t8_debugf ("[D] pointer type\n"); + SC_CHECK_MPI (mpiret); + for (const auto &item : m_data) { + const int size = single_handler.size (*item, comm); + total_size += size; + } + } + else { + t8_debugf ("[D] non-pointer type\n"); + const int single_size = single_handler.size (m_data[0], comm); + t8_debugf ("[D] single_size: %d\n", single_size); + total_size += single_size * m_data.size (); } + t8_debugf ("[D] buffer_size: %d\n", total_size); return total_size; } @@ -215,7 +246,7 @@ class t8_data_handler: public t8_abstract_data_handler { SC_CHECK_MPI (mpiret); for (const auto &item : m_data) { - single_handler.pack (item.get (), pos, buffer, num_bytes, comm); + single_handler.pack (item, pos, buffer, num_bytes, comm); } } @@ -225,13 +256,20 @@ class t8_data_handler: public t8_abstract_data_handler { int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &outcount, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); T8_ASSERT (outcount >= 0); - - m_data.clear (); - m_data.reserve (outcount); - for (int i = 0; i < outcount; ++i) { - auto item = std::make_unique (); - single_handler.unpack (buffer, num_bytes, pos, item.get (), comm); - m_data.emplace_back (std::move (item)); + if constexpr (std::is_pointer_v) { + m_data.clear (); + m_data.reserve (outcount); + for (int i = 0; i < outcount; ++i) { + auto item = new T (); + single_handler.unpack (buffer, num_bytes, pos, item, comm); + m_data.emplace_back (std::move (item)); + } + } + else { + m_data.resize (outcount); + for (int i = 0; i < outcount; ++i) { + single_handler.unpack (buffer, num_bytes, pos, m_data[i], comm); + } } } @@ -285,7 +323,7 @@ class t8_data_handler: public t8_abstract_data_handler { ~t8_data_handler () override = default; private: - std::vector> m_data; + std::vector m_data; t8_single_data_handler single_handler; }; diff --git a/src/t8_data/t8_data_handler_base.hxx b/src/t8_data/t8_data_handler_base.hxx index c3d17482c5..413309cd82 100644 --- a/src/t8_data/t8_data_handler_base.hxx +++ b/src/t8_data/t8_data_handler_base.hxx @@ -59,7 +59,7 @@ class t8_single_data_handler { * \param[in] comm The MPI communicator used for communication. */ void - unpack (const void *buffer, const int num_bytes, int &pos, T *data, sc_MPI_Comm comm); + unpack (const void *buffer, const int num_bytes, int &pos, T &data, sc_MPI_Comm comm); /** * Returns the type of the data handler. diff --git a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx index 16f8479e1f..30c06ea344 100644 --- a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx +++ b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx @@ -32,7 +32,7 @@ template <> class t8_single_data_handler> { public: int - size (const enlarged_data *item, sc_MPI_Comm comm) + size (const enlarged_data &item, sc_MPI_Comm comm) { int size; const int mpiret = sc_MPI_Pack_size (2, sc_MPI_INT, comm, &size); @@ -41,22 +41,22 @@ class t8_single_data_handler> { } void - pack (const enlarged_data *data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm) + pack (const enlarged_data &data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm) { - int mpiret = sc_MPI_Pack (&(data->data), 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); + int mpiret = sc_MPI_Pack (&(data.data), 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); - mpiret = sc_MPI_Pack (&(data->check), 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); + mpiret = sc_MPI_Pack (&(data.check), 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); } void - unpack (const void *buffer, const int num_bytes, int &pos, enlarged_data *data, sc_MPI_Comm comm) + unpack (const void *buffer, const int num_bytes, int &pos, enlarged_data &data, sc_MPI_Comm comm) { - int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &(data->data), 1, sc_MPI_INT, comm); + int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &(data.data), 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); - mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &(data->check), 1, sc_MPI_INT, comm); + mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &(data.check), 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); } @@ -71,7 +71,7 @@ template <> class t8_single_data_handler> { public: int - size (const enlarged_data *item, sc_MPI_Comm comm) + size (const enlarged_data &item, sc_MPI_Comm comm) { int int_size; int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &int_size); @@ -83,22 +83,22 @@ class t8_single_data_handler> { } void - pack (const enlarged_data *data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm) + pack (const enlarged_data &data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm) { - int mpiret = sc_MPI_Pack (&(data->data), 1, sc_MPI_DOUBLE, buffer, num_bytes, &pos, comm); + int mpiret = sc_MPI_Pack (&(data.data), 1, sc_MPI_DOUBLE, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); - mpiret = sc_MPI_Pack (&(data->check), 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); + mpiret = sc_MPI_Pack (&(data.check), 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); } void - unpack (const void *buffer, const int num_bytes, int &pos, enlarged_data *data, sc_MPI_Comm comm) + unpack (const void *buffer, const int num_bytes, int &pos, enlarged_data &data, sc_MPI_Comm comm) { - int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &(data->data), 1, sc_MPI_DOUBLE, comm); + int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &(data.data), 1, sc_MPI_DOUBLE, comm); SC_CHECK_MPI (mpiret); - mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &(data->check), 1, sc_MPI_INT, comm); + mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &(data.check), 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); } diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index c34dafe6b0..db9b4c016b 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -252,7 +252,7 @@ TEST (data_handler_test, tree_test) const double fraction = 0.42; - std::vector trees; + std::vector> trees; for (int itree = 0; itree < num_trees; itree++) { pseudo_tree tree; @@ -281,9 +281,9 @@ TEST (data_handler_test, tree_test) } tree.tree_data.push_back (std::unique_ptr (new_handler)); } - trees.push_back (tree); + trees.push_back (std::unique_ptr (new pseudo_tree (tree))); } - t8_data_handler tree_handler (trees); + t8_data_handler> tree_handler (trees); const int send_to = (mpirank + 1) % mpisize; const int recv_from = (mpirank == 0) ? (mpisize - 1) : (mpirank - 1); @@ -294,7 +294,7 @@ TEST (data_handler_test, tree_test) int outcount; mpiret = tree_handler.recv (recv_from, 0, comm, &status, outcount); - std::vector recv_trees; + std::vector> recv_trees; tree_handler.get_data (recv_trees); const int num_recv_trees = recv_trees.size (); @@ -302,19 +302,19 @@ TEST (data_handler_test, tree_test) ASSERT_EQ (num_recv_trees, ((recv_from) % 4) * 10); for (int itree = 0; itree < num_recv_trees; itree++) { - const int num_recv_tree_topo_size = recv_trees[itree].topo_data.size (); + const int num_recv_tree_topo_size = recv_trees[itree]->topo_data.size (); ASSERT_EQ (num_recv_tree_topo_size, ((recv_from % 3) + 1) * 10); for (int itopo_data = 0; itopo_data < num_recv_tree_topo_size; itopo_data++) { - EXPECT_EQ (recv_trees[itree].topo_data[itopo_data], itopo_data); + EXPECT_EQ (recv_trees[itree]->topo_data[itopo_data], itopo_data); } - const int num_recv_tree_data = recv_trees[itree].tree_data.size (); + const int num_recv_tree_data = recv_trees[itree]->tree_data.size (); ASSERT_EQ (num_recv_tree_data, (recv_from + itree) % 2); for (int itree_data = 0; itree_data < num_recv_tree_data; itree_data++) { if (itree_data == 0) { std::vector> recv_ints; - ((t8_data_handler> *) (recv_trees[itree].tree_data[itree_data].get ())) + dynamic_cast> *> (recv_trees[itree]->tree_data[itree_data].get ()) ->get_data (recv_ints); ASSERT_EQ ((const int) recv_ints.size (), num_data); for (int idata = 0; idata < num_data; idata++) { @@ -324,7 +324,7 @@ TEST (data_handler_test, tree_test) } else { std::vector> recv_double; - dynamic_cast> *> (recv_trees[itree].tree_data[itree_data].get ()) + dynamic_cast> *> (recv_trees[itree]->tree_data[itree_data].get ()) ->get_data (recv_double); ASSERT_EQ ((const int) recv_double.size (), num_data); for (int idata = 0; idata < num_data; idata++) { diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index 109dc2852e..2cdd54c782 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -31,6 +31,21 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include +/** + * \class pseudo_tree + * A class representing a pseudo tree structure. + * + * The pseudo_tree class encapsulates a tree-like structure with topology data and tree data. + * It provides constructors, assignment operator, and destructor for managing the tree data. + * + * It is meant for testing purposes only and to mimic the structure of a tree. + * + * \var std::vector pseudo_tree::topo_data + * A vector containing the topology data of the pseudo tree. + * + * \var std::vector> pseudo_tree::tree_data + * A vector of unique pointers to t8_abstract_data_handler objects representing the tree data. + */ class pseudo_tree { public: pseudo_tree () @@ -70,39 +85,39 @@ template <> class t8_single_data_handler { public: int - size (const pseudo_tree *item, sc_MPI_Comm comm) + size (const pseudo_tree &item, sc_MPI_Comm comm) { int int_size = 0; - const int topo_data_size = item->topo_data.size () + 1; + const int topo_data_size = item.topo_data.size () + 1; - const int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &int_size); + int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &int_size); SC_CHECK_MPI (mpiret); int total_size = topo_data_size * int_size; /* tree_data_size */ total_size += int_size; - for (const auto &ihandler : item->tree_data) { + for (const auto &ihandler : item.tree_data) { total_size += ihandler->buffer_size (comm) + int_size; } return total_size; } void - pack (const pseudo_tree *data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm) + pack (const pseudo_tree &data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm) { - const int data_size = data->topo_data.size (); + const int data_size = data.topo_data.size (); /* Pack number of topological data */ int mpiret = sc_MPI_Pack (&data_size, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); /* Pack each topological data*/ - mpiret = sc_MPI_Pack ((data->topo_data.data ()), data_size, sc_MPI_INT, buffer, num_bytes, &pos, comm); + mpiret = sc_MPI_Pack ((data.topo_data.data ()), data_size, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); /* Pack number of tree-specific data*/ - const int tree_data_size = data->tree_data.size (); + const int tree_data_size = data.tree_data.size (); mpiret = sc_MPI_Pack (&tree_data_size, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); - for (auto &handler : data->tree_data) { + for (auto &handler : data.tree_data) { const int type = handler->type (); /* Pack type of tree data */ mpiret = sc_MPI_Pack (&type, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); @@ -113,21 +128,21 @@ class t8_single_data_handler { } void - unpack (const void *buffer, const int num_bytes, int &pos, pseudo_tree *data, sc_MPI_Comm comm) + unpack (const void *buffer, const int num_bytes, int &pos, pseudo_tree &data, sc_MPI_Comm comm) { /* Clear existing tree data */ - for (const auto &handler_ptr : data->tree_data) { + for (const auto &handler_ptr : data.tree_data) { t8_abstract_data_handler *handler = handler_ptr.get (); delete handler; } - data->tree_data.clear (); + data.tree_data.clear (); /* Unpack number of topological data */ int topo_data_size = 0; int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &topo_data_size, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); - data->topo_data.resize (topo_data_size); - for (int &topo_item : data->topo_data) { + data.topo_data.resize (topo_data_size); + for (int &topo_item : data.topo_data) { /* Unpack each topological item */ mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &topo_item, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); @@ -144,12 +159,12 @@ class t8_single_data_handler { if (type == 0) { t8_data_handler> *new_handler = new t8_data_handler> (); new_handler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); - data->tree_data.push_back (std::unique_ptr (new_handler)); + data.tree_data.push_back (std::unique_ptr (new_handler)); } else if (type == 1) { t8_data_handler> *new_handler = new t8_data_handler> (); new_handler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); - data->tree_data.push_back (std::unique_ptr (new_handler)); + data.tree_data.push_back (std::unique_ptr (new_handler)); } else { SC_ABORT_NOT_REACHED (); From b0bc6ec7fa6dbcee7bbe2b5a42741e634d859598 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 27 Sep 2024 14:55:06 +0200 Subject: [PATCH 37/81] Provide implementation for unique_ptr --- src/t8_data/t8_data_handler.hxx | 217 +++++++++++++++++-------- test/t8_data/t8_gtest_data_handler.cxx | 16 +- test/t8_data/t8_pseudo_trees.hxx | 30 ++-- 3 files changed, 174 insertions(+), 89 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 5894983e3d..458482b65c 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -153,31 +153,14 @@ class t8_data_handler: public t8_abstract_data_handler { t8_data_handler (const t8_data_handler &other) { - if (std::is_pointer_v) { - m_data.reserve (other.m_data.size ()); - for (const auto &item : other.m_data) { - m_data.emplace_back (item); - } - } - else { - m_data = other.m_data; - } + m_data = other.m_data; } t8_data_handler & operator= (const t8_data_handler &other) { if (this != &other) { - if constexpr (std::is_pointer_v) { - m_data.clear (); - m_data.reserve (other.m_data.size ()); - for (const auto &item : other.m_data) { - m_data.emplace_back (item); - } - } - else { - m_data = other.m_data; - } + m_data = other.m_data; } return *this; } @@ -190,29 +173,13 @@ class t8_data_handler: public t8_abstract_data_handler { t8_data_handler (std::vector &data) { - if constexpr (std::is_pointer_v) { - m_data.reserve (data.size ()); - for (const auto &item : data) { - m_data.emplace_back (item); - } - } - else { - m_data = data; - } + m_data = data; } void get_data (std::vector &data) { - if constexpr (std::is_pointer_v) { - data.resize (m_data.size ()); - for (size_t i = 0; i < m_data.size (); ++i) { - data[i] = *m_data[i]; - } - } - else { - data = m_data; - } + data = m_data; } int @@ -220,21 +187,8 @@ class t8_data_handler: public t8_abstract_data_handler { { int total_size = 0; int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &total_size); - if constexpr (std::is_pointer_v) { - t8_debugf ("[D] pointer type\n"); - SC_CHECK_MPI (mpiret); - for (const auto &item : m_data) { - const int size = single_handler.size (*item, comm); - total_size += size; - } - } - else { - t8_debugf ("[D] non-pointer type\n"); - const int single_size = single_handler.size (m_data[0], comm); - t8_debugf ("[D] single_size: %d\n", single_size); - total_size += single_size * m_data.size (); - } - t8_debugf ("[D] buffer_size: %d\n", total_size); + const int single_size = single_handler.size (m_data[0], comm); + total_size += single_size * m_data.size (); return total_size; } @@ -256,20 +210,9 @@ class t8_data_handler: public t8_abstract_data_handler { int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &outcount, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); T8_ASSERT (outcount >= 0); - if constexpr (std::is_pointer_v) { - m_data.clear (); - m_data.reserve (outcount); - for (int i = 0; i < outcount; ++i) { - auto item = new T (); - single_handler.unpack (buffer, num_bytes, pos, item, comm); - m_data.emplace_back (std::move (item)); - } - } - else { - m_data.resize (outcount); - for (int i = 0; i < outcount; ++i) { - single_handler.unpack (buffer, num_bytes, pos, m_data[i], comm); - } + m_data.resize (outcount); + for (auto &item : m_data) { + single_handler.unpack (buffer, num_bytes, pos, item, comm); } } @@ -327,4 +270,146 @@ class t8_data_handler: public t8_abstract_data_handler { t8_single_data_handler single_handler; }; +template +class t8_data_handler> { + public: + t8_data_handler () = default; + + t8_data_handler (const t8_data_handler &other) + { + m_data.reserve (other.m_data.size ()); + for (const auto &item : other.m_data) { + m_data.emplace_back (item->clone ()); + } + } + + t8_data_handler & + operator= (const t8_data_handler &other) + { + if (this != &other) { + m_data.clear (); + m_data.reserve (other.m_data.size ()); + for (const auto &item : other.m_data) { + m_data.emplace_back (item->clone ()); + } + } + return *this; + } + + t8_abstract_data_handler * + clone () const + { + return new t8_data_handler> (*this); + } + + t8_data_handler (std::vector &data) + { + m_data.reserve (data.size ()); + for (const auto &item : data) { + m_data.emplace_back (std::make_unique (item)); + } + } + + void + get_data (std::vector &data) + { + data.resize (m_data.size ()); + for (size_t i = 0; i < m_data.size (); ++i) { + data[i] = *m_data[i]; + } + } + + int + buffer_size (sc_MPI_Comm comm) + { + int total_size = 0; + int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &total_size); + SC_CHECK_MPI (mpiret); + for (const auto &item : m_data) { + const int size = single_handler.size (item.get (), comm); + total_size += size; + } + return total_size; + } + + void + pack_vector_prefix (void *buffer, const int num_bytes, int &pos, sc_MPI_Comm comm) + { + const int num_data = m_data.size (); + int mpiret = sc_MPI_Pack (&num_data, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); + SC_CHECK_MPI (mpiret); + + for (const auto &item : m_data) { + single_handler.pack (item.get (), pos, buffer, num_bytes, comm); + } + } + + void + unpack_vector_prefix (const void *buffer, const int num_bytes, int &pos, int &outcount, sc_MPI_Comm comm) + { + int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &outcount, 1, sc_MPI_INT, comm); + SC_CHECK_MPI (mpiret); + T8_ASSERT (outcount >= 0); + + m_data.clear (); + m_data.reserve (outcount); + for (int i = 0; i < outcount; ++i) { + auto item = std::make_unique (); + single_handler.unpack (buffer, num_bytes, pos, item.get (), comm); + m_data.emplace_back (std::move (item)); + } + } + + int + send (const int dest, const int tag, sc_MPI_Comm comm) + { +#if T8_ENABLE_MPI + int pos = 0; + const int num_bytes = buffer_size (comm); + std::vector buffer (num_bytes); + pack_vector_prefix (buffer.data (), num_bytes, pos, comm); + + int mpiret = sc_MPI_Send (buffer.data (), num_bytes, sc_MPI_PACKED, dest, tag, comm); + SC_CHECK_MPI (mpiret); + return mpiret; +#else + t8_infof ("send only available when configured with --enable-mpi\n"); + return sc_MPI_ERR_OTHER; +#endif + } + + int + recv (const int source, const int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) + { +#if T8_ENABLE_MPI + int pos = 0; + int mpiret = sc_MPI_Probe (source, tag, comm, status); + SC_CHECK_MPI (mpiret); + + int num_bytes; + mpiret = sc_MPI_Get_count (status, sc_MPI_PACKED, &num_bytes); + SC_CHECK_MPI (mpiret); + std::vector buffer (num_bytes); + + mpiret = sc_MPI_Recv (buffer.data (), num_bytes, sc_MPI_PACKED, source, tag, comm, status); + SC_CHECK_MPI (mpiret); + unpack_vector_prefix (buffer.data (), num_bytes, pos, outcount, comm); + return mpiret; +#else + t8_infof ("recv only available when configured with --enable-mpi\n"); + return sc_MPI_ERR_OTHER; +#endif + } + + int + type () + { + return single_handler.type (); + } + + private: + std::vector> m_data; + t8_single_data_handler single_handler; +}; + #endif /* T8_DATA_HANDLER_HXX */ diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index db9b4c016b..96df00cc8d 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -252,7 +252,7 @@ TEST (data_handler_test, tree_test) const double fraction = 0.42; - std::vector> trees; + std::vector trees; for (int itree = 0; itree < num_trees; itree++) { pseudo_tree tree; @@ -281,7 +281,7 @@ TEST (data_handler_test, tree_test) } tree.tree_data.push_back (std::unique_ptr (new_handler)); } - trees.push_back (std::unique_ptr (new pseudo_tree (tree))); + trees.push_back (tree); } t8_data_handler> tree_handler (trees); @@ -294,7 +294,7 @@ TEST (data_handler_test, tree_test) int outcount; mpiret = tree_handler.recv (recv_from, 0, comm, &status, outcount); - std::vector> recv_trees; + std::vector recv_trees; tree_handler.get_data (recv_trees); const int num_recv_trees = recv_trees.size (); @@ -302,19 +302,19 @@ TEST (data_handler_test, tree_test) ASSERT_EQ (num_recv_trees, ((recv_from) % 4) * 10); for (int itree = 0; itree < num_recv_trees; itree++) { - const int num_recv_tree_topo_size = recv_trees[itree]->topo_data.size (); + const int num_recv_tree_topo_size = recv_trees[itree].topo_data.size (); ASSERT_EQ (num_recv_tree_topo_size, ((recv_from % 3) + 1) * 10); for (int itopo_data = 0; itopo_data < num_recv_tree_topo_size; itopo_data++) { - EXPECT_EQ (recv_trees[itree]->topo_data[itopo_data], itopo_data); + EXPECT_EQ (recv_trees[itree].topo_data[itopo_data], itopo_data); } - const int num_recv_tree_data = recv_trees[itree]->tree_data.size (); + const int num_recv_tree_data = recv_trees[itree].tree_data.size (); ASSERT_EQ (num_recv_tree_data, (recv_from + itree) % 2); for (int itree_data = 0; itree_data < num_recv_tree_data; itree_data++) { if (itree_data == 0) { std::vector> recv_ints; - dynamic_cast> *> (recv_trees[itree]->tree_data[itree_data].get ()) + dynamic_cast> *> (recv_trees[itree].tree_data[itree_data].get ()) ->get_data (recv_ints); ASSERT_EQ ((const int) recv_ints.size (), num_data); for (int idata = 0; idata < num_data; idata++) { @@ -324,7 +324,7 @@ TEST (data_handler_test, tree_test) } else { std::vector> recv_double; - dynamic_cast> *> (recv_trees[itree]->tree_data[itree_data].get ()) + dynamic_cast> *> (recv_trees[itree].tree_data[itree_data].get ()) ->get_data (recv_double); ASSERT_EQ ((const int) recv_double.size (), num_data); for (int idata = 0; idata < num_data; idata++) { diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index 2cdd54c782..9ec832c199 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -85,10 +85,10 @@ template <> class t8_single_data_handler { public: int - size (const pseudo_tree &item, sc_MPI_Comm comm) + size (const pseudo_tree *item, sc_MPI_Comm comm) { int int_size = 0; - const int topo_data_size = item.topo_data.size () + 1; + const int topo_data_size = item->topo_data.size () + 1; int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &int_size); SC_CHECK_MPI (mpiret); @@ -96,28 +96,28 @@ class t8_single_data_handler { /* tree_data_size */ total_size += int_size; - for (const auto &ihandler : item.tree_data) { + for (const auto &ihandler : item->tree_data) { total_size += ihandler->buffer_size (comm) + int_size; } return total_size; } void - pack (const pseudo_tree &data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm) + pack (const pseudo_tree *data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm) { - const int data_size = data.topo_data.size (); + const int data_size = data->topo_data.size (); /* Pack number of topological data */ int mpiret = sc_MPI_Pack (&data_size, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); /* Pack each topological data*/ - mpiret = sc_MPI_Pack ((data.topo_data.data ()), data_size, sc_MPI_INT, buffer, num_bytes, &pos, comm); + mpiret = sc_MPI_Pack ((data->topo_data.data ()), data_size, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); /* Pack number of tree-specific data*/ - const int tree_data_size = data.tree_data.size (); + const int tree_data_size = data->tree_data.size (); mpiret = sc_MPI_Pack (&tree_data_size, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); - for (auto &handler : data.tree_data) { + for (auto &handler : data->tree_data) { const int type = handler->type (); /* Pack type of tree data */ mpiret = sc_MPI_Pack (&type, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); @@ -128,21 +128,21 @@ class t8_single_data_handler { } void - unpack (const void *buffer, const int num_bytes, int &pos, pseudo_tree &data, sc_MPI_Comm comm) + unpack (const void *buffer, const int num_bytes, int &pos, pseudo_tree *data, sc_MPI_Comm comm) { /* Clear existing tree data */ - for (const auto &handler_ptr : data.tree_data) { + for (const auto &handler_ptr : data->tree_data) { t8_abstract_data_handler *handler = handler_ptr.get (); delete handler; } - data.tree_data.clear (); + data->tree_data.clear (); /* Unpack number of topological data */ int topo_data_size = 0; int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &topo_data_size, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); - data.topo_data.resize (topo_data_size); - for (int &topo_item : data.topo_data) { + data->topo_data.resize (topo_data_size); + for (int &topo_item : data->topo_data) { /* Unpack each topological item */ mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &topo_item, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); @@ -159,12 +159,12 @@ class t8_single_data_handler { if (type == 0) { t8_data_handler> *new_handler = new t8_data_handler> (); new_handler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); - data.tree_data.push_back (std::unique_ptr (new_handler)); + data->tree_data.push_back (std::unique_ptr (new_handler)); } else if (type == 1) { t8_data_handler> *new_handler = new t8_data_handler> (); new_handler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); - data.tree_data.push_back (std::unique_ptr (new_handler)); + data->tree_data.push_back (std::unique_ptr (new_handler)); } else { SC_ABORT_NOT_REACHED (); From de2b97f225488de13374941cfb3104e2a67eeeef Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 27 Sep 2024 14:57:26 +0200 Subject: [PATCH 38/81] improve for pointer-type --- src/t8_data/t8_data_handler.hxx | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 458482b65c..7b7d88adc8 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -151,20 +151,6 @@ class t8_data_handler: public t8_abstract_data_handler { public: t8_data_handler () = default; - t8_data_handler (const t8_data_handler &other) - { - m_data = other.m_data; - } - - t8_data_handler & - operator= (const t8_data_handler &other) - { - if (this != &other) { - m_data = other.m_data; - } - return *this; - } - t8_abstract_data_handler * clone () const override { From 5bc39834642f370e01ed4857a8de673537641c10 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 27 Sep 2024 15:34:51 +0200 Subject: [PATCH 39/81] minor improvements --- src/t8_data/t8_data_handler.hxx | 25 +++++++++++++++++++------ test/t8_data/t8_pseudo_trees.hxx | 12 ++++++------ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 7b7d88adc8..88ddcdae13 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -151,6 +151,20 @@ class t8_data_handler: public t8_abstract_data_handler { public: t8_data_handler () = default; + t8_data_handler (const t8_data_handler &other) + { + m_data = other.m_data; + } + + t8_data_handler & + operator= (const t8_data_handler &other) + { + if (this != &other) { + m_data = other.m_data; + } + return *this; + } + t8_abstract_data_handler * clone () const override { @@ -172,17 +186,16 @@ class t8_data_handler: public t8_abstract_data_handler { buffer_size (sc_MPI_Comm comm) override { int total_size = 0; - int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &total_size); - const int single_size = single_handler.size (m_data[0], comm); - total_size += single_size * m_data.size (); - return total_size; + const int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &total_size); + SC_CHECK_MPI (mpiret); + return total_size + single_handler.size (m_data[0], comm) * m_data.size (); } void pack_vector_prefix (void *buffer, const int num_bytes, int &pos, sc_MPI_Comm comm) override { const int num_data = m_data.size (); - int mpiret = sc_MPI_Pack (&num_data, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); + const int mpiret = sc_MPI_Pack (&num_data, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); for (const auto &item : m_data) { @@ -193,7 +206,7 @@ class t8_data_handler: public t8_abstract_data_handler { void unpack_vector_prefix (const void *buffer, const int num_bytes, int &pos, int &outcount, sc_MPI_Comm comm) override { - int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &outcount, 1, sc_MPI_INT, comm); + const int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &outcount, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); T8_ASSERT (outcount >= 0); m_data.resize (outcount); diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index 9ec832c199..b0767ce30f 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -157,14 +157,14 @@ class t8_single_data_handler { mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &type, 1, sc_MPI_INT, comm); int outcount = 0; if (type == 0) { - t8_data_handler> *new_handler = new t8_data_handler> (); - new_handler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); - data->tree_data.push_back (std::unique_ptr (new_handler)); + auto new_handler = std::make_unique>>(); + new_handler->unpack_vector_prefix(buffer, num_bytes, pos, outcount, comm); + data->tree_data.push_back(std::move(new_handler)); } else if (type == 1) { - t8_data_handler> *new_handler = new t8_data_handler> (); - new_handler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); - data->tree_data.push_back (std::unique_ptr (new_handler)); + auto new_handler = std::make_unique>>(); + new_handler->unpack_vector_prefix(buffer, num_bytes, pos, outcount, comm); + data->tree_data.push_back(std::move(new_handler)); } else { SC_ABORT_NOT_REACHED (); From def4cbb5dd97f0533b8693ee69fa99b034350908 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Mon, 30 Sep 2024 10:19:10 +0200 Subject: [PATCH 40/81] minor optimization --- src/t8_data/t8_data_handler.hxx | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 88ddcdae13..888809dae5 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -224,7 +224,7 @@ class t8_data_handler: public t8_abstract_data_handler { std::vector buffer (num_bytes); pack_vector_prefix (buffer.data (), num_bytes, pos, comm); - int mpiret = sc_MPI_Send (buffer.data (), num_bytes, sc_MPI_PACKED, dest, tag, comm); + const int mpiret = sc_MPI_Send (buffer.data (), num_bytes, sc_MPI_PACKED, dest, tag, comm); SC_CHECK_MPI (mpiret); return mpiret; #else @@ -270,7 +270,7 @@ class t8_data_handler: public t8_abstract_data_handler { }; template -class t8_data_handler> { +class t8_data_handler>: public t8_abstract_data_handler { public: t8_data_handler () = default; @@ -278,7 +278,7 @@ class t8_data_handler> { { m_data.reserve (other.m_data.size ()); for (const auto &item : other.m_data) { - m_data.emplace_back (item->clone ()); + m_data.emplace_back (std::make_unique (*item)); } } @@ -289,14 +289,14 @@ class t8_data_handler> { m_data.clear (); m_data.reserve (other.m_data.size ()); for (const auto &item : other.m_data) { - m_data.emplace_back (item->clone ()); + m_data.emplace_back (std::make_unique (*item)); } } return *this; } t8_abstract_data_handler * - clone () const + clone () const override { return new t8_data_handler> (*this); } @@ -319,10 +319,10 @@ class t8_data_handler> { } int - buffer_size (sc_MPI_Comm comm) + buffer_size (sc_MPI_Comm comm) override { int total_size = 0; - int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &total_size); + const int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &total_size); SC_CHECK_MPI (mpiret); for (const auto &item : m_data) { const int size = single_handler.size (item.get (), comm); @@ -332,10 +332,10 @@ class t8_data_handler> { } void - pack_vector_prefix (void *buffer, const int num_bytes, int &pos, sc_MPI_Comm comm) + pack_vector_prefix (void *buffer, const int num_bytes, int &pos, sc_MPI_Comm comm) override { const int num_data = m_data.size (); - int mpiret = sc_MPI_Pack (&num_data, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); + const int mpiret = sc_MPI_Pack (&num_data, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); for (const auto &item : m_data) { @@ -344,9 +344,9 @@ class t8_data_handler> { } void - unpack_vector_prefix (const void *buffer, const int num_bytes, int &pos, int &outcount, sc_MPI_Comm comm) + unpack_vector_prefix (const void *buffer, const int num_bytes, int &pos, int &outcount, sc_MPI_Comm comm) override { - int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &outcount, 1, sc_MPI_INT, comm); + const int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &outcount, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); T8_ASSERT (outcount >= 0); @@ -360,7 +360,7 @@ class t8_data_handler> { } int - send (const int dest, const int tag, sc_MPI_Comm comm) + send (const int dest, const int tag, sc_MPI_Comm comm) override { #if T8_ENABLE_MPI int pos = 0; @@ -368,7 +368,7 @@ class t8_data_handler> { std::vector buffer (num_bytes); pack_vector_prefix (buffer.data (), num_bytes, pos, comm); - int mpiret = sc_MPI_Send (buffer.data (), num_bytes, sc_MPI_PACKED, dest, tag, comm); + const int mpiret = sc_MPI_Send (buffer.data (), num_bytes, sc_MPI_PACKED, dest, tag, comm); SC_CHECK_MPI (mpiret); return mpiret; #else @@ -378,7 +378,7 @@ class t8_data_handler> { } int - recv (const int source, const int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) + recv (const int source, const int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) override { #if T8_ENABLE_MPI int pos = 0; @@ -401,11 +401,13 @@ class t8_data_handler> { } int - type () + type () override { return single_handler.type (); } + ~t8_data_handler () override = default; + private: std::vector> m_data; t8_single_data_handler single_handler; From 0f602719fc5f58cb5da43cf7a247530358384fc4 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Mon, 30 Sep 2024 11:14:31 +0200 Subject: [PATCH 41/81] avoid copying the vector --- src/t8_data/t8_data_handler.hxx | 51 +++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 888809dae5..d37a5375b8 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -149,18 +149,31 @@ class t8_abstract_data_handler { template class t8_data_handler: public t8_abstract_data_handler { public: - t8_data_handler () = default; + t8_data_handler (): single_handler () + { + m_data = nullptr; + } t8_data_handler (const t8_data_handler &other) { - m_data = other.m_data; + if (other.m_data) { + m_data = std::make_unique> (*other.m_data); + } + else { + m_data = nullptr; + } } t8_data_handler & operator= (const t8_data_handler &other) { if (this != &other) { - m_data = other.m_data; + if (other.m_data) { + m_data = std::make_unique> (*other.m_data); + } + else { + m_data.reset (); + } } return *this; } @@ -171,15 +184,20 @@ class t8_data_handler: public t8_abstract_data_handler { return new t8_data_handler (*this); } - t8_data_handler (std::vector &data) + t8_data_handler (const std::vector &data) { - m_data = data; + m_data = std::make_unique> (data); } void get_data (std::vector &data) { - data = m_data; + if (m_data) { + data = *m_data; + } + else { + data.clear (); + } } int @@ -188,17 +206,23 @@ class t8_data_handler: public t8_abstract_data_handler { int total_size = 0; const int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &total_size); SC_CHECK_MPI (mpiret); - return total_size + single_handler.size (m_data[0], comm) * m_data.size (); + if (m_data) { + return total_size + this->single_handler.size (m_data->at (0), comm) * m_data->size (); + } + else { + SC_ABORT_NOT_REACHED (); + return -1; + } } void pack_vector_prefix (void *buffer, const int num_bytes, int &pos, sc_MPI_Comm comm) override { - const int num_data = m_data.size (); + const int num_data = m_data->size (); const int mpiret = sc_MPI_Pack (&num_data, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); - for (const auto &item : m_data) { + for (const auto &item : *m_data) { single_handler.pack (item, pos, buffer, num_bytes, comm); } } @@ -209,8 +233,11 @@ class t8_data_handler: public t8_abstract_data_handler { const int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &outcount, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); T8_ASSERT (outcount >= 0); - m_data.resize (outcount); - for (auto &item : m_data) { + if (!m_data) { + m_data = std::make_unique> (); + } + m_data->resize (outcount); + for (auto &item : *m_data) { single_handler.unpack (buffer, num_bytes, pos, item, comm); } } @@ -265,7 +292,7 @@ class t8_data_handler: public t8_abstract_data_handler { ~t8_data_handler () override = default; private: - std::vector m_data; + std::unique_ptr> m_data; t8_single_data_handler single_handler; }; From 67b413d8d4a918144568457b25a1d33c132eebe1 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Mon, 30 Sep 2024 13:12:38 +0200 Subject: [PATCH 42/81] Simplify data_handler --- src/t8_data/t8_data_handler.hxx | 158 ++----------------------- test/t8_data/t8_gtest_data_handler.cxx | 2 +- test/t8_data/t8_pseudo_trees.hxx | 40 +++---- 3 files changed, 29 insertions(+), 171 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index d37a5375b8..29f36000c9 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -207,12 +207,13 @@ class t8_data_handler: public t8_abstract_data_handler { const int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &total_size); SC_CHECK_MPI (mpiret); if (m_data) { - return total_size + this->single_handler.size (m_data->at (0), comm) * m_data->size (); - } - else { - SC_ABORT_NOT_REACHED (); - return -1; + if (m_data) { + for (const auto &item : *m_data) { + total_size += single_handler.size (item, comm); + } + } } + return total_size; } void @@ -289,154 +290,15 @@ class t8_data_handler: public t8_abstract_data_handler { return single_handler.type (); } - ~t8_data_handler () override = default; - - private: - std::unique_ptr> m_data; - t8_single_data_handler single_handler; -}; - -template -class t8_data_handler>: public t8_abstract_data_handler { - public: - t8_data_handler () = default; - - t8_data_handler (const t8_data_handler &other) - { - m_data.reserve (other.m_data.size ()); - for (const auto &item : other.m_data) { - m_data.emplace_back (std::make_unique (*item)); - } - } - - t8_data_handler & - operator= (const t8_data_handler &other) + ~t8_data_handler () override { - if (this != &other) { - m_data.clear (); - m_data.reserve (other.m_data.size ()); - for (const auto &item : other.m_data) { - m_data.emplace_back (std::make_unique (*item)); - } - } - return *this; - } - - t8_abstract_data_handler * - clone () const override - { - return new t8_data_handler> (*this); - } - - t8_data_handler (std::vector &data) - { - m_data.reserve (data.size ()); - for (const auto &item : data) { - m_data.emplace_back (std::make_unique (item)); - } - } - - void - get_data (std::vector &data) - { - data.resize (m_data.size ()); - for (size_t i = 0; i < m_data.size (); ++i) { - data[i] = *m_data[i]; - } - } - - int - buffer_size (sc_MPI_Comm comm) override - { - int total_size = 0; - const int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &total_size); - SC_CHECK_MPI (mpiret); - for (const auto &item : m_data) { - const int size = single_handler.size (item.get (), comm); - total_size += size; - } - return total_size; - } - - void - pack_vector_prefix (void *buffer, const int num_bytes, int &pos, sc_MPI_Comm comm) override - { - const int num_data = m_data.size (); - const int mpiret = sc_MPI_Pack (&num_data, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); - SC_CHECK_MPI (mpiret); - - for (const auto &item : m_data) { - single_handler.pack (item.get (), pos, buffer, num_bytes, comm); - } - } - - void - unpack_vector_prefix (const void *buffer, const int num_bytes, int &pos, int &outcount, sc_MPI_Comm comm) override - { - const int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &outcount, 1, sc_MPI_INT, comm); - SC_CHECK_MPI (mpiret); - T8_ASSERT (outcount >= 0); - - m_data.clear (); - m_data.reserve (outcount); - for (int i = 0; i < outcount; ++i) { - auto item = std::make_unique (); - single_handler.unpack (buffer, num_bytes, pos, item.get (), comm); - m_data.emplace_back (std::move (item)); + if (m_data) { + m_data.reset (); } } - int - send (const int dest, const int tag, sc_MPI_Comm comm) override - { -#if T8_ENABLE_MPI - int pos = 0; - const int num_bytes = buffer_size (comm); - std::vector buffer (num_bytes); - pack_vector_prefix (buffer.data (), num_bytes, pos, comm); - - const int mpiret = sc_MPI_Send (buffer.data (), num_bytes, sc_MPI_PACKED, dest, tag, comm); - SC_CHECK_MPI (mpiret); - return mpiret; -#else - t8_infof ("send only available when configured with --enable-mpi\n"); - return sc_MPI_ERR_OTHER; -#endif - } - - int - recv (const int source, const int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) override - { -#if T8_ENABLE_MPI - int pos = 0; - int mpiret = sc_MPI_Probe (source, tag, comm, status); - SC_CHECK_MPI (mpiret); - - int num_bytes; - mpiret = sc_MPI_Get_count (status, sc_MPI_PACKED, &num_bytes); - SC_CHECK_MPI (mpiret); - std::vector buffer (num_bytes); - - mpiret = sc_MPI_Recv (buffer.data (), num_bytes, sc_MPI_PACKED, source, tag, comm, status); - SC_CHECK_MPI (mpiret); - unpack_vector_prefix (buffer.data (), num_bytes, pos, outcount, comm); - return mpiret; -#else - t8_infof ("recv only available when configured with --enable-mpi\n"); - return sc_MPI_ERR_OTHER; -#endif - } - - int - type () override - { - return single_handler.type (); - } - - ~t8_data_handler () override = default; - private: - std::vector> m_data; + std::unique_ptr> m_data; t8_single_data_handler single_handler; }; diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 96df00cc8d..804663e0ab 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -283,7 +283,7 @@ TEST (data_handler_test, tree_test) } trees.push_back (tree); } - t8_data_handler> tree_handler (trees); + t8_data_handler tree_handler (trees); const int send_to = (mpirank + 1) % mpisize; const int recv_from = (mpirank == 0) ? (mpisize - 1) : (mpirank - 1); diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index b0767ce30f..d6c18b35ae 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -85,10 +85,10 @@ template <> class t8_single_data_handler { public: int - size (const pseudo_tree *item, sc_MPI_Comm comm) + size (const pseudo_tree &item, sc_MPI_Comm comm) { int int_size = 0; - const int topo_data_size = item->topo_data.size () + 1; + const int topo_data_size = item.topo_data.size () + 1; int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &int_size); SC_CHECK_MPI (mpiret); @@ -96,28 +96,28 @@ class t8_single_data_handler { /* tree_data_size */ total_size += int_size; - for (const auto &ihandler : item->tree_data) { + for (const auto &ihandler : item.tree_data) { total_size += ihandler->buffer_size (comm) + int_size; } return total_size; } void - pack (const pseudo_tree *data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm) + pack (const pseudo_tree &data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm) { - const int data_size = data->topo_data.size (); + const int data_size = data.topo_data.size (); /* Pack number of topological data */ int mpiret = sc_MPI_Pack (&data_size, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); /* Pack each topological data*/ - mpiret = sc_MPI_Pack ((data->topo_data.data ()), data_size, sc_MPI_INT, buffer, num_bytes, &pos, comm); + mpiret = sc_MPI_Pack ((data.topo_data.data ()), data_size, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); /* Pack number of tree-specific data*/ - const int tree_data_size = data->tree_data.size (); + const int tree_data_size = data.tree_data.size (); mpiret = sc_MPI_Pack (&tree_data_size, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); - for (auto &handler : data->tree_data) { + for (auto &handler : data.tree_data) { const int type = handler->type (); /* Pack type of tree data */ mpiret = sc_MPI_Pack (&type, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); @@ -128,21 +128,17 @@ class t8_single_data_handler { } void - unpack (const void *buffer, const int num_bytes, int &pos, pseudo_tree *data, sc_MPI_Comm comm) + unpack (const void *buffer, const int num_bytes, int &pos, pseudo_tree &data, sc_MPI_Comm comm) { /* Clear existing tree data */ - for (const auto &handler_ptr : data->tree_data) { - t8_abstract_data_handler *handler = handler_ptr.get (); - delete handler; - } - data->tree_data.clear (); + data.tree_data.clear (); /* Unpack number of topological data */ int topo_data_size = 0; int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &topo_data_size, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); - data->topo_data.resize (topo_data_size); - for (int &topo_item : data->topo_data) { + data.topo_data.resize (topo_data_size); + for (int &topo_item : data.topo_data) { /* Unpack each topological item */ mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &topo_item, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); @@ -157,14 +153,14 @@ class t8_single_data_handler { mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &type, 1, sc_MPI_INT, comm); int outcount = 0; if (type == 0) { - auto new_handler = std::make_unique>>(); - new_handler->unpack_vector_prefix(buffer, num_bytes, pos, outcount, comm); - data->tree_data.push_back(std::move(new_handler)); + auto new_handler = std::make_unique>> (); + new_handler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); + data.tree_data.push_back (std::move (new_handler)); } else if (type == 1) { - auto new_handler = std::make_unique>>(); - new_handler->unpack_vector_prefix(buffer, num_bytes, pos, outcount, comm); - data->tree_data.push_back(std::move(new_handler)); + auto new_handler = std::make_unique>> (); + new_handler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); + data.tree_data.push_back (std::move (new_handler)); } else { SC_ABORT_NOT_REACHED (); From 85d69e590d3f04d6c8856d7f62d25d181fac6f66 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Mon, 30 Sep 2024 13:18:56 +0200 Subject: [PATCH 43/81] Optimize pseudo-trees --- src/t8_data/t8_data_handler.hxx | 9 ++---- test/t8_data/t8_pseudo_trees.hxx | 47 +++++++++++++++++--------------- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 29f36000c9..19349284bf 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -207,10 +207,8 @@ class t8_data_handler: public t8_abstract_data_handler { const int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &total_size); SC_CHECK_MPI (mpiret); if (m_data) { - if (m_data) { - for (const auto &item : *m_data) { - total_size += single_handler.size (item, comm); - } + for (const auto &item : *m_data) { + total_size += single_handler.size (item, comm); } } return total_size; @@ -292,9 +290,6 @@ class t8_data_handler: public t8_abstract_data_handler { ~t8_data_handler () override { - if (m_data) { - m_data.reset (); - } } private: diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index d6c18b35ae..b3552a6889 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -88,17 +88,19 @@ class t8_single_data_handler { size (const pseudo_tree &item, sc_MPI_Comm comm) { int int_size = 0; - const int topo_data_size = item.topo_data.size () + 1; - int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &int_size); SC_CHECK_MPI (mpiret); - int total_size = topo_data_size * int_size; - /* tree_data_size */ - total_size += int_size; + // Calculate the size for topo_data + const int topo_data_size = item.topo_data.size (); + int total_size = (topo_data_size + 1) * int_size; + + // Calculate the size for tree_data + total_size += int_size; // for tree_data_size for (const auto &ihandler : item.tree_data) { total_size += ihandler->buffer_size (comm) + int_size; } + return total_size; } @@ -109,20 +111,20 @@ class t8_single_data_handler { /* Pack number of topological data */ int mpiret = sc_MPI_Pack (&data_size, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); - /* Pack each topological data*/ - mpiret = sc_MPI_Pack ((data.topo_data.data ()), data_size, sc_MPI_INT, buffer, num_bytes, &pos, comm); + /* Pack topological data in one call */ + mpiret = sc_MPI_Pack (data.topo_data.data (), data_size, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); - /* Pack number of tree-specific data*/ + /* Pack number of tree-specific data */ const int tree_data_size = data.tree_data.size (); mpiret = sc_MPI_Pack (&tree_data_size, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); - for (auto &handler : data.tree_data) { + for (const auto &handler : data.tree_data) { const int type = handler->type (); /* Pack type of tree data */ mpiret = sc_MPI_Pack (&type, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); - /* Pack each data. */ + /* Pack each data */ handler->pack_vector_prefix (buffer, num_bytes, pos, comm); } } @@ -138,33 +140,34 @@ class t8_single_data_handler { int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &topo_data_size, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); data.topo_data.resize (topo_data_size); - for (int &topo_item : data.topo_data) { - /* Unpack each topological item */ - mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &topo_item, 1, sc_MPI_INT, comm); - SC_CHECK_MPI (mpiret); - } + mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, data.topo_data.data (), topo_data_size, sc_MPI_INT, comm); + SC_CHECK_MPI (mpiret); + /* Unpack number of tree-specific data */ int num_handler = 0; mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &num_handler, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); + data.tree_data.reserve (num_handler); for (int ihandler = 0; ihandler < num_handler; ihandler++) { int type; mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &type, 1, sc_MPI_INT, comm); - int outcount = 0; + SC_CHECK_MPI (mpiret); + + std::unique_ptr new_handler; if (type == 0) { - auto new_handler = std::make_unique>> (); - new_handler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); - data.tree_data.push_back (std::move (new_handler)); + new_handler = std::make_unique>> (); } else if (type == 1) { - auto new_handler = std::make_unique>> (); - new_handler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); - data.tree_data.push_back (std::move (new_handler)); + new_handler = std::make_unique>> (); } else { SC_ABORT_NOT_REACHED (); } + + int outcount = 0; + new_handler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); + data.tree_data.push_back (std::move (new_handler)); } } From 1a66765c7519087e93f5f342b1a888e6a6bed0af Mon Sep 17 00:00:00 2001 From: David Knapp Date: Mon, 30 Sep 2024 21:00:04 +0200 Subject: [PATCH 44/81] use shared_ptr --- src/t8_data/t8_data_handler.hxx | 58 ++------------- test/t8_data/t8_gtest_data_handler.cxx | 97 ++++++++++++++------------ test/t8_data/t8_pseudo_trees.hxx | 62 ++++------------ 3 files changed, 70 insertions(+), 147 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 19349284bf..b24b8f7bdf 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -45,19 +45,6 @@ class t8_abstract_data_handler { buffer_size (sc_MPI_Comm comm) = 0; - /** - * Creates a copy of the current data handler. - * - * This pure virtual function must be implemented by derived classes to - * provide a mechanism for cloning the data handler. The cloned object - * should be a deep copy, ensuring that all relevant data is duplicated. - * - * \return A pointer to the newly cloned t8_abstract_data_handler object. - */ - virtual t8_abstract_data_handler * - clone () const - = 0; - /** * Packs a vector into a buffer. The vector data will be prefixed with the number of elements in the vector. * @@ -154,50 +141,17 @@ class t8_data_handler: public t8_abstract_data_handler { m_data = nullptr; } - t8_data_handler (const t8_data_handler &other) - { - if (other.m_data) { - m_data = std::make_unique> (*other.m_data); - } - else { - m_data = nullptr; - } - } - - t8_data_handler & - operator= (const t8_data_handler &other) - { - if (this != &other) { - if (other.m_data) { - m_data = std::make_unique> (*other.m_data); - } - else { - m_data.reset (); - } - } - return *this; - } - - t8_abstract_data_handler * - clone () const override - { - return new t8_data_handler (*this); - } - - t8_data_handler (const std::vector &data) + t8_data_handler (const std::vector &data): single_handler () { - m_data = std::make_unique> (data); + m_data = std::make_shared> (data); } void - get_data (std::vector &data) + get_data (std::vector &data) const { if (m_data) { data = *m_data; } - else { - data.clear (); - } } int @@ -288,12 +242,8 @@ class t8_data_handler: public t8_abstract_data_handler { return single_handler.type (); } - ~t8_data_handler () override - { - } - private: - std::unique_ptr> m_data; + std::shared_ptr> m_data; t8_single_data_handler single_handler; }; diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 804663e0ab..729dd08e1a 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -199,40 +199,44 @@ TEST (data_handler_test, pseudo_tree_test) { const int num_data = 100; pseudo_tree tree; + tree.topo_data.resize (10); + std::iota (tree.topo_data.begin (), tree.topo_data.end (), 0); + std::vector> int_data (num_data); - for (int idata = 0; idata < num_data; idata++) { + for (int idata = 0; idata < num_data; ++idata) { int_data[idata].check = 42; int_data[idata].data = idata; } - tree.topo_data.resize (10); - std::iota (tree.topo_data.begin (), tree.topo_data.end (), 0); - t8_data_handler> int_handler (int_data); - - tree.tree_data.push_back (std::make_unique>> (int_handler)); + tree.tree_data.resize (1); + tree.tree_data[0] = std::make_shared>> (std::move (int_data)); pseudo_tree tree_copy (tree); EXPECT_EQ (tree.topo_data.size (), tree_copy.topo_data.size ()); EXPECT_EQ (tree.tree_data.size (), tree_copy.tree_data.size ()); std::vector> copied_data; - ((t8_data_handler> *) (tree_copy.tree_data[0].get ()))->get_data (copied_data); + auto handler = std::dynamic_pointer_cast>> (tree_copy.tree_data[0]).get (); + ASSERT_NE (handler, nullptr); + handler->get_data (copied_data); - for (int idata = 0; idata < num_data; idata++) { - EXPECT_EQ (copied_data[idata].data, int_data[idata].data); - EXPECT_EQ (copied_data[idata].check, int_data[idata].check); + for (int idata = 0; idata < num_data; ++idata) { + EXPECT_EQ (copied_data[idata].data, idata); + EXPECT_EQ (copied_data[idata].check, 42); } - pseudo_tree tree_equal = tree_copy; + pseudo_tree tree_equal = std::move (tree_copy); EXPECT_EQ (tree.topo_data.size (), tree_equal.topo_data.size ()); EXPECT_EQ (tree.tree_data.size (), tree_equal.tree_data.size ()); std::vector> equal_data; - ((t8_data_handler> *) (tree_equal.tree_data[0].get ()))->get_data (equal_data); + auto handler_equal = std::dynamic_pointer_cast>> (tree_equal.tree_data[0]).get (); + ASSERT_NE (handler_equal, nullptr); + handler_equal->get_data (equal_data); - for (int idata = 0; idata < num_data; idata++) { - EXPECT_EQ (equal_data[idata].data, int_data[idata].data); - EXPECT_EQ (equal_data[idata].check, int_data[idata].check); + for (int idata = 0; idata < num_data; ++idata) { + EXPECT_EQ (equal_data[idata].data, idata); + EXPECT_EQ (equal_data[idata].check, 42); } } @@ -240,49 +244,47 @@ TEST (data_handler_test, pseudo_tree_test) TEST (data_handler_test, tree_test) { sc_MPI_Comm comm = sc_MPI_COMM_WORLD; - int mpirank; - int mpisize; - int mpiret = sc_MPI_Comm_rank (comm, &mpirank); + int mpirank, mpisize, mpiret; + mpiret = sc_MPI_Comm_rank (comm, &mpirank); SC_CHECK_MPI (mpiret); mpiret = sc_MPI_Comm_size (comm, &mpisize); SC_CHECK_MPI (mpiret); const int num_trees = (mpirank % 4) * 10; - const int num_data = 100; - + const int num_data = 1000; const double fraction = 0.42; - std::vector trees; + std::vector trees (num_trees); - for (int itree = 0; itree < num_trees; itree++) { + for (int itree = 0; itree < num_trees; ++itree) { pseudo_tree tree; const int tree_topo_size = ((mpirank % 3) + 1) * 10; tree.topo_data.resize (tree_topo_size); std::iota (tree.topo_data.begin (), tree.topo_data.end (), 0); const int num_tree_data = (mpirank + itree) % 2; - t8_abstract_data_handler *new_handler = NULL; - for (int itree_data = 0; itree_data < num_tree_data; itree_data++) { + tree.tree_data.resize (num_tree_data); + for (int itree_data = 0; itree_data < num_tree_data; ++itree_data) { if (itree_data == 0) { std::vector> int_data (num_data); - for (int idata = 0; idata < num_data; idata++) { + for (int idata = 0; idata < num_data; ++idata) { int_data[idata].check = mpirank; int_data[idata].data = idata; } - new_handler = new t8_data_handler> (int_data); + tree.tree_data[itree_data] = std::make_shared>> (std::move (int_data)); } else { std::vector> double_data (num_data); - for (int idata = 0; idata < num_data; idata++) { + for (int idata = 0; idata < num_data; ++idata) { double_data[idata].check = mpirank; - double_data[idata].data = (double) idata + fraction; - new_handler = new t8_data_handler> (double_data); + double_data[idata].data = static_cast (idata) + fraction; } + tree.tree_data[itree_data] = std::make_shared>> (std::move (double_data)); } - tree.tree_data.push_back (std::unique_ptr (new_handler)); } - trees.push_back (tree); + trees[itree] = std::move (tree); } + t8_data_handler tree_handler (trees); const int send_to = (mpirank + 1) % mpisize; @@ -298,37 +300,42 @@ TEST (data_handler_test, tree_test) tree_handler.get_data (recv_trees); const int num_recv_trees = recv_trees.size (); + ASSERT_EQ (num_recv_trees, (recv_from % 4) * 10); - ASSERT_EQ (num_recv_trees, ((recv_from) % 4) * 10); - - for (int itree = 0; itree < num_recv_trees; itree++) { + for (int itree = 0; itree < num_recv_trees; ++itree) { const int num_recv_tree_topo_size = recv_trees[itree].topo_data.size (); ASSERT_EQ (num_recv_tree_topo_size, ((recv_from % 3) + 1) * 10); - for (int itopo_data = 0; itopo_data < num_recv_tree_topo_size; itopo_data++) { + for (int itopo_data = 0; itopo_data < num_recv_tree_topo_size; ++itopo_data) { EXPECT_EQ (recv_trees[itree].topo_data[itopo_data], itopo_data); } const int num_recv_tree_data = recv_trees[itree].tree_data.size (); ASSERT_EQ (num_recv_tree_data, (recv_from + itree) % 2); - for (int itree_data = 0; itree_data < num_recv_tree_data; itree_data++) { + for (int itree_data = 0; itree_data < num_recv_tree_data; ++itree_data) { if (itree_data == 0) { std::vector> recv_ints; - dynamic_cast> *> (recv_trees[itree].tree_data[itree_data].get ()) - ->get_data (recv_ints); - ASSERT_EQ ((const int) recv_ints.size (), num_data); - for (int idata = 0; idata < num_data; idata++) { + auto int_handler + = std::dynamic_pointer_cast>> (recv_trees[itree].tree_data[itree_data]) + .get (); + ASSERT_NE (int_handler, nullptr); + int_handler->get_data (recv_ints); + ASSERT_EQ (static_cast (recv_ints.size ()), num_data); + for (int idata = 0; idata < num_data; ++idata) { EXPECT_EQ (recv_ints[idata].data, idata); EXPECT_EQ (recv_ints[idata].check, recv_from); } } else { std::vector> recv_double; - dynamic_cast> *> (recv_trees[itree].tree_data[itree_data].get ()) - ->get_data (recv_double); - ASSERT_EQ ((const int) recv_double.size (), num_data); - for (int idata = 0; idata < num_data; idata++) { - EXPECT_EQ (recv_double[idata].data, (double) idata + fraction); + auto double_handler + = std::dynamic_pointer_cast>> (recv_trees[itree].tree_data[itree_data]) + .get (); + ASSERT_NE (double_handler, nullptr); + double_handler->get_data (recv_double); + ASSERT_EQ (static_cast (recv_double.size ()), num_data); + for (int idata = 0; idata < num_data; ++idata) { + EXPECT_EQ (recv_double[idata].data, static_cast (idata) + fraction); EXPECT_EQ (recv_double[idata].check, recv_from); } } diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index b3552a6889..8dedfb8e47 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -33,52 +33,18 @@ along with t8code; if not, write to the Free Software Foundation, Inc., /** * \class pseudo_tree - * A class representing a pseudo tree structure. - * - * The pseudo_tree class encapsulates a tree-like structure with topology data and tree data. - * It provides constructors, assignment operator, and destructor for managing the tree data. + * Represents a pseudo tree structure containing topological and tree data. * - * It is meant for testing purposes only and to mimic the structure of a tree. - * - * \var std::vector pseudo_tree::topo_data - * A vector containing the topology data of the pseudo tree. - * - * \var std::vector> pseudo_tree::tree_data - * A vector of unique pointers to t8_abstract_data_handler objects representing the tree data. + * \note This class is used for testing purposes only. + * + * The pseudo_tree class encapsulates two main data members: + * - `topo_data`: A vector of integers representing topological data. + * - `tree_data`: A vector of pointers to t8_abstract_data_handler objects, representing tree data. */ class pseudo_tree { public: - pseudo_tree () - { - } - - pseudo_tree (const pseudo_tree &other): topo_data (other.topo_data) - { - tree_data.resize (other.tree_data.size ()); - for (size_t i = 0; i < other.tree_data.size (); ++i) { - tree_data[i] = std::unique_ptr (other.tree_data[i]->clone ()); - } - } - - pseudo_tree & - operator= (const pseudo_tree &other) - { - if (this != &other) { - tree_data.clear (); - topo_data = other.topo_data; - - tree_data.resize (other.tree_data.size ()); - for (size_t i = 0; i < other.tree_data.size (); ++i) { - tree_data[i] = std::unique_ptr (other.tree_data[i]->clone ()); - } - } - return *this; - } - - ~pseudo_tree () = default; - std::vector topo_data; - std::vector> tree_data; + std::vector> tree_data; }; template <> @@ -97,7 +63,7 @@ class t8_single_data_handler { // Calculate the size for tree_data total_size += int_size; // for tree_data_size - for (const auto &ihandler : item.tree_data) { + for (auto ihandler : item.tree_data) { total_size += ihandler->buffer_size (comm) + int_size; } @@ -148,26 +114,26 @@ class t8_single_data_handler { mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &num_handler, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); - data.tree_data.reserve (num_handler); + data.tree_data.resize (num_handler); for (int ihandler = 0; ihandler < num_handler; ihandler++) { + } + for (auto &ihandler : data.tree_data) { int type; mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &type, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); - std::unique_ptr new_handler; if (type == 0) { - new_handler = std::make_unique>> (); + ihandler = std::make_shared>> (); } else if (type == 1) { - new_handler = std::make_unique>> (); + ihandler = std::make_shared>> (); } else { SC_ABORT_NOT_REACHED (); } int outcount = 0; - new_handler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); - data.tree_data.push_back (std::move (new_handler)); + ihandler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); } } From 988546802ccbbe854f1a3b49821b95233b95dde9 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Mon, 30 Sep 2024 21:09:57 +0200 Subject: [PATCH 45/81] minor improvements --- src/t8_data/t8_data_handler.hxx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index b24b8f7bdf..6954b569aa 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -141,9 +141,8 @@ class t8_data_handler: public t8_abstract_data_handler { m_data = nullptr; } - t8_data_handler (const std::vector &data): single_handler () + t8_data_handler (const std::vector &data): m_data (std::make_shared> (data)), single_handler () { - m_data = std::make_shared> (data); } void @@ -186,10 +185,13 @@ class t8_data_handler: public t8_abstract_data_handler { const int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &outcount, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); T8_ASSERT (outcount >= 0); + if (!m_data) { - m_data = std::make_unique> (); + m_data = std::make_shared> (outcount); + } + else { + m_data->resize (outcount); } - m_data->resize (outcount); for (auto &item : *m_data) { single_handler.unpack (buffer, num_bytes, pos, item, comm); } From ffc6a499eb419271fc63a54d9c57997290ca32e6 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Mon, 30 Sep 2024 21:13:05 +0200 Subject: [PATCH 46/81] documentation --- src/t8_data/t8_data_handler.hxx | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 6954b569aa..6602644774 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -123,15 +123,12 @@ class t8_abstract_data_handler { /** * \class t8_data_handler - * A data handler class that manages a collection of data items. - * - * This class provides functionalities to handle a collection of data items - * of type T. It supports cloning, packing, unpacking, sending, and receiving - * data using MPI. - * - * \tparam T The type of data items managed by this handler. - * - * \note This class requires MPI to be enabled for send and receive operations. + * \brief A template class for handling data in a distributed environment. + * + * This class inherits from t8_abstract_data_handler and provides methods for + * packing, unpacking, sending, and receiving data using MPI. + * + * \tparam T The type of data to be handled. */ template class t8_data_handler: public t8_abstract_data_handler { From 291c0f565aee77936fec325d4e546adb91e9bf98 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Tue, 1 Oct 2024 11:26:00 +0200 Subject: [PATCH 47/81] More stl --- src/t8_data/t8_data_handler.hxx | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 6602644774..3a14056bca 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -28,7 +28,7 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include #include -#include +#include class t8_abstract_data_handler { public: @@ -157,9 +157,8 @@ class t8_data_handler: public t8_abstract_data_handler { const int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &total_size); SC_CHECK_MPI (mpiret); if (m_data) { - for (const auto &item : *m_data) { - total_size += single_handler.size (item, comm); - } + total_size += std::accumulate (m_data->begin (), m_data->end (), 0, + [&] (int sum, const T &item) { return sum + single_handler.size (item, comm); }); } return total_size; } @@ -171,9 +170,8 @@ class t8_data_handler: public t8_abstract_data_handler { const int mpiret = sc_MPI_Pack (&num_data, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); - for (const auto &item : *m_data) { - single_handler.pack (item, pos, buffer, num_bytes, comm); - } + std::for_each (m_data->begin (), m_data->end (), + [&] (const T &item) { single_handler.pack (item, pos, buffer, num_bytes, comm); }); } void @@ -189,9 +187,8 @@ class t8_data_handler: public t8_abstract_data_handler { else { m_data->resize (outcount); } - for (auto &item : *m_data) { - single_handler.unpack (buffer, num_bytes, pos, item, comm); - } + std::for_each (m_data->begin (), m_data->end (), + [&] (T &item) { single_handler.unpack (buffer, num_bytes, pos, item, comm); }); } int From c36773c5a5a554fe6a3fd35716980c5f753ce484 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Tue, 1 Oct 2024 13:57:34 +0200 Subject: [PATCH 48/81] Documentation --- src/t8_data/t8_data_handler.hxx | 8 ++++++++ src/t8_data/t8_data_handler_base.hxx | 12 ++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 3a14056bca..276cc37a3f 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -239,7 +239,15 @@ class t8_data_handler: public t8_abstract_data_handler { } private: + /** + * \brief A shared pointer to a vector of data. + * This data will be packed, unpacked, and communicated via MPI. + */ std::shared_ptr> m_data; + /** + * \brief A single data handler for the data type T. + * This handler will be used to pack and unpack individual data items. + */ t8_single_data_handler single_handler; }; diff --git a/src/t8_data/t8_data_handler_base.hxx b/src/t8_data/t8_data_handler_base.hxx index 413309cd82..3b3a10528c 100644 --- a/src/t8_data/t8_data_handler_base.hxx +++ b/src/t8_data/t8_data_handler_base.hxx @@ -28,8 +28,20 @@ along with t8code; if not, write to the Free Software Foundation, Inc., template class t8_single_data_handler { public: + + /** + * Construct a new t8 single data handler. + * + */ t8_single_data_handler () {}; + /** + * Returns the size of the data. + * + * \param[in] data The data to compute the size of. + * \param[in] comm The MPI communicator used for communication. + * \return An integer representing the size of the data. + */ int size (const T &data, sc_MPI_Comm comm); From 4d03763702b623d37fec2c3ff1f60864b1449e58 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Tue, 1 Oct 2024 14:00:17 +0200 Subject: [PATCH 49/81] T -> TType --- src/t8_data/t8_data_handler.hxx | 26 ++++++++++++++------------ src/t8_data/t8_data_handler_base.hxx | 9 ++++----- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 276cc37a3f..54e8e065ef 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -128,9 +128,9 @@ class t8_abstract_data_handler { * This class inherits from t8_abstract_data_handler and provides methods for * packing, unpacking, sending, and receiving data using MPI. * - * \tparam T The type of data to be handled. + * \tparam TType The type of data to be handled. */ -template +template class t8_data_handler: public t8_abstract_data_handler { public: t8_data_handler (): single_handler () @@ -138,12 +138,13 @@ class t8_data_handler: public t8_abstract_data_handler { m_data = nullptr; } - t8_data_handler (const std::vector &data): m_data (std::make_shared> (data)), single_handler () + t8_data_handler (const std::vector &data) + : m_data (std::make_shared> (data)), single_handler () { } void - get_data (std::vector &data) const + get_data (std::vector &data) const { if (m_data) { data = *m_data; @@ -157,8 +158,9 @@ class t8_data_handler: public t8_abstract_data_handler { const int mpiret = sc_MPI_Pack_size (1, sc_MPI_INT, comm, &total_size); SC_CHECK_MPI (mpiret); if (m_data) { - total_size += std::accumulate (m_data->begin (), m_data->end (), 0, - [&] (int sum, const T &item) { return sum + single_handler.size (item, comm); }); + total_size += std::accumulate (m_data->begin (), m_data->end (), 0, [&] (int sum, const TType &item) { + return sum + single_handler.size (item, comm); + }); } return total_size; } @@ -171,7 +173,7 @@ class t8_data_handler: public t8_abstract_data_handler { SC_CHECK_MPI (mpiret); std::for_each (m_data->begin (), m_data->end (), - [&] (const T &item) { single_handler.pack (item, pos, buffer, num_bytes, comm); }); + [&] (const TType &item) { single_handler.pack (item, pos, buffer, num_bytes, comm); }); } void @@ -182,13 +184,13 @@ class t8_data_handler: public t8_abstract_data_handler { T8_ASSERT (outcount >= 0); if (!m_data) { - m_data = std::make_shared> (outcount); + m_data = std::make_shared> (outcount); } else { m_data->resize (outcount); } std::for_each (m_data->begin (), m_data->end (), - [&] (T &item) { single_handler.unpack (buffer, num_bytes, pos, item, comm); }); + [&] (TType &item) { single_handler.unpack (buffer, num_bytes, pos, item, comm); }); } int @@ -239,16 +241,16 @@ class t8_data_handler: public t8_abstract_data_handler { } private: - /** + /** * \brief A shared pointer to a vector of data. * This data will be packed, unpacked, and communicated via MPI. */ - std::shared_ptr> m_data; + std::shared_ptr> m_data; /** * \brief A single data handler for the data type T. * This handler will be used to pack and unpack individual data items. */ - t8_single_data_handler single_handler; + t8_single_data_handler single_handler; }; #endif /* T8_DATA_HANDLER_HXX */ diff --git a/src/t8_data/t8_data_handler_base.hxx b/src/t8_data/t8_data_handler_base.hxx index 3b3a10528c..62f6d3619a 100644 --- a/src/t8_data/t8_data_handler_base.hxx +++ b/src/t8_data/t8_data_handler_base.hxx @@ -25,10 +25,9 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include -template +template class t8_single_data_handler { public: - /** * Construct a new t8 single data handler. * @@ -43,7 +42,7 @@ class t8_single_data_handler { * \return An integer representing the size of the data. */ int - size (const T &data, sc_MPI_Comm comm); + size (const TType &data, sc_MPI_Comm comm); /** * Packs the given data into a buffer for communication. @@ -56,7 +55,7 @@ class t8_single_data_handler { * \param[in] comm The MPI communicator used for communication. */ void - pack (const T &data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm); + pack (const TType &data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm); /** * Unpacks data from a buffer. @@ -71,7 +70,7 @@ class t8_single_data_handler { * \param[in] comm The MPI communicator used for communication. */ void - unpack (const void *buffer, const int num_bytes, int &pos, T &data, sc_MPI_Comm comm); + unpack (const void *buffer, const int num_bytes, int &pos, TType &data, sc_MPI_Comm comm); /** * Returns the type of the data handler. From ad6270cffcc6d6b134c29c1bc21010cef2f3c973 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Tue, 1 Oct 2024 14:01:43 +0200 Subject: [PATCH 50/81] More documentation --- src/t8_data/t8_data_handler.hxx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 54e8e065ef..4b29f928ef 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -133,11 +133,20 @@ class t8_abstract_data_handler { template class t8_data_handler: public t8_abstract_data_handler { public: + /** + * Construct a new t8 data handler. + * m_data is initialized to nullptr. + */ t8_data_handler (): single_handler () { m_data = nullptr; } + /** + * Construct a new t8 data handler with the given data. + * + * \param[in] data The data to be handled. + */ t8_data_handler (const std::vector &data) : m_data (std::make_shared> (data)), single_handler () { From 691ae7d4cee035d4c3e767b8a841bd523c42b260 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Tue, 1 Oct 2024 14:10:09 +0200 Subject: [PATCH 51/81] update and document getter function --- src/t8_data/t8_data_handler.hxx | 13 ++++++++----- test/t8_data/t8_gtest_data_handler.cxx | 27 +++++++++++--------------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 4b29f928ef..b4d0ca720b 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -152,12 +152,15 @@ class t8_data_handler: public t8_abstract_data_handler { { } - void - get_data (std::vector &data) const + /** + * \brief Get the data. + * + * \return std::shared_ptr> + */ + std::shared_ptr> + get_data () const { - if (m_data) { - data = *m_data; - } + return m_data; } int diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 729dd08e1a..7083c3e118 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -82,7 +82,7 @@ TYPED_TEST_P (data_handler_test, pack_unpack_vector_of_data) this->data_handler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, this->comm); EXPECT_EQ (outcount, this->max_num_data); - this->data_handler->get_data (this->recv_data); + this->recv_data = *(this->data_handler->get_data ()); for (int idata = 0; idata < this->max_num_data; idata++) { EXPECT_EQ (this->recv_data[idata].data, this->creator.large_data[idata].data); @@ -116,7 +116,7 @@ TYPED_TEST_P (data_handler_test, send_recv) int outcount; mpiret = this->data_handler->recv (recv_from, 0, this->comm, &status, outcount); - this->data_handler->get_data (this->recv_data); + this->recv_data = *(this->data_handler->get_data ()); #if T8_ENABLE_MPI SC_CHECK_MPI (mpiret); EXPECT_EQ (outcount, this->max_num_data); @@ -177,10 +177,9 @@ TEST (data_handler_test, multiple_handler) #endif } - std::vector> recv_ints; - std::vector> recv_doubles; - ((t8_data_handler> *) (handler[0]))->get_data (recv_ints); - ((t8_data_handler> *) (handler[1]))->get_data (recv_doubles); + std::vector> recv_ints = *((t8_data_handler> *) (handler[0]))->get_data (); + std::vector> recv_doubles + = *((t8_data_handler> *) (handler[1]))->get_data (); #if T8_ENABLE_MPI SC_CHECK_MPI (mpiret); @@ -214,10 +213,9 @@ TEST (data_handler_test, pseudo_tree_test) EXPECT_EQ (tree.topo_data.size (), tree_copy.topo_data.size ()); EXPECT_EQ (tree.tree_data.size (), tree_copy.tree_data.size ()); - std::vector> copied_data; auto handler = std::dynamic_pointer_cast>> (tree_copy.tree_data[0]).get (); ASSERT_NE (handler, nullptr); - handler->get_data (copied_data); + std::vector> copied_data = *(handler->get_data ()); for (int idata = 0; idata < num_data; ++idata) { EXPECT_EQ (copied_data[idata].data, idata); @@ -229,10 +227,9 @@ TEST (data_handler_test, pseudo_tree_test) EXPECT_EQ (tree.topo_data.size (), tree_equal.topo_data.size ()); EXPECT_EQ (tree.tree_data.size (), tree_equal.tree_data.size ()); - std::vector> equal_data; auto handler_equal = std::dynamic_pointer_cast>> (tree_equal.tree_data[0]).get (); ASSERT_NE (handler_equal, nullptr); - handler_equal->get_data (equal_data); + std::vector> equal_data = *(handler_equal->get_data ()); for (int idata = 0; idata < num_data; ++idata) { EXPECT_EQ (equal_data[idata].data, idata); @@ -296,8 +293,7 @@ TEST (data_handler_test, tree_test) int outcount; mpiret = tree_handler.recv (recv_from, 0, comm, &status, outcount); - std::vector recv_trees; - tree_handler.get_data (recv_trees); + std::vector recv_trees = *(tree_handler.get_data ()); const int num_recv_trees = recv_trees.size (); ASSERT_EQ (num_recv_trees, (recv_from % 4) * 10); @@ -314,12 +310,12 @@ TEST (data_handler_test, tree_test) ASSERT_EQ (num_recv_tree_data, (recv_from + itree) % 2); for (int itree_data = 0; itree_data < num_recv_tree_data; ++itree_data) { if (itree_data == 0) { - std::vector> recv_ints; auto int_handler = std::dynamic_pointer_cast>> (recv_trees[itree].tree_data[itree_data]) .get (); ASSERT_NE (int_handler, nullptr); - int_handler->get_data (recv_ints); + std::vector> recv_ints = *(int_handler->get_data ()); + ASSERT_EQ (static_cast (recv_ints.size ()), num_data); for (int idata = 0; idata < num_data; ++idata) { EXPECT_EQ (recv_ints[idata].data, idata); @@ -327,12 +323,11 @@ TEST (data_handler_test, tree_test) } } else { - std::vector> recv_double; auto double_handler = std::dynamic_pointer_cast>> (recv_trees[itree].tree_data[itree_data]) .get (); ASSERT_NE (double_handler, nullptr); - double_handler->get_data (recv_double); + std::vector> recv_double = *(double_handler->get_data ()); ASSERT_EQ (static_cast (recv_double.size ()), num_data); for (int idata = 0; idata < num_data; ++idata) { EXPECT_EQ (recv_double[idata].data, static_cast (idata) + fraction); From 14e66daf170066cb74aca25f3239aa706f9a97e9 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Tue, 1 Oct 2024 14:44:15 +0200 Subject: [PATCH 52/81] do no double-wrap --- src/t8_data/t8_data_handler.hxx | 10 ---------- test/t8_data/t8_gtest_data_handler.cxx | 18 +++++------------- 2 files changed, 5 insertions(+), 23 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index b4d0ca720b..c3e7638fe0 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -208,7 +208,6 @@ class t8_data_handler: public t8_abstract_data_handler { int send (const int dest, const int tag, sc_MPI_Comm comm) override { -#if T8_ENABLE_MPI int pos = 0; const int num_bytes = buffer_size (comm); std::vector buffer (num_bytes); @@ -217,16 +216,11 @@ class t8_data_handler: public t8_abstract_data_handler { const int mpiret = sc_MPI_Send (buffer.data (), num_bytes, sc_MPI_PACKED, dest, tag, comm); SC_CHECK_MPI (mpiret); return mpiret; -#else - t8_infof ("send only available when configured with --enable-mpi\n"); - return sc_MPI_ERR_OTHER; -#endif } int recv (const int source, const int tag, sc_MPI_Comm comm, sc_MPI_Status *status, int &outcount) override { -#if T8_ENABLE_MPI int pos = 0; int mpiret = sc_MPI_Probe (source, tag, comm, status); SC_CHECK_MPI (mpiret); @@ -240,10 +234,6 @@ class t8_data_handler: public t8_abstract_data_handler { SC_CHECK_MPI (mpiret); unpack_vector_prefix (buffer.data (), num_bytes, pos, outcount, comm); return mpiret; -#else - t8_infof ("recv only available when configured with --enable-mpi\n"); - return sc_MPI_ERR_OTHER; -#endif } int diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 7083c3e118..b8ad937a93 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -101,11 +101,9 @@ TYPED_TEST_P (data_handler_test, send_recv) int send_to = (this->mpirank + 1) % this->mpisize; /* Pack and send the data. */ - int mpiret = this->data_handler->send (send_to, 0, this->comm); #if T8_ENABLE_MPI + int mpiret = this->data_handler->send (send_to, 0, this->comm); SC_CHECK_MPI (mpiret); -#else - EXPECT_EQ (mpiret, sc_MPI_ERR_OTHER); #endif /* Compute the rank we this rank receives from. */ @@ -114,18 +112,16 @@ TYPED_TEST_P (data_handler_test, send_recv) /* Receive and unpack the data. */ sc_MPI_Status status; int outcount; - mpiret = this->data_handler->recv (recv_from, 0, this->comm, &status, outcount); - - this->recv_data = *(this->data_handler->get_data ()); #if T8_ENABLE_MPI + mpiret = this->data_handler->recv (recv_from, 0, this->comm, &status, outcount); SC_CHECK_MPI (mpiret); + this->recv_data = *(this->data_handler->get_data ()); + EXPECT_EQ (outcount, this->max_num_data); for (int idata = 0; idata < this->max_num_data; idata++) { EXPECT_EQ (this->recv_data[idata].data, this->creator.large_data[idata].data); EXPECT_EQ (this->recv_data[idata].check, this->creator.large_data[idata].check); } -#else - EXPECT_EQ (mpiret, sc_MPI_ERR_OTHER); #endif } @@ -165,15 +161,13 @@ TEST (data_handler_test, multiple_handler) #endif for (t8_abstract_data_handler *ihandler : handler) { - mpiret = ihandler->send (send_to, 0, comm); #if T8_ENABLE_MPI + mpiret = ihandler->send (send_to, 0, comm); SC_CHECK_MPI (mpiret); /* Receive and unpack the data. */ sc_MPI_Status status; int outcount; mpiret = ihandler->recv (recv_from, 0, comm, &status, outcount); -#else - EXPECT_EQ (mpiret, sc_MPI_ERR_OTHER); #endif } @@ -189,8 +183,6 @@ TEST (data_handler_test, multiple_handler) EXPECT_EQ (recv_doubles[idata].check, recv_from); EXPECT_NEAR (recv_doubles[idata].data, (double) idata + fraction, T8_PRECISION_EPS); } -#else - EXPECT_EQ (mpiret, sc_MPI_ERR_OTHER); #endif } From 82872001705f05b86c8171b16277f6b0e008c5dc Mon Sep 17 00:00:00 2001 From: David Knapp Date: Tue, 1 Oct 2024 14:56:13 +0200 Subject: [PATCH 53/81] File documentation --- src/t8_data/t8_data_handler.hxx | 5 +++++ src/t8_data/t8_data_handler_base.hxx | 5 +++++ test/t8_data/t8_gtest_data_handler.cxx | 5 +++++ test/t8_data/t8_pseudo_trees.hxx | 7 +++++-- 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index c3e7638fe0..2c573710e7 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -20,6 +20,11 @@ along with t8code; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +/** + * \file This file provides functions to pack and unpack data for communication and to send and receive it using MPI. + * + */ + #ifndef T8_DATA_HANDLER_HXX #define T8_DATA_HANDLER_HXX diff --git a/src/t8_data/t8_data_handler_base.hxx b/src/t8_data/t8_data_handler_base.hxx index 62f6d3619a..22b1ed2e90 100644 --- a/src/t8_data/t8_data_handler_base.hxx +++ b/src/t8_data/t8_data_handler_base.hxx @@ -23,6 +23,11 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #ifndef T8_DATA_HANDLER_BASE #define T8_DATA_HANDLER_BASE +/** + * \file This file provides a templated class for handling single data items. + * + */ + #include template diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index b8ad937a93..1fede7ffa7 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -28,6 +28,11 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include +/** + * \file Test to check the functionality of the t8_data_handler class. + * + */ + /** * Templated testing class. Creates enlarged data (original data + a checking integer) and a * data handler. diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index 8dedfb8e47..8c7e3e935b 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -25,12 +25,15 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include -#include #include #include - #include +/** + * /file This file provides a pseudo tree structure for testing purposes. + * + */ + /** * \class pseudo_tree * Represents a pseudo tree structure containing topological and tree data. From 56c60464cdcd10d0bab2f3ecab197aaf95a144d9 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Tue, 1 Oct 2024 14:56:24 +0200 Subject: [PATCH 54/81] clean-up --- test/t8_data/t8_pseudo_trees.hxx | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index 8c7e3e935b..01541a09b3 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -118,8 +118,6 @@ class t8_single_data_handler { SC_CHECK_MPI (mpiret); data.tree_data.resize (num_handler); - for (int ihandler = 0; ihandler < num_handler; ihandler++) { - } for (auto &ihandler : data.tree_data) { int type; mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &type, 1, sc_MPI_INT, comm); From 18330e6a5499a83c4871e011b07946ed7b3f1858 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Tue, 1 Oct 2024 15:30:42 +0200 Subject: [PATCH 55/81] Documentation --- src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx | 9 +++++++++ src/t8_data/t8_data_packs/t8_packed_types.hxx | 5 +++++ 2 files changed, 14 insertions(+) diff --git a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx index 30c06ea344..2d32445518 100644 --- a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx +++ b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx @@ -26,6 +26,15 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include +/** + * \file This file provides a templated class for testing single data items. + * + */ + +/** + * \brief pseudo_types for testing + * + */ enum pseudo_types { T8_ENLARGED_INT = 0, T8_ENLARGED_DOUBLE = 1 }; template <> diff --git a/src/t8_data/t8_data_packs/t8_packed_types.hxx b/src/t8_data/t8_data_packs/t8_packed_types.hxx index 05f76544d7..29fc55d7c8 100644 --- a/src/t8_data/t8_data_packs/t8_packed_types.hxx +++ b/src/t8_data/t8_data_packs/t8_packed_types.hxx @@ -23,6 +23,11 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #ifndef T8_PACKED_TYPES #define T8_PACKED_TYPES +/** + * \file Summary file to include all packed types. + * + */ + #include #endif /* T8_PACKED_TYPES */ From 813269816c21e1a31c93ea13ccbb01f7af918288 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Tue, 1 Oct 2024 15:31:08 +0200 Subject: [PATCH 56/81] proper implementation of enlarged_data --- test/t8_data/t8_data_handler_specs.cxx | 10 +++--- test/t8_data/t8_data_handler_specs.hxx | 48 +++++++++++++++++--------- 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/test/t8_data/t8_data_handler_specs.cxx b/test/t8_data/t8_data_handler_specs.cxx index ea613c4503..67cbdce2d4 100644 --- a/test/t8_data/t8_data_handler_specs.cxx +++ b/test/t8_data/t8_data_handler_specs.cxx @@ -27,10 +27,9 @@ template <> void data_creator>::create (const int num_data) { - large_data.resize (num_data); + large_data.reserve (num_data); for (int idata = 0; idata < num_data; idata++) { - large_data[idata].data = idata; - large_data[idata].check = 42; + large_data.emplace_back (42, idata); } } @@ -38,9 +37,8 @@ template <> void data_creator>::create (const int num_data) { - large_data.resize (num_data); + large_data.reserve (num_data); for (int idata = 0; idata < num_data; idata++) { - large_data[idata].data = idata; - large_data[idata].check = 42.42; + large_data.emplace_back (42.42, idata); } } diff --git a/test/t8_data/t8_data_handler_specs.hxx b/test/t8_data/t8_data_handler_specs.hxx index d4a4102efd..8d3a7c48d2 100644 --- a/test/t8_data/t8_data_handler_specs.hxx +++ b/test/t8_data/t8_data_handler_specs.hxx @@ -23,46 +23,62 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #ifndef T8_DATA_HANDLER_SPECS_HXX #define T8_DATA_HANDLER_SPECS_HXX +/** + * \file This file provides a templated class that enlarges a data type by a check-int. + * Should only be used for testing purposes. + */ + #include #include #include -template +/** + * \class enlarged_data + * \brief A template class to handle data with an additional check value. + * + * This class is designed to store a piece of data along with an integer + * value that can be used for additional checks or validations. + * + * \tparam TType The type of the data to be stored. + * + * \var TType data + * The original data of type T. + * + * \var int check + * An integer value used for additional checks or validations. + */ +template class enlarged_data { public: enlarged_data () { } - void - set (T data, int check) + enlarged_data (TType data, int check): data (data), check (check) { - data = data; - check = check; } - T data; // original data - int check; // additional data to check against + TType data; /**< original data */ + int check; /**< additional data to check against */ }; -template +/** + * A template class to create data of type T. + * + * \tparam TType + */ +template class data_creator { public: data_creator () { - large_data = std::vector (0); + large_data = std::vector (0); }; void create (const int num_data); - std::vector large_data; + std::vector large_data; }; -template <> -class data_creator; - -template <> -class data_creator; - #endif /* T8_DATA_HANDLER_SPECS_HXX */ From f6dc3fb71bbf89b30e22b6bcae456cc25e68a634 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Tue, 1 Oct 2024 15:40:58 +0200 Subject: [PATCH 57/81] fix pedantic errors --- test/t8_data/t8_gtest_data_handler.cxx | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 1fede7ffa7..9a6ed0fd4f 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -103,13 +103,12 @@ TYPED_TEST_P (data_handler_test, pack_unpack_vector_of_data) TYPED_TEST_P (data_handler_test, send_recv) { /* Compute the rank this rank sends to. We send in a round-robin fashion */ - int send_to = (this->mpirank + 1) % this->mpisize; /* Pack and send the data. */ #if T8_ENABLE_MPI + int send_to = (this->mpirank + 1) % this->mpisize; int mpiret = this->data_handler->send (send_to, 0, this->comm); SC_CHECK_MPI (mpiret); -#endif /* Compute the rank we this rank receives from. */ int recv_from = (this->mpirank == 0) ? (this->mpisize - 1) : (this->mpirank - 1); @@ -117,7 +116,6 @@ TYPED_TEST_P (data_handler_test, send_recv) /* Receive and unpack the data. */ sc_MPI_Status status; int outcount; -#if T8_ENABLE_MPI mpiret = this->data_handler->recv (recv_from, 0, this->comm, &status, outcount); SC_CHECK_MPI (mpiret); this->recv_data = *(this->data_handler->get_data ()); @@ -158,29 +156,25 @@ TEST (data_handler_test, multiple_handler) handler.push_back (&int_handler); handler.push_back (&double_handler); +#if T8_ENABLE_MPI /* Compute the rank this rank sends to. We send in a round-robin fashion */ int send_to = (mpirank + 1) % mpisize; -#if T8_ENABLE_MPI /* Compute the rank this rank receives from. */ int recv_from = (mpirank == 0) ? (mpisize - 1) : (mpirank - 1); -#endif for (t8_abstract_data_handler *ihandler : handler) { -#if T8_ENABLE_MPI mpiret = ihandler->send (send_to, 0, comm); SC_CHECK_MPI (mpiret); /* Receive and unpack the data. */ sc_MPI_Status status; int outcount; mpiret = ihandler->recv (recv_from, 0, comm, &status, outcount); -#endif } std::vector> recv_ints = *((t8_data_handler> *) (handler[0]))->get_data (); std::vector> recv_doubles = *((t8_data_handler> *) (handler[1]))->get_data (); -#if T8_ENABLE_MPI SC_CHECK_MPI (mpiret); for (int idata = 0; idata < num_data; idata++) { EXPECT_EQ (recv_ints[idata].check, recv_from); From 5fc95720d04dbd11a7deac51c52b69be87db53db Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 11 Oct 2024 11:27:01 +0200 Subject: [PATCH 58/81] clear memory befor replacing it --- src/t8_data/t8_data_handler.hxx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 2c573710e7..2ba2fcd1d2 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -204,6 +204,7 @@ class t8_data_handler: public t8_abstract_data_handler { m_data = std::make_shared> (outcount); } else { + m_data->clear (); m_data->resize (outcount); } std::for_each (m_data->begin (), m_data->end (), From 7e1b537bf8c9f1a795793a5c447011efcba69659 Mon Sep 17 00:00:00 2001 From: Ole Albers Date: Thu, 17 Oct 2024 17:08:57 +0200 Subject: [PATCH 59/81] add placeholder for internal data handling --- src/t8_data/t8_data_handler.hxx | 10 ++++++++++ test/t8_data/t8_pseudo_trees.hxx | 25 ++++++++++++++----------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 2ba2fcd1d2..47061d0cf5 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -248,6 +248,16 @@ class t8_data_handler: public t8_abstract_data_handler { return single_handler.type (); } + bool + create_handle_for_internal_data (auto &ihandler, type) + { + switch (type) { + // Placeholder for future internal data, which is handled here. + default: + return false; + } + } + private: /** * \brief A shared pointer to a vector of data. diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index 01541a09b3..a2ea17d5ce 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -123,18 +123,21 @@ class t8_single_data_handler { mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &type, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); - if (type == 0) { - ihandler = std::make_shared>> (); + if (!create_handle_for_internal_data (ihandler, type)) { + + if (type == 0) { + ihandler = std::make_shared>> (); + } + else if (type == 1) { + ihandler = std::make_shared>> (); + } + else { + SC_ABORT_NOT_REACHED (); + } + + int outcount = 0; + ihandler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); } - else if (type == 1) { - ihandler = std::make_shared>> (); - } - else { - SC_ABORT_NOT_REACHED (); - } - - int outcount = 0; - ihandler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); } } From ec33c01f55aa1508886d1e18f992c27431210111 Mon Sep 17 00:00:00 2001 From: Ole Albers <122293607+ole-alb@users.noreply.github.com> Date: Fri, 18 Oct 2024 14:41:52 +0200 Subject: [PATCH 60/81] Update src/t8_data/t8_data_handler.hxx Co-authored-by: David Knapp --- src/t8_data/t8_data_handler.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 47061d0cf5..75f5809700 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -249,7 +249,7 @@ class t8_data_handler: public t8_abstract_data_handler { } bool - create_handle_for_internal_data (auto &ihandler, type) + create_handle_for_internal_data (t8_abstract_data_handler * const handler, const int type) { switch (type) { // Placeholder for future internal data, which is handled here. From fab64966a69d1479bf7a530485e5d799e5451cdc Mon Sep 17 00:00:00 2001 From: Ole Albers Date: Wed, 13 Nov 2024 15:51:22 +0100 Subject: [PATCH 61/81] add function to base-class --- src/t8_data/t8_data_handler.hxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 75f5809700..ab7325b879 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -123,6 +123,10 @@ class t8_abstract_data_handler { type () = 0; + virtual bool + create_handle_for_internal_data (t8_abstract_data_handler *const handler, const int type) + = 0; + virtual ~t8_abstract_data_handler () {}; }; @@ -249,7 +253,7 @@ class t8_data_handler: public t8_abstract_data_handler { } bool - create_handle_for_internal_data (t8_abstract_data_handler * const handler, const int type) + create_handle_for_internal_data (t8_abstract_data_handler *const handler, const int type) override { switch (type) { // Placeholder for future internal data, which is handled here. From 8d322b51b3ce841999ef29ec4c1bc770e1fbdc23 Mon Sep 17 00:00:00 2001 From: Ole Albers Date: Thu, 14 Nov 2024 10:32:27 +0100 Subject: [PATCH 62/81] fix spelling errors --- example/version/t8_version.cxx | 2 +- src/t8_cmesh/t8_cmesh_readmshfile.cxx | 2 +- .../t8_geometry_implementations/t8_geometry_examples.cxx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/example/version/t8_version.cxx b/example/version/t8_version.cxx index 655315be42..ff85cbf15f 100644 --- a/example/version/t8_version.cxx +++ b/example/version/t8_version.cxx @@ -66,7 +66,7 @@ main (int argc, char **argv) opt = sc_options_new (argv[0]); sc_options_add_switch (opt, 'h', "help", &helpme, "Display a short help message."); sc_options_add_switch (opt, 'v', "verbose", &verbose, - "Print more information. In particual major, minor and patch version."); + "Print more information. In particular major, minor and patch version."); int parsed = sc_options_parse (t8_get_package_id (), SC_LP_ERROR, opt, argc, argv); diff --git a/src/t8_cmesh/t8_cmesh_readmshfile.cxx b/src/t8_cmesh/t8_cmesh_readmshfile.cxx index a356692de2..ce3046616e 100644 --- a/src/t8_cmesh/t8_cmesh_readmshfile.cxx +++ b/src/t8_cmesh/t8_cmesh_readmshfile.cxx @@ -1522,7 +1522,7 @@ t8_cmesh_msh_file_4_read_eles (t8_cmesh_t cmesh, FILE *fp, sc_hash_t *vertices, typedef struct { t8_locidx_t ltree_id; /* The local id of the tree this face belongs to */ - int8_t face_number; /* The number of that face whitin the tree */ + int8_t face_number; /* The number of that face within the tree */ int num_vertices; /* The number of vertices of this face. */ long *vertices; /* The indices of these vertices. */ } t8_msh_file_face_t; diff --git a/src/t8_geometry/t8_geometry_implementations/t8_geometry_examples.cxx b/src/t8_geometry/t8_geometry_implementations/t8_geometry_examples.cxx index 04fcadf40f..2dca1e705a 100644 --- a/src/t8_geometry/t8_geometry_implementations/t8_geometry_examples.cxx +++ b/src/t8_geometry/t8_geometry_implementations/t8_geometry_examples.cxx @@ -97,7 +97,7 @@ t8_geom_evaluate_sphere_tri_prism (const double *active_tree_vertices, const t8_ { // All elements are aligned such that the reference z-direction follows the // outward radial direction of the sphere. Hence the inner radius is equal to - // the norm of the first positition vector of `active_tree_vertices`. + // the norm of the first position vector of `active_tree_vertices`. const double inner_radius = t8_vec_norm (active_tree_vertices); t8_geom_compute_linear_geometry (eclass, active_tree_vertices, ref_coords, num_coords, out_coords); From 5be27c648f15567d05e8263242b79bf4c7fc7acc Mon Sep 17 00:00:00 2001 From: Ole Albers <122293607+ole-alb@users.noreply.github.com> Date: Mon, 25 Nov 2024 15:43:10 +0100 Subject: [PATCH 63/81] Update test/t8_data/t8_pseudo_trees.hxx Co-authored-by: David Knapp --- test/t8_data/t8_pseudo_trees.hxx | 1 + 1 file changed, 1 insertion(+) diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index a2ea17d5ce..44b7990a81 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -125,6 +125,7 @@ class t8_single_data_handler { if (!create_handle_for_internal_data (ihandler, type)) { +/* TODO: This is currently only a placeholder for actual internal data types. */ if (type == 0) { ihandler = std::make_shared>> (); } From f7de80acb2daac6a6be599b50311e3a6c747052f Mon Sep 17 00:00:00 2001 From: David Knapp Date: Fri, 10 Jan 2025 15:49:58 +0100 Subject: [PATCH 64/81] Implement suggestions from review --- src/t8_data/t8_data_handler.hxx | 35 ++--- src/t8_data/t8_data_handler_base.hxx | 47 ++++--- .../t8_data_packs/t8_enlarged_stdtypes.hxx | 128 ++++++++++++++---- src/t8_data/t8_data_packs/t8_packed_types.hxx | 34 ++--- 4 files changed, 171 insertions(+), 73 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index ab7325b879..d3c5b5c9d0 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -1,27 +1,29 @@ /* -This file is part of t8code. -t8code is a C library to manage a collection (a forest) of multiple -connected adaptive space-trees of general element classes in parallel. + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element classes in parallel. -Copyright (C) 2024 the developers + Copyright (C) 2025 the developers -t8code 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 2 of the License, or -(at your option) any later version. + t8code 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 2 of the License, or + (at your option) any later version. -t8code 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. + t8code 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 t8code; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /** - * \file This file provides functions to pack and unpack data for communication and to send and receive it using MPI. + * \file t8_data_handler.hxx + * + * This file provides functions to pack and unpack data for communication and to send and receive it using MPI. * */ @@ -118,6 +120,7 @@ class t8_abstract_data_handler { * This function must be overridden in derived classes to return the type. * * \return An integer representing the type. + * TODO: implement a proper type/enum for this. */ virtual int type () diff --git a/src/t8_data/t8_data_handler_base.hxx b/src/t8_data/t8_data_handler_base.hxx index 22b1ed2e90..2d92f328e9 100644 --- a/src/t8_data/t8_data_handler_base.hxx +++ b/src/t8_data/t8_data_handler_base.hxx @@ -1,35 +1,48 @@ /* -This file is part of t8code. -t8code is a C library to manage a collection (a forest) of multiple -connected adaptive space-trees of general element classes in parallel. +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element classes in parallel. -Copyright (C) 2024 the developers + Copyright (C) 2025 the developers -t8code 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 2 of the License, or -(at your option) any later version. + t8code 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 2 of the License, or + (at your option) any later version. -t8code 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. + t8code 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 t8code; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + #ifndef T8_DATA_HANDLER_BASE #define T8_DATA_HANDLER_BASE /** - * \file This file provides a templated class for handling single data items. + * \file t8_data_handler_base.hxx + * + * This file provides a templated class for handling single data items. * */ #include + +/** + * \class t8_single_data_handler + * \brief A template class for handling single data items. + * + * This class implements methods for packing, unpacking, and determining the size of single data items. + * + * \tparam TType The type of data to be handled. + */ template class t8_single_data_handler { public: @@ -52,7 +65,6 @@ class t8_single_data_handler { /** * Packs the given data into a buffer for communication. * - * \tparam T The type of the data to be packed. * \param[in] data The data to be packed. * \param[in] pos The current position in the buffer where the data should be packed. * \param[in, out] buffer The buffer where the data will be packed. @@ -67,7 +79,6 @@ class t8_single_data_handler { * * This function unpacks data from a given buffer into the provided data structure. * - * \tparam T The type of the data to be unpacked. * \param[in] buffer A pointer to the buffer containing the packed data. * \param[in] num_bytes The number of bytes in the buffer. * \param[in] pos A reference to an integer representing the current position in the buffer. diff --git a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx index 2d32445518..81b991902d 100644 --- a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx +++ b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx @@ -1,23 +1,23 @@ /* -This file is part of t8code. -t8code is a C library to manage a collection (a forest) of multiple -connected adaptive space-trees of general element classes in parallel. + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element classes in parallel. -Copyright (C) 2024 the developers + Copyright (C) 2025 the developers -t8code 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 2 of the License, or -(at your option) any later version. + t8code 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 2 of the License, or + (at your option) any later version. -t8code 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. + t8code 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 t8code; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef T8_ENLARGED_STDTYPES @@ -27,7 +27,9 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include /** - * \file This file provides a templated class for testing single data items. + * \file t8_enlarged_stdtypes.hxx + * + * This file provides a templated class for testing single data items. * */ @@ -37,10 +39,25 @@ along with t8code; if not, write to the Free Software Foundation, Inc., */ enum pseudo_types { T8_ENLARGED_INT = 0, T8_ENLARGED_DOUBLE = 1 }; +/** + * \class t8_single_data_handler + * \brief A template spezialisation for handling single enlarged ints (int plus an additional int, this + * data-type is meant for testing). + * + * This class implements methods for packing, unpacking, and determining the size of single data items. + * + */ template <> class t8_single_data_handler> { public: - int + /** + * Returns the size of an enlarged_int. + * + * \param[in] data The data to compute the size of. + * \param[in] comm The MPI communicator used for communication. + * \return An integer representing the size of the data. + */ + inline int size (const enlarged_data &item, sc_MPI_Comm comm) { int size; @@ -49,7 +66,16 @@ class t8_single_data_handler> { return size; } - void + /** + * Packs an enlarged_int into a buffer for communication. + * + * \param[in] data The data to be packed. + * \param[in] pos The current position in the buffer where the data should be packed. + * \param[in, out] buffer The buffer where the data will be packed. + * \param[in] num_bytes The number of bytes available in the buffer. + * \param[in] comm The MPI communicator used for communication. + */ + inline void pack (const enlarged_data &data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm) { int mpiret = sc_MPI_Pack (&(data.data), 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); @@ -59,7 +85,16 @@ class t8_single_data_handler> { SC_CHECK_MPI (mpiret); } - void + /** + * Unpacks an enlarged_int from a buffer. + * + * \param[in] buffer A pointer to the buffer containing the packed data. + * \param[in] num_bytes The number of bytes in the buffer. + * \param[in] pos A reference to an integer representing the current position in the buffer. + * \param[in, out] data A pointer to the data structure where the unpacked data will be stored. + * \param[in] comm The MPI communicator used for communication. + */ + inline void unpack (const void *buffer, const int num_bytes, int &pos, enlarged_data &data, sc_MPI_Comm comm) { int mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &(data.data), 1, sc_MPI_INT, comm); @@ -69,17 +104,39 @@ class t8_single_data_handler> { SC_CHECK_MPI (mpiret); } - int + /** + * Returns the type of the data handler. + * + * This function returns the type of the data handler. + * + * \return An integer representing the type. + */ + constexpr int type () { return T8_ENLARGED_INT; } }; +/** + * \class t8_single_data_handler + * \brief A template spezialisation for handling single enlarged doubles (double plus an additional int, this + * data-type is meant for testing). + * + * This class implements methods for packing, unpacking, and determining the size of single data items. + * + */ template <> class t8_single_data_handler> { public: - int + /** + * Returns the size of an enlarged_double. + * + * \param[in] data The data to compute the size of. + * \param[in] comm The MPI communicator used for communication. + * \return An integer representing the size of the data. + */ + inline int size (const enlarged_data &item, sc_MPI_Comm comm) { int int_size; @@ -91,7 +148,16 @@ class t8_single_data_handler> { return int_size + double_size; } - void + /** + * Packs an enlarged_double into a buffer for communication. + * + * \param[in] data The data to be packed. + * \param[in] pos The current position in the buffer where the data should be packed. + * \param[in, out] buffer The buffer where the data will be packed. + * \param[in] num_bytes The number of bytes available in the buffer. + * \param[in] comm The MPI communicator used for communication. + */ + inline void pack (const enlarged_data &data, int &pos, void *buffer, const int num_bytes, sc_MPI_Comm comm) { int mpiret = sc_MPI_Pack (&(data.data), 1, sc_MPI_DOUBLE, buffer, num_bytes, &pos, comm); @@ -101,6 +167,15 @@ class t8_single_data_handler> { SC_CHECK_MPI (mpiret); } + /** + * Unpacks an enlarged_double from a buffer. + * + * \param[in] buffer A pointer to the buffer containing the packed data. + * \param[in] num_bytes The number of bytes in the buffer. + * \param[in] pos A reference to an integer representing the current position in the buffer. + * \param[in, out] data A pointer to the data structure where the unpacked data will be stored. + * \param[in] comm The MPI communicator used for communication. + */ void unpack (const void *buffer, const int num_bytes, int &pos, enlarged_data &data, sc_MPI_Comm comm) { @@ -111,7 +186,14 @@ class t8_single_data_handler> { SC_CHECK_MPI (mpiret); } - int + /** + * Returns the type of the data handler. + * + * This function returns the type of the data handler. + * + * \return An integer representing the type. + */ + constexpr int type () { return T8_ENLARGED_DOUBLE; diff --git a/src/t8_data/t8_data_packs/t8_packed_types.hxx b/src/t8_data/t8_data_packs/t8_packed_types.hxx index 29fc55d7c8..8c7d20c28e 100644 --- a/src/t8_data/t8_data_packs/t8_packed_types.hxx +++ b/src/t8_data/t8_data_packs/t8_packed_types.hxx @@ -1,30 +1,32 @@ /* -This file is part of t8code. -t8code is a C library to manage a collection (a forest) of multiple -connected adaptive space-trees of general element classes in parallel. + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element classes in parallel. -Copyright (C) 2024 the developers + Copyright (C) 2025 the developers -t8code 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 2 of the License, or -(at your option) any later version. + t8code 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 2 of the License, or + (at your option) any later version. -t8code 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. + t8code 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 t8code; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + You should have received a copy of the GNU General Public License + along with t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef T8_PACKED_TYPES #define T8_PACKED_TYPES /** - * \file Summary file to include all packed types. + * \file t8_data_handler.hxx + * + * Summary file to include all packed types. * */ From 89cf66a9a23fe705156e7461ada1a37008a8f30b Mon Sep 17 00:00:00 2001 From: David Knapp Date: Mon, 27 Jan 2025 09:21:52 +0100 Subject: [PATCH 65/81] fix comment --- src/t8_data/t8_data_handler_base.hxx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/t8_data/t8_data_handler_base.hxx b/src/t8_data/t8_data_handler_base.hxx index 2d92f328e9..1ace6f630b 100644 --- a/src/t8_data/t8_data_handler_base.hxx +++ b/src/t8_data/t8_data_handler_base.hxx @@ -1,4 +1,3 @@ -/* /* This file is part of t8code. t8code is a C library to manage a collection (a forest) of multiple @@ -21,7 +20,6 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - #ifndef T8_DATA_HANDLER_BASE #define T8_DATA_HANDLER_BASE @@ -34,7 +32,6 @@ #include - /** * \class t8_single_data_handler * \brief A template class for handling single data items. From 6da5a983fe895e7c491e0879eabeaedd14842372 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Mon, 27 Jan 2025 09:35:50 +0100 Subject: [PATCH 66/81] fix typo --- src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx index 81b991902d..23650e925e 100644 --- a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx +++ b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx @@ -41,7 +41,7 @@ enum pseudo_types { T8_ENLARGED_INT = 0, T8_ENLARGED_DOUBLE = 1 }; /** * \class t8_single_data_handler - * \brief A template spezialisation for handling single enlarged ints (int plus an additional int, this + * \brief A template specialisation for handling single enlarged ints (int plus an additional int, this * data-type is meant for testing). * * This class implements methods for packing, unpacking, and determining the size of single data items. @@ -120,7 +120,7 @@ class t8_single_data_handler> { /** * \class t8_single_data_handler - * \brief A template spezialisation for handling single enlarged doubles (double plus an additional int, this + * \brief A template specialisation for handling single enlarged doubles (double plus an additional int, this * data-type is meant for testing). * * This class implements methods for packing, unpacking, and determining the size of single data items. From cbca230222c2ef1dc10e73302de2d6403d032af5 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Mon, 27 Jan 2025 09:38:34 +0100 Subject: [PATCH 67/81] Indent files --- test/t8_data/t8_pseudo_trees.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index 44b7990a81..e54d03f193 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -125,7 +125,7 @@ class t8_single_data_handler { if (!create_handle_for_internal_data (ihandler, type)) { -/* TODO: This is currently only a placeholder for actual internal data types. */ + /* TODO: This is currently only a placeholder for actual internal data types. */ if (type == 0) { ihandler = std::make_shared>> (); } From 7dd35e2883a2e1696644fedf06e396c574b8a860 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Mon, 27 Jan 2025 10:30:01 +0100 Subject: [PATCH 68/81] fix documentation --- src/t8_data/t8_data_handler.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index d3c5b5c9d0..e76ef3b3af 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -59,7 +59,7 @@ class t8_abstract_data_handler { * * \param[in, out] buffer A pointer to the buffer where the vector prefix will be packed. * \param[in] num_bytes The number of bytes to be packed. - * \param[in] pos A reference to an integer representing the current position in the buffer. This will be updated as bytes are packed. + * \param[in, out] pos A reference to an integer representing the current position in the buffer. This will be updated as bytes are packed. * \param[in] comm The MPI communicator used for the operation. */ virtual void From 467daa06ae3fab955222540677dddc8d7924fb9e Mon Sep 17 00:00:00 2001 From: David Knapp Date: Mon, 27 Jan 2025 10:30:30 +0100 Subject: [PATCH 69/81] intermediate commit --- src/t8_data/t8_data_handler.hxx | 27 +++++++++++++-------------- src/t8_data/t8_data_handler_base.hxx | 11 ++++++++++- test/t8_data/t8_pseudo_trees.hxx | 12 +++++++----- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index e76ef3b3af..63b3cb8d60 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -126,10 +126,6 @@ class t8_abstract_data_handler { type () = 0; - virtual bool - create_handle_for_internal_data (t8_abstract_data_handler *const handler, const int type) - = 0; - virtual ~t8_abstract_data_handler () {}; }; @@ -255,16 +251,6 @@ class t8_data_handler: public t8_abstract_data_handler { return single_handler.type (); } - bool - create_handle_for_internal_data (t8_abstract_data_handler *const handler, const int type) override - { - switch (type) { - // Placeholder for future internal data, which is handled here. - default: - return false; - } - } - private: /** * \brief A shared pointer to a vector of data. @@ -278,4 +264,17 @@ class t8_data_handler: public t8_abstract_data_handler { t8_single_data_handler single_handler; }; +t8_abstract_data_handler * +create_internal_handler (const int type) +{ + switch (type) { + case 0: + return new t8_data_handler (); + case 1: + return new t8_data_handler (); + default: + return nullptr; + } +} + #endif /* T8_DATA_HANDLER_HXX */ diff --git a/src/t8_data/t8_data_handler_base.hxx b/src/t8_data/t8_data_handler_base.hxx index 1ace6f630b..dcafb1dd4a 100644 --- a/src/t8_data/t8_data_handler_base.hxx +++ b/src/t8_data/t8_data_handler_base.hxx @@ -29,7 +29,6 @@ * This file provides a templated class for handling single data items. * */ - #include /** @@ -85,6 +84,16 @@ class t8_single_data_handler { void unpack (const void *buffer, const int num_bytes, int &pos, TType &data, sc_MPI_Comm comm); + bool + is_internal_data (const int type) + { + switch (type) { + // Placeholder for future internal data, which is handled here. + default: + return false; + } + } + /** * Returns the type of the data handler. * diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index e54d03f193..00a4fc1a22 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -26,7 +26,7 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include #include -#include +#include #include /** @@ -123,7 +123,7 @@ class t8_single_data_handler { mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &type, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); - if (!create_handle_for_internal_data (ihandler, type)) { + if (!is_internal_data (type)) { /* TODO: This is currently only a placeholder for actual internal data types. */ if (type == 0) { @@ -135,10 +135,12 @@ class t8_single_data_handler { else { SC_ABORT_NOT_REACHED (); } - - int outcount = 0; - ihandler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); } + else { + ihandler = create_handle_for_internal_data (type); + } + int outcount = 0; + ihandler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); } } From 73cb287295dc3edbf399e3eed323d927c5ece560 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Mon, 27 Jan 2025 15:55:50 +0100 Subject: [PATCH 70/81] fix internal_data_handler call --- src/t8_data/t8_data_handler.hxx | 7 ++----- src/t8_data/t8_data_handler_base.hxx | 26 +++++++++++++------------- test/t8_data/t8_pseudo_trees.hxx | 4 ++-- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 63b3cb8d60..7701444032 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -264,14 +264,11 @@ class t8_data_handler: public t8_abstract_data_handler { t8_single_data_handler single_handler; }; -t8_abstract_data_handler * +inline t8_abstract_data_handler * create_internal_handler (const int type) { switch (type) { - case 0: - return new t8_data_handler (); - case 1: - return new t8_data_handler (); + /* Place holder to create a handler for internal data structures */ default: return nullptr; } diff --git a/src/t8_data/t8_data_handler_base.hxx b/src/t8_data/t8_data_handler_base.hxx index dcafb1dd4a..c257f3f446 100644 --- a/src/t8_data/t8_data_handler_base.hxx +++ b/src/t8_data/t8_data_handler_base.hxx @@ -20,8 +20,8 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef T8_DATA_HANDLER_BASE -#define T8_DATA_HANDLER_BASE +#ifndef T8_DATA_HANDLER_BASE_HXX +#define T8_DATA_HANDLER_BASE_HXX /** * \file t8_data_handler_base.hxx @@ -31,6 +31,16 @@ */ #include +inline bool +is_internal_data (const int type) +{ + switch (type) { + // Placeholder for future internal data, which is handled here. + default: + return false; + } +}; + /** * \class t8_single_data_handler * \brief A template class for handling single data items. @@ -84,16 +94,6 @@ class t8_single_data_handler { void unpack (const void *buffer, const int num_bytes, int &pos, TType &data, sc_MPI_Comm comm); - bool - is_internal_data (const int type) - { - switch (type) { - // Placeholder for future internal data, which is handled here. - default: - return false; - } - } - /** * Returns the type of the data handler. * @@ -107,4 +107,4 @@ class t8_single_data_handler { ~t8_single_data_handler () {}; }; -#endif /* T8_DATA_HANDLER_BASE */ +#endif /* T8_DATA_HANDLER_BASE_HXX */ diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index 00a4fc1a22..555fc1a56b 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -26,7 +26,7 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include #include -#include +#include #include /** @@ -137,7 +137,7 @@ class t8_single_data_handler { } } else { - ihandler = create_handle_for_internal_data (type); + ihandler = std::shared_ptr (create_internal_handler (type)); } int outcount = 0; ihandler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); From a86628160a8d5d071a7410a975daeaae2cc30943 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Mon, 27 Jan 2025 15:57:07 +0100 Subject: [PATCH 71/81] renamed template parameter in the tests --- test/t8_data/t8_gtest_data_handler.cxx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 9a6ed0fd4f..83c5e09d2d 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -39,7 +39,7 @@ along with t8code; if not, write to the Free Software Foundation, Inc., * * @tparam T the type of data */ -template +template class data_handler_test: public testing::Test { protected: void @@ -49,9 +49,9 @@ class data_handler_test: public testing::Test { SC_CHECK_MPI (mpiret); mpiret = sc_MPI_Comm_size (comm, &mpisize); SC_CHECK_MPI (mpiret); - creator = data_creator> (); + creator = data_creator> (); creator.create (max_num_data); - data_handler = new t8_data_handler> (creator.large_data); + data_handler = new t8_data_handler> (creator.large_data); } void @@ -60,9 +60,9 @@ class data_handler_test: public testing::Test { delete data_handler; } - t8_data_handler> *data_handler; - data_creator> creator; - std::vector> recv_data; + t8_data_handler> *data_handler; + data_creator> creator; + std::vector> recv_data; int mpirank; int mpisize; const int max_num_data = 100; From 943dd6bec5f7f550d3a1faa71ac13093bea9d054 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Wed, 12 Feb 2025 15:27:05 +0100 Subject: [PATCH 72/81] Apply suggestions from code review Co-authored-by: Sandro Elsweijer <49643115+sandro-elsweijer@users.noreply.github.com> --- src/t8_data/t8_data_handler.hxx | 9 ++++----- src/t8_data/t8_data_handler_base.hxx | 3 +-- src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx | 5 ++--- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 7701444032..56257d46c8 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -130,8 +130,7 @@ class t8_abstract_data_handler { }; /** - * \class t8_data_handler - * \brief A template class for handling data in a distributed environment. + * A template class for handling data in a distributed environment. * * This class inherits from t8_abstract_data_handler and provides methods for * packing, unpacking, sending, and receiving data using MPI. @@ -161,7 +160,7 @@ class t8_data_handler: public t8_abstract_data_handler { } /** - * \brief Get the data. + * Get the data. * * \return std::shared_ptr> */ @@ -253,12 +252,12 @@ class t8_data_handler: public t8_abstract_data_handler { private: /** - * \brief A shared pointer to a vector of data. + * A shared pointer to a vector of data. * This data will be packed, unpacked, and communicated via MPI. */ std::shared_ptr> m_data; /** - * \brief A single data handler for the data type T. + * A single data handler for the data type T. * This handler will be used to pack and unpack individual data items. */ t8_single_data_handler single_handler; diff --git a/src/t8_data/t8_data_handler_base.hxx b/src/t8_data/t8_data_handler_base.hxx index c257f3f446..2634184ce6 100644 --- a/src/t8_data/t8_data_handler_base.hxx +++ b/src/t8_data/t8_data_handler_base.hxx @@ -42,8 +42,7 @@ is_internal_data (const int type) }; /** - * \class t8_single_data_handler - * \brief A template class for handling single data items. + * Template class for handling single data items. * * This class implements methods for packing, unpacking, and determining the size of single data items. * diff --git a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx index 23650e925e..ce5c470c05 100644 --- a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx +++ b/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx @@ -34,14 +34,13 @@ */ /** - * \brief pseudo_types for testing + * pseudo_types for testing * */ enum pseudo_types { T8_ENLARGED_INT = 0, T8_ENLARGED_DOUBLE = 1 }; /** - * \class t8_single_data_handler - * \brief A template specialisation for handling single enlarged ints (int plus an additional int, this + * A template specialisation for handling single enlarged ints (int plus an additional int, this * data-type is meant for testing). * * This class implements methods for packing, unpacking, and determining the size of single data items. From 06302b837dda90169151746f9bffc74dfd4fd735 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Thu, 13 Feb 2025 09:37:41 +0100 Subject: [PATCH 73/81] Update file-structure --- src/t8_data/t8_data_packs/t8_packed_types.hxx | 35 ------------------- .../t8_data}/t8_enlarged_stdtypes.hxx | 0 test/t8_data/t8_gtest_data_handler.cxx | 2 +- 3 files changed, 1 insertion(+), 36 deletions(-) delete mode 100644 src/t8_data/t8_data_packs/t8_packed_types.hxx rename {src/t8_data/t8_data_packs => test/t8_data}/t8_enlarged_stdtypes.hxx (100%) diff --git a/src/t8_data/t8_data_packs/t8_packed_types.hxx b/src/t8_data/t8_data_packs/t8_packed_types.hxx deleted file mode 100644 index 8c7d20c28e..0000000000 --- a/src/t8_data/t8_data_packs/t8_packed_types.hxx +++ /dev/null @@ -1,35 +0,0 @@ -/* - This file is part of t8code. - t8code is a C library to manage a collection (a forest) of multiple - connected adaptive space-trees of general element classes in parallel. - - Copyright (C) 2025 the developers - - t8code 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 2 of the License, or - (at your option) any later version. - - t8code 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 t8code; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef T8_PACKED_TYPES -#define T8_PACKED_TYPES - -/** - * \file t8_data_handler.hxx - * - * Summary file to include all packed types. - * - */ - -#include - -#endif /* T8_PACKED_TYPES */ diff --git a/src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx b/test/t8_data/t8_enlarged_stdtypes.hxx similarity index 100% rename from src/t8_data/t8_data_packs/t8_enlarged_stdtypes.hxx rename to test/t8_data/t8_enlarged_stdtypes.hxx diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 83c5e09d2d..cede3bc31f 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -21,7 +21,7 @@ along with t8code; if not, write to the Free Software Foundation, Inc., */ #include -#include +#include #include #include #include From 1d9f03e82d8909154341e71efaf25edbe65aef85 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Thu, 13 Feb 2025 09:50:28 +0100 Subject: [PATCH 74/81] Rename classes t8_single_data_handler -> t8_data_handler t8_abstract_data_handler -> t8_abstract_vector_handler t8_data_handler -> t8_vector_handler --- src/t8_data/t8_data_handler.hxx | 14 +++++----- src/t8_data/t8_data_handler_base.hxx | 6 ++-- test/t8_data/t8_enlarged_stdtypes.hxx | 4 +-- test/t8_data/t8_gtest_data_handler.cxx | 38 ++++++++++++++------------ test/t8_data/t8_pseudo_trees.hxx | 10 +++---- 5 files changed, 37 insertions(+), 35 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index 56257d46c8..669b82f2d2 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -37,7 +37,7 @@ #include #include -class t8_abstract_data_handler { +class t8_abstract_vector_handler { public: /** * Pure virtual function to determine the buffer size. @@ -126,7 +126,7 @@ class t8_abstract_data_handler { type () = 0; - virtual ~t8_abstract_data_handler () {}; + virtual ~t8_abstract_vector_handler () {}; }; /** @@ -138,13 +138,13 @@ class t8_abstract_data_handler { * \tparam TType The type of data to be handled. */ template -class t8_data_handler: public t8_abstract_data_handler { +class t8_vector_handler: public t8_abstract_vector_handler { public: /** * Construct a new t8 data handler. * m_data is initialized to nullptr. */ - t8_data_handler (): single_handler () + t8_vector_handler (): single_handler () { m_data = nullptr; } @@ -154,7 +154,7 @@ class t8_data_handler: public t8_abstract_data_handler { * * \param[in] data The data to be handled. */ - t8_data_handler (const std::vector &data) + t8_vector_handler (const std::vector &data) : m_data (std::make_shared> (data)), single_handler () { } @@ -260,10 +260,10 @@ class t8_data_handler: public t8_abstract_data_handler { * A single data handler for the data type T. * This handler will be used to pack and unpack individual data items. */ - t8_single_data_handler single_handler; + t8_data_handler single_handler; }; -inline t8_abstract_data_handler * +inline t8_abstract_vector_handler * create_internal_handler (const int type) { switch (type) { diff --git a/src/t8_data/t8_data_handler_base.hxx b/src/t8_data/t8_data_handler_base.hxx index 2634184ce6..b44213744c 100644 --- a/src/t8_data/t8_data_handler_base.hxx +++ b/src/t8_data/t8_data_handler_base.hxx @@ -49,13 +49,13 @@ is_internal_data (const int type) * \tparam TType The type of data to be handled. */ template -class t8_single_data_handler { +class t8_data_handler { public: /** * Construct a new t8 single data handler. * */ - t8_single_data_handler () {}; + t8_data_handler () {}; /** * Returns the size of the data. @@ -103,7 +103,7 @@ class t8_single_data_handler { int type (); - ~t8_single_data_handler () {}; + ~t8_data_handler () {}; }; #endif /* T8_DATA_HANDLER_BASE_HXX */ diff --git a/test/t8_data/t8_enlarged_stdtypes.hxx b/test/t8_data/t8_enlarged_stdtypes.hxx index ce5c470c05..50a551dd02 100644 --- a/test/t8_data/t8_enlarged_stdtypes.hxx +++ b/test/t8_data/t8_enlarged_stdtypes.hxx @@ -47,7 +47,7 @@ enum pseudo_types { T8_ENLARGED_INT = 0, T8_ENLARGED_DOUBLE = 1 }; * */ template <> -class t8_single_data_handler> { +class t8_data_handler> { public: /** * Returns the size of an enlarged_int. @@ -126,7 +126,7 @@ class t8_single_data_handler> { * */ template <> -class t8_single_data_handler> { +class t8_data_handler> { public: /** * Returns the size of an enlarged_double. diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index cede3bc31f..5433885191 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -51,7 +51,7 @@ class data_handler_test: public testing::Test { SC_CHECK_MPI (mpiret); creator = data_creator> (); creator.create (max_num_data); - data_handler = new t8_data_handler> (creator.large_data); + data_handler = new t8_vector_handler> (creator.large_data); } void @@ -60,7 +60,7 @@ class data_handler_test: public testing::Test { delete data_handler; } - t8_data_handler> *data_handler; + t8_vector_handler> *data_handler; data_creator> creator; std::vector> recv_data; int mpirank; @@ -149,9 +149,9 @@ TEST (data_handler_test, multiple_handler) double_data[idata].data = (double) idata + fraction; double_data[idata].check = mpirank; } - t8_data_handler> int_handler (int_data); - t8_data_handler> double_handler (double_data); - std::vector handler; + t8_vector_handler> int_handler (int_data); + t8_vector_handler> double_handler (double_data); + std::vector handler; handler.push_back (&int_handler); handler.push_back (&double_handler); @@ -161,7 +161,7 @@ TEST (data_handler_test, multiple_handler) int send_to = (mpirank + 1) % mpisize; /* Compute the rank this rank receives from. */ int recv_from = (mpirank == 0) ? (mpisize - 1) : (mpirank - 1); - for (t8_abstract_data_handler *ihandler : handler) { + for (t8_abstract_vector_handler *ihandler : handler) { mpiret = ihandler->send (send_to, 0, comm); SC_CHECK_MPI (mpiret); @@ -171,9 +171,9 @@ TEST (data_handler_test, multiple_handler) mpiret = ihandler->recv (recv_from, 0, comm, &status, outcount); } - std::vector> recv_ints = *((t8_data_handler> *) (handler[0]))->get_data (); + std::vector> recv_ints = *((t8_vector_handler> *) (handler[0]))->get_data (); std::vector> recv_doubles - = *((t8_data_handler> *) (handler[1]))->get_data (); + = *((t8_vector_handler> *) (handler[1]))->get_data (); SC_CHECK_MPI (mpiret); for (int idata = 0; idata < num_data; idata++) { @@ -198,13 +198,13 @@ TEST (data_handler_test, pseudo_tree_test) int_data[idata].data = idata; } tree.tree_data.resize (1); - tree.tree_data[0] = std::make_shared>> (std::move (int_data)); + tree.tree_data[0] = std::make_shared>> (std::move (int_data)); pseudo_tree tree_copy (tree); EXPECT_EQ (tree.topo_data.size (), tree_copy.topo_data.size ()); EXPECT_EQ (tree.tree_data.size (), tree_copy.tree_data.size ()); - auto handler = std::dynamic_pointer_cast>> (tree_copy.tree_data[0]).get (); + auto handler = std::dynamic_pointer_cast>> (tree_copy.tree_data[0]).get (); ASSERT_NE (handler, nullptr); std::vector> copied_data = *(handler->get_data ()); @@ -218,7 +218,8 @@ TEST (data_handler_test, pseudo_tree_test) EXPECT_EQ (tree.topo_data.size (), tree_equal.topo_data.size ()); EXPECT_EQ (tree.tree_data.size (), tree_equal.tree_data.size ()); - auto handler_equal = std::dynamic_pointer_cast>> (tree_equal.tree_data[0]).get (); + auto handler_equal + = std::dynamic_pointer_cast>> (tree_equal.tree_data[0]).get (); ASSERT_NE (handler_equal, nullptr); std::vector> equal_data = *(handler_equal->get_data ()); @@ -259,7 +260,7 @@ TEST (data_handler_test, tree_test) int_data[idata].check = mpirank; int_data[idata].data = idata; } - tree.tree_data[itree_data] = std::make_shared>> (std::move (int_data)); + tree.tree_data[itree_data] = std::make_shared>> (std::move (int_data)); } else { std::vector> double_data (num_data); @@ -267,13 +268,14 @@ TEST (data_handler_test, tree_test) double_data[idata].check = mpirank; double_data[idata].data = static_cast (idata) + fraction; } - tree.tree_data[itree_data] = std::make_shared>> (std::move (double_data)); + tree.tree_data[itree_data] + = std::make_shared>> (std::move (double_data)); } } trees[itree] = std::move (tree); } - t8_data_handler tree_handler (trees); + t8_vector_handler tree_handler (trees); const int send_to = (mpirank + 1) % mpisize; const int recv_from = (mpirank == 0) ? (mpisize - 1) : (mpirank - 1); @@ -302,7 +304,7 @@ TEST (data_handler_test, tree_test) for (int itree_data = 0; itree_data < num_recv_tree_data; ++itree_data) { if (itree_data == 0) { auto int_handler - = std::dynamic_pointer_cast>> (recv_trees[itree].tree_data[itree_data]) + = std::dynamic_pointer_cast>> (recv_trees[itree].tree_data[itree_data]) .get (); ASSERT_NE (int_handler, nullptr); std::vector> recv_ints = *(int_handler->get_data ()); @@ -314,9 +316,9 @@ TEST (data_handler_test, tree_test) } } else { - auto double_handler - = std::dynamic_pointer_cast>> (recv_trees[itree].tree_data[itree_data]) - .get (); + auto double_handler = std::dynamic_pointer_cast>> ( + recv_trees[itree].tree_data[itree_data]) + .get (); ASSERT_NE (double_handler, nullptr); std::vector> recv_double = *(double_handler->get_data ()); ASSERT_EQ (static_cast (recv_double.size ()), num_data); diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index 555fc1a56b..6f56cde441 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -47,11 +47,11 @@ along with t8code; if not, write to the Free Software Foundation, Inc., class pseudo_tree { public: std::vector topo_data; - std::vector> tree_data; + std::vector> tree_data; }; template <> -class t8_single_data_handler { +class t8_data_handler { public: int size (const pseudo_tree &item, sc_MPI_Comm comm) @@ -127,17 +127,17 @@ class t8_single_data_handler { /* TODO: This is currently only a placeholder for actual internal data types. */ if (type == 0) { - ihandler = std::make_shared>> (); + ihandler = std::make_shared>> (); } else if (type == 1) { - ihandler = std::make_shared>> (); + ihandler = std::make_shared>> (); } else { SC_ABORT_NOT_REACHED (); } } else { - ihandler = std::shared_ptr (create_internal_handler (type)); + ihandler = std::shared_ptr (create_internal_handler (type)); } int outcount = 0; ihandler->unpack_vector_prefix (buffer, num_bytes, pos, outcount, comm); From 0465dbc08ef6eb0d2a879931630383a46560d5a7 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Thu, 13 Feb 2025 09:54:33 +0100 Subject: [PATCH 75/81] Rename file t8_data_handler.hxx -> t8_vector_handler.hxx --- src/t8_data/{t8_data_handler.hxx => t8_vector_handler.hxx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/t8_data/{t8_data_handler.hxx => t8_vector_handler.hxx} (100%) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_vector_handler.hxx similarity index 100% rename from src/t8_data/t8_data_handler.hxx rename to src/t8_data/t8_vector_handler.hxx From ac3292dd5b681660275a5514185c0fc82985d3d0 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Thu, 13 Feb 2025 09:56:09 +0100 Subject: [PATCH 76/81] update includes and include-guards --- src/t8_data/t8_vector_handler.hxx | 6 +++--- test/t8_data/t8_data_handler_specs.hxx | 2 +- test/t8_data/t8_gtest_data_handler.cxx | 2 +- test/t8_data/t8_pseudo_trees.hxx | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/t8_data/t8_vector_handler.hxx b/src/t8_data/t8_vector_handler.hxx index 669b82f2d2..70e0769cdb 100644 --- a/src/t8_data/t8_vector_handler.hxx +++ b/src/t8_data/t8_vector_handler.hxx @@ -27,8 +27,8 @@ * */ -#ifndef T8_DATA_HANDLER_HXX -#define T8_DATA_HANDLER_HXX +#ifndef T8_VECTOR_HANDLER_HXX +#define T8_VECTOR_HANDLER_HXX #include #include @@ -273,4 +273,4 @@ create_internal_handler (const int type) } } -#endif /* T8_DATA_HANDLER_HXX */ +#endif /* T8_VECTOR_HANDLER_HXX */ diff --git a/test/t8_data/t8_data_handler_specs.hxx b/test/t8_data/t8_data_handler_specs.hxx index 8d3a7c48d2..176a6c83dd 100644 --- a/test/t8_data/t8_data_handler_specs.hxx +++ b/test/t8_data/t8_data_handler_specs.hxx @@ -30,7 +30,7 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include -#include +#include /** * \class enlarged_data diff --git a/test/t8_data/t8_gtest_data_handler.cxx b/test/t8_data/t8_gtest_data_handler.cxx index 5433885191..97afdec03c 100644 --- a/test/t8_data/t8_gtest_data_handler.cxx +++ b/test/t8_data/t8_gtest_data_handler.cxx @@ -24,7 +24,7 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include #include -#include +#include #include #include diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index 6f56cde441..2e2dc7ccb7 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -26,7 +26,7 @@ along with t8code; if not, write to the Free Software Foundation, Inc., #include #include #include -#include +#include #include /** From 6572ed8f3a8f695aa2c358e29e1d17dab88f827c Mon Sep 17 00:00:00 2001 From: David Knapp Date: Thu, 13 Feb 2025 09:57:13 +0100 Subject: [PATCH 77/81] Rename file t8_data_handler_base.hxx -> t8_data_handler.hxx --- src/t8_data/{t8_data_handler_base.hxx => t8_data_handler.hxx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/t8_data/{t8_data_handler_base.hxx => t8_data_handler.hxx} (100%) diff --git a/src/t8_data/t8_data_handler_base.hxx b/src/t8_data/t8_data_handler.hxx similarity index 100% rename from src/t8_data/t8_data_handler_base.hxx rename to src/t8_data/t8_data_handler.hxx From c408d2f4bd3593ed0264e0c5df20e4776e6d7ba1 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Thu, 13 Feb 2025 09:59:03 +0100 Subject: [PATCH 78/81] update includes and include-guards --- src/t8_data/t8_data_handler.hxx | 8 ++++---- src/t8_data/t8_vector_handler.hxx | 4 ++-- test/t8_data/t8_enlarged_stdtypes.hxx | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index b44213744c..abf2c29976 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -20,11 +20,11 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef T8_DATA_HANDLER_BASE_HXX -#define T8_DATA_HANDLER_BASE_HXX +#ifndef T8_DATA_HANDLER_HXX +#define T8_DATA_HANDLER_HXX /** - * \file t8_data_handler_base.hxx + * \file t8_data_handler.hxx * * This file provides a templated class for handling single data items. * @@ -106,4 +106,4 @@ class t8_data_handler { ~t8_data_handler () {}; }; -#endif /* T8_DATA_HANDLER_BASE_HXX */ +#endif /* T8_DATA_HANDLER_HXX */ diff --git a/src/t8_data/t8_vector_handler.hxx b/src/t8_data/t8_vector_handler.hxx index 70e0769cdb..d17aa7ddb6 100644 --- a/src/t8_data/t8_vector_handler.hxx +++ b/src/t8_data/t8_vector_handler.hxx @@ -21,7 +21,7 @@ */ /** - * \file t8_data_handler.hxx + * \file t8_vector_handler.hxx * * This file provides functions to pack and unpack data for communication and to send and receive it using MPI. * @@ -32,7 +32,7 @@ #include #include -#include +#include #include #include #include diff --git a/test/t8_data/t8_enlarged_stdtypes.hxx b/test/t8_data/t8_enlarged_stdtypes.hxx index 50a551dd02..69ed5f92ad 100644 --- a/test/t8_data/t8_enlarged_stdtypes.hxx +++ b/test/t8_data/t8_enlarged_stdtypes.hxx @@ -24,7 +24,7 @@ #define T8_ENLARGED_STDTYPES #include -#include +#include /** * \file t8_enlarged_stdtypes.hxx From b87e4b5593099972e22317a6122ffa3de18e2bf2 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Thu, 13 Feb 2025 16:19:05 +0100 Subject: [PATCH 79/81] use a T8Type to descripe the type of data handler --- src/t8_data/t8_data_handler.hxx | 9 +++++---- src/t8_data/t8_vector_handler.hxx | 10 +++++----- test/t8_data/t8_pseudo_trees.hxx | 12 ++++++------ 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index abf2c29976..a98a05e6ce 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -30,11 +30,12 @@ * */ #include +#include -inline bool -is_internal_data (const int type) +constexpr bool +is_internal_data (const t8_data_handler_type type) { - switch (type) { + switch (type.underlying ().get ()) { // Placeholder for future internal data, which is handled here. default: return false; @@ -100,7 +101,7 @@ class t8_data_handler { * * \return An integer representing the type. */ - int + t8_data_handler_type type (); ~t8_data_handler () {}; diff --git a/src/t8_data/t8_vector_handler.hxx b/src/t8_data/t8_vector_handler.hxx index d17aa7ddb6..a4633bb895 100644 --- a/src/t8_data/t8_vector_handler.hxx +++ b/src/t8_data/t8_vector_handler.hxx @@ -122,7 +122,7 @@ class t8_abstract_vector_handler { * \return An integer representing the type. * TODO: implement a proper type/enum for this. */ - virtual int + virtual t8_data_handler_type type () = 0; @@ -244,10 +244,10 @@ class t8_vector_handler: public t8_abstract_vector_handler { return mpiret; } - int + t8_data_handler_type type () override { - return single_handler.type (); + return t8_data_handler_type (single_handler.type ()); } private: @@ -264,9 +264,9 @@ class t8_vector_handler: public t8_abstract_vector_handler { }; inline t8_abstract_vector_handler * -create_internal_handler (const int type) +create_internal_handler (const t8_data_handler_type type) { - switch (type) { + switch (type.underlying ().get ()) { /* Place holder to create a handler for internal data structures */ default: return nullptr; diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index 2e2dc7ccb7..eeea68235c 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -89,7 +89,7 @@ class t8_data_handler { SC_CHECK_MPI (mpiret); for (const auto &handler : data.tree_data) { - const int type = handler->type (); + const t8_data_handler_type type = handler->type (); /* Pack type of tree data */ mpiret = sc_MPI_Pack (&type, 1, sc_MPI_INT, buffer, num_bytes, &pos, comm); SC_CHECK_MPI (mpiret); @@ -119,17 +119,17 @@ class t8_data_handler { data.tree_data.resize (num_handler); for (auto &ihandler : data.tree_data) { - int type; + t8_data_handler_type type; mpiret = sc_MPI_Unpack (buffer, num_bytes, &pos, &type, 1, sc_MPI_INT, comm); SC_CHECK_MPI (mpiret); if (!is_internal_data (type)) { /* TODO: This is currently only a placeholder for actual internal data types. */ - if (type == 0) { + if (type.underlying ().get () == 0) { ihandler = std::make_shared>> (); } - else if (type == 1) { + else if (type.underlying ().get () == 1) { ihandler = std::make_shared>> (); } else { @@ -144,10 +144,10 @@ class t8_data_handler { } } - int + constexpr t8_data_handler_type type () { - return -1; + return t8_data_handler_type (-1); } }; From dc3db9a8c41de1bf4229db7b705901bee863a364 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Thu, 13 Feb 2025 16:37:49 +0100 Subject: [PATCH 80/81] make type() a constexpr --- src/t8_data/t8_data_handler.hxx | 2 +- src/t8_data/t8_vector_handler.hxx | 4 ++-- test/t8_data/t8_enlarged_stdtypes.hxx | 8 ++++---- test/t8_data/t8_pseudo_trees.hxx | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/t8_data/t8_data_handler.hxx b/src/t8_data/t8_data_handler.hxx index a98a05e6ce..aa63c5a440 100644 --- a/src/t8_data/t8_data_handler.hxx +++ b/src/t8_data/t8_data_handler.hxx @@ -35,7 +35,7 @@ constexpr bool is_internal_data (const t8_data_handler_type type) { - switch (type.underlying ().get ()) { + switch (type.get ()) { // Placeholder for future internal data, which is handled here. default: return false; diff --git a/src/t8_data/t8_vector_handler.hxx b/src/t8_data/t8_vector_handler.hxx index a4633bb895..9e49c0c826 100644 --- a/src/t8_data/t8_vector_handler.hxx +++ b/src/t8_data/t8_vector_handler.hxx @@ -244,7 +244,7 @@ class t8_vector_handler: public t8_abstract_vector_handler { return mpiret; } - t8_data_handler_type + constexpr t8_data_handler_type type () override { return t8_data_handler_type (single_handler.type ()); @@ -266,7 +266,7 @@ class t8_vector_handler: public t8_abstract_vector_handler { inline t8_abstract_vector_handler * create_internal_handler (const t8_data_handler_type type) { - switch (type.underlying ().get ()) { + switch (type.get ()) { /* Place holder to create a handler for internal data structures */ default: return nullptr; diff --git a/test/t8_data/t8_enlarged_stdtypes.hxx b/test/t8_data/t8_enlarged_stdtypes.hxx index 69ed5f92ad..fbc5d1d95b 100644 --- a/test/t8_data/t8_enlarged_stdtypes.hxx +++ b/test/t8_data/t8_enlarged_stdtypes.hxx @@ -110,10 +110,10 @@ class t8_data_handler> { * * \return An integer representing the type. */ - constexpr int + constexpr t8_data_handler_type type () { - return T8_ENLARGED_INT; + return t8_data_handler_type (T8_ENLARGED_INT); } }; @@ -192,10 +192,10 @@ class t8_data_handler> { * * \return An integer representing the type. */ - constexpr int + constexpr t8_data_handler_type type () { - return T8_ENLARGED_DOUBLE; + return t8_data_handler_type (T8_ENLARGED_DOUBLE); } }; diff --git a/test/t8_data/t8_pseudo_trees.hxx b/test/t8_data/t8_pseudo_trees.hxx index eeea68235c..4e33bd8d37 100644 --- a/test/t8_data/t8_pseudo_trees.hxx +++ b/test/t8_data/t8_pseudo_trees.hxx @@ -126,10 +126,10 @@ class t8_data_handler { if (!is_internal_data (type)) { /* TODO: This is currently only a placeholder for actual internal data types. */ - if (type.underlying ().get () == 0) { + if (type.get () == 0) { ihandler = std::make_shared>> (); } - else if (type.underlying ().get () == 1) { + else if (type.get () == 1) { ihandler = std::make_shared>> (); } else { From 52a8b5762960cd8f1adde16f6b55cd14bc10c315 Mon Sep 17 00:00:00 2001 From: David Knapp Date: Thu, 13 Feb 2025 16:45:58 +0100 Subject: [PATCH 81/81] Add the description of t8_data_handler_type --- src/t8_types/t8_data_handler_type.hxx | 43 +++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/t8_types/t8_data_handler_type.hxx diff --git a/src/t8_types/t8_data_handler_type.hxx b/src/t8_types/t8_data_handler_type.hxx new file mode 100644 index 0000000000..4fca3a9334 --- /dev/null +++ b/src/t8_types/t8_data_handler_type.hxx @@ -0,0 +1,43 @@ +/* + This file is part of t8code. + t8code is a C library to manage a collection (a forest) of multiple + connected adaptive space-trees of general element classes in parallel. + + Copyright (C) 2025 the developers + + t8code 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 2 of the License, or + (at your option) any later version. + + t8code 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 t8code; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef T8_DATA_HANDLER_TYPE_HXX +#define T8_DATA_HANDLER_TYPE_HXX + +#include +#include + +/** \file + * This file provides a strong type for the data handler. + */ + +struct t8_data_handler_tag +{ +}; + +/** + * Strong type to describe the data handler type. + * + */ +using t8_data_handler_type = T8Type; + +#endif /* T8_DATA_HANDLER_TYPE_HXX */