From 37d801e372c69bc02c39ab8694a3f76307978ecf Mon Sep 17 00:00:00 2001 From: Bruno Turcksin Date: Tue, 15 Feb 2022 19:07:28 +0000 Subject: [PATCH] Add tests --- tests/arborx/distributed_tree_intersect.cc | 201 +++++++++++ ...distributed_tree_intersect.mpirun=2.output | 3 + tests/arborx/distributed_tree_nearest.cc | 330 ++++++++++++++++++ .../distributed_tree_nearest.mpirun=2.output | 3 + 4 files changed, 537 insertions(+) create mode 100644 tests/arborx/distributed_tree_intersect.cc create mode 100644 tests/arborx/distributed_tree_intersect.mpirun=2.output create mode 100644 tests/arborx/distributed_tree_nearest.cc create mode 100644 tests/arborx/distributed_tree_nearest.mpirun=2.output diff --git a/tests/arborx/distributed_tree_intersect.cc b/tests/arborx/distributed_tree_intersect.cc new file mode 100644 index 0000000000..e388b5490f --- /dev/null +++ b/tests/arborx/distributed_tree_intersect.cc @@ -0,0 +1,201 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2022 by the deal.II authors +// +// This file is part of the deal.II library. +// +// The deal.II library is free software; you can use it, redistribute +// it, and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// The full text of the license can be found in the file LICENSE.md at +// the top level directory of deal.II. +// +// --------------------------------------------------------------------- + + +// Check ArborX wrapper: intersection of bounding boxes + + +#include +#include + +#include + +#include "../tests.h" + + +void +test_2d() +{ + std::vector> bounding_boxes; + std::vector> points; + + const unsigned int n_points_1d = 5; + const int rank = Utilities::MPI::this_mpi_process(MPI_COMM_WORLD); + const int n_procs = Utilities::MPI::n_mpi_processes(MPI_COMM_WORLD); + const int offset_bb = 2 * rank * n_points_1d; + const int offset_query = 2 * ((rank + 1) % n_procs) * n_points_1d; + for (unsigned int i = 0; i < n_points_1d; ++i) + { + for (unsigned int j = 0; j < n_points_1d; ++j) + { + points.emplace_back(j + offset_bb, i + offset_bb); + } + } + + for (unsigned int i = 0; i < n_points_1d - 1; ++i) + { + for (unsigned int j = 0; j < n_points_1d - 1; ++j) + { + unsigned int point_index = j + i * n_points_1d; + bounding_boxes.push_back( + std::make_pair(points[point_index], + points[point_index + n_points_1d + 1])); + } + } + + Point<2> point_a(0.5 + offset_query, 0.5 + offset_query); + Point<2> point_b(1.5 + offset_query, 1.5 + offset_query); + Point<2> point_c(2.2 + offset_query, 2.2 + offset_query); + Point<2> point_d(2.6 + offset_query, 2.6 + offset_query); + + std::vector> query_bounding_boxes; + query_bounding_boxes.emplace_back(std::make_pair(point_a, point_b)); + query_bounding_boxes.emplace_back(std::make_pair(point_c, point_d)); + + ArborXWrappers::DistributedTree distributed_tree(MPI_COMM_WORLD, + bounding_boxes); + ArborXWrappers::BoundingBoxIntersectPredicate bb_intersect( + query_bounding_boxes); + auto indices_ranks_offset = distributed_tree.query(bb_intersect); + auto indices_ranks = indices_ranks_offset.first; + auto offsets = indices_ranks_offset.second; + + std::vector indices_ref = {0, 1, 4, 5, 10}; + std::vector offsets_ref = {0, 4, 5}; + + AssertThrow(indices_ranks.size() == indices_ref.size(), ExcInternalError()); + AssertThrow(offsets.size() == offsets_ref.size(), ExcInternalError()); + for (unsigned int i = 0; i < offsets.size() - 1; ++i) + { + for (int j = offsets[i]; j < offsets[i + 1]; ++j) + { + // The indices associated to each query are not ordered. + bool found = false; + for (int k = offsets[i]; k < offsets[i + 1]; ++k) + { + if ((indices_ranks[j].first == indices_ref[k]) && + (indices_ranks[j].second == (rank + 1) % n_procs)) + { + found = true; + break; + } + } + AssertThrow(found, ExcInternalError()); + } + } + for (unsigned int i = 0; i < offsets.size(); ++i) + AssertThrow(offsets[i] == offsets_ref[i], ExcInternalError()); + + deallog << "OK" << std::endl; +} + +void +test_3d() +{ + std::vector> bounding_boxes; + std::vector> points; + + unsigned int n_points_1d = 5; + const int rank = Utilities::MPI::this_mpi_process(MPI_COMM_WORLD); + const int n_procs = Utilities::MPI::n_mpi_processes(MPI_COMM_WORLD); + const int offset_bb = 2 * rank * n_points_1d; + const int offset_query = 2 * ((rank + 1) % n_procs) * n_points_1d; + for (unsigned int i = 0; i < n_points_1d; ++i) + { + for (unsigned int j = 0; j < n_points_1d; ++j) + { + for (unsigned int k = 0; k < n_points_1d; ++k) + { + points.emplace_back(k + offset_bb, j + offset_bb, i + offset_bb); + } + } + } + + for (unsigned int i = 0; i < n_points_1d - 1; ++i) + { + for (unsigned int j = 0; j < n_points_1d - 1; ++j) + { + for (unsigned int k = 0; k < n_points_1d - 1; ++k) + { + unsigned int point_index = + k + j * n_points_1d + i * n_points_1d * n_points_1d; + bounding_boxes.push_back( + std::make_pair(points[point_index], + points[point_index + n_points_1d * n_points_1d + + n_points_1d + 1])); + } + } + } + + Point<3> point_a(0.5 + offset_query, 0.5 + offset_query, 0.5 + offset_query); + Point<3> point_b(1.5 + offset_query, 1.5 + offset_query, 1.5 + offset_query); + Point<3> point_c(2.2 + offset_query, 2.2 + offset_query, 2.2 + offset_query); + Point<3> point_d(2.6 + offset_query, 2.6 + offset_query, 2.6 + offset_query); + + std::vector> query_bounding_boxes; + query_bounding_boxes.emplace_back(std::make_pair(point_a, point_b)); + query_bounding_boxes.emplace_back(std::make_pair(point_c, point_d)); + + ArborXWrappers::DistributedTree distributed_tree(MPI_COMM_WORLD, + bounding_boxes); + ArborXWrappers::BoundingBoxIntersectPredicate bb_intersect( + query_bounding_boxes); + auto indices_ranks_offset = distributed_tree.query(bb_intersect); + auto indices_ranks = indices_ranks_offset.first; + auto offsets = indices_ranks_offset.second; + + std::vector indices_ref = {0, 1, 4, 5, 16, 17, 20, 21, 42}; + std::vector offsets_ref = {0, 8, 9}; + + AssertThrow(indices_ranks.size() == indices_ref.size(), ExcInternalError()); + AssertThrow(offsets.size() == offsets_ref.size(), ExcInternalError()); + for (unsigned int i = 0; i < offsets.size() - 1; ++i) + { + for (int j = offsets[i]; j < offsets[i + 1]; ++j) + { + // The indices associated to each query are not ordered. + bool found = false; + for (int k = offsets[i]; k < offsets[i + 1]; ++k) + { + if ((indices_ranks[j].first == indices_ref[k]) && + (indices_ranks[j].second == (rank + 1) % n_procs)) + { + found = true; + break; + } + } + AssertThrow(found, ExcInternalError()); + } + } + for (unsigned int i = 0; i < offsets.size(); ++i) + AssertThrow(offsets[i] == offsets_ref[i], ExcInternalError()); + deallog << "OK" << std::endl; +} + +int +main(int argc, char **argv) +{ + // Initialize Kokkos + Kokkos::initialize(argc, argv); + Utilities::MPI::MPI_InitFinalize mpi_init(argc, argv); + + initlog(); + + // tests + test_2d(); + test_3d(); + + Kokkos::finalize(); +} diff --git a/tests/arborx/distributed_tree_intersect.mpirun=2.output b/tests/arborx/distributed_tree_intersect.mpirun=2.output new file mode 100644 index 0000000000..9282f706bc --- /dev/null +++ b/tests/arborx/distributed_tree_intersect.mpirun=2.output @@ -0,0 +1,3 @@ + +DEAL::OK +DEAL::OK diff --git a/tests/arborx/distributed_tree_nearest.cc b/tests/arborx/distributed_tree_nearest.cc new file mode 100644 index 0000000000..fff2ff032b --- /dev/null +++ b/tests/arborx/distributed_tree_nearest.cc @@ -0,0 +1,330 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2022 by the deal.II authors +// +// This file is part of the deal.II library. +// +// The deal.II library is free software; you can use it, redistribute +// it, and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// The full text of the license can be found in the file LICENSE.md at +// the top level directory of deal.II. +// +// --------------------------------------------------------------------- + + +// Check ArborX wrapper: nearest bounding boxes + + +#include +#include + +#include + +#include "../tests.h" + + +void +test_bounding_box_2d() +{ + std::vector> bounding_boxes; + std::vector> points; + + unsigned int n_points_1d = 5; + const int rank = Utilities::MPI::this_mpi_process(MPI_COMM_WORLD); + const int n_procs = Utilities::MPI::n_mpi_processes(MPI_COMM_WORLD); + const int offset_bb = 2 * rank * n_points_1d; + const int offset_query = 2 * ((rank + 1) % n_procs) * n_points_1d; + for (unsigned int i = 0; i < n_points_1d; ++i) + { + for (unsigned int j = 0; j < n_points_1d; ++j) + { + points.emplace_back(j + offset_bb, i + offset_bb); + } + } + + for (unsigned int i = 0; i < n_points_1d - 1; ++i) + { + for (unsigned int j = 0; j < n_points_1d - 1; ++j) + { + unsigned int point_index = j + i * n_points_1d; + bounding_boxes.push_back( + std::make_pair(points[point_index], + points[point_index + n_points_1d + 1])); + } + } + + Point<2> point_a(-1.0 + offset_query, -1.0 + offset_query); + Point<2> point_b(-0.5 + offset_query, -0.5 + offset_query); + Point<2> point_c(5.2 + offset_query, 5.2 + offset_query); + Point<2> point_d(5.6 + offset_query, 5.6 + offset_query); + + std::vector> query_bounding_boxes; + query_bounding_boxes.emplace_back(std::make_pair(point_a, point_b)); + query_bounding_boxes.emplace_back(std::make_pair(point_c, point_d)); + + ArborXWrappers::DistributedTree distributed_tree(MPI_COMM_WORLD, + bounding_boxes); + ArborXWrappers::BoundingBoxNearestPredicate bb_nearest(query_bounding_boxes, + 1); + auto indices_ranks_offsets = distributed_tree.query(bb_nearest); + auto indices = indices_ranks_offsets.first; + auto offsets = indices_ranks_offsets.second; + + std::vector indices_ref = {0, 15}; + std::vector offsets_ref = {0, 1, 2}; + + AssertThrow(indices.size() == indices_ref.size(), ExcInternalError()); + AssertThrow(offsets.size() == offsets_ref.size(), ExcInternalError()); + for (unsigned int i = 0; i < offsets.size() - 1; ++i) + { + for (int j = offsets[i]; j < offsets[i + 1]; ++j) + { + // The indices associated to each query are not ordered. + bool found = false; + for (int k = offsets[i]; k < offsets[i + 1]; ++k) + { + if ((indices_ranks[j].first == indices_ref[k]) && + (indices_ranks[j].second == (rank + 1) % n_procs)) + { + found = true; + break; + } + } + AssertThrow(found, ExcInternalError()); + } + } + for (unsigned int i = 0; i < offsets.size(); ++i) + AssertThrow(offsets[i] == offsets_ref[i], ExcInternalError()); + + deallog << "OK" << std::endl; +} + +void +test_point_2d() +{ + std::vector> points; + + unsigned int n_points_1d = 5; + const int rank = Utilities::MPI::this_mpi_process(MPI_COMM_WORLD); + const int n_procs = Utilities::MPI::n_mpi_processes(MPI_COMM_WORLD); + const int offset_pt = 2 * rank * n_points_1d; + const int offset_query = 2 * ((rank + 1) % n_procs) * n_points_1d; + for (unsigned int i = 0; i < n_points_1d; ++i) + { + for (unsigned int j = 0; j < n_points_1d; ++j) + { + points.emplace_back(j + offset_pt, i + offset_pt); + } + } + + Point<3> point_a(0.5 + offset_query, 0.5 + offset_query, 0.5 + offset_query); + Point<3> point_b(1.5 + offset_query, 1.5 + offset_query, 1.5 + offset_query); + Point<3> point_c(2.2 + offset_query, 2.2 + offset_query, 2.2 + offset_query); + Point<3> point_d(2.6 + offset_query, 2.6 + offset_query, 2.6 + offset_query); + + std::vector> query_bounding_boxes; + query_bounding_boxes.emplace_back(std::make_pair(point_a, point_b)); + query_bounding_boxes.emplace_back(std::make_pair(point_c, point_d)); + + ArborXWrappers::DistributedTree distributed_tree(MPI_COMM_WORLD, points); + ArborXWrappers::BoundingBoxNearestPredicate bb_nearest(query_bounding_boxes, + 1); + auto indices_ranks_offset = distributed_tree.query(bb_nearest); + auto indices = indices_ranks_offset.first; + auto offsets = indices_ranks_offset.second; + + std::vector indices_ref = {6, 12}; + std::vector offsets_ref = {0, 1, 2}; + + AssertThrow(indices_ranks.size() == indices_ref.size(), ExcInternalError()); + AssertThrow(offsets.size() == offsets_ref.size(), ExcInternalError()); + for (unsigned int i = 0; i < offsets.size() - 1; ++i) + { + for (int j = offsets[i]; j < offsets[i + 1]; ++j) + { + // The indices associated to each query are not ordered. + bool found = false; + for (int k = offsets[i]; k < offsets[i + 1]; ++k) + { + if ((indices_ranks[j].first == indices_ref[k]) && + (indices_ranks[j].second == (rank + 1) % n_procs)) + { + found = true; + break; + } + } + AssertThrow(found, ExcInternalError()); + } + } + for (unsigned int i = 0; i < offsets.size(); ++i) + AssertThrow(offsets[i] == offsets_ref[i], ExcInternalError()); + + deallog << "OK" << std::endl; +} + +void +test_bounding_box_3d() +{ + std::vector> bounding_boxes; + std::vector> points; + + unsigned int n_points_1d = 5; + const int rank = Utilities::MPI::this_mpi_process(MPI_COMM_WORLD); + const int n_procs = Utilities::MPI::n_mpi_processes(MPI_COMM_WORLD); + const int offset_bb = 2 * rank * n_points_1d; + const int offset_query = 2 * ((rank + 1) % n_procs) * n_points_1d; + for (unsigned int i = 0; i < n_points_1d; ++i) + { + for (unsigned int j = 0; j < n_points_1d; ++j) + { + for (unsigned int k = 0; k < n_points_1d; ++k) + { + points.emplace_back(k + offset_bb, j + offset_bb, i + offset_bb); + } + } + } + + for (unsigned int i = 0; i < n_points_1d - 1; ++i) + { + for (unsigned int j = 0; j < n_points_1d - 1; ++j) + { + for (unsigned int k = 0; k < n_points_1d - 1; ++k) + { + unsigned int point_index = + k + j * n_points_1d + i * n_points_1d * n_points_1d; + bounding_boxes.push_back( + std::make_pair(points[point_index], + points[point_index + n_points_1d * n_points_1d + + n_points_1d + 1])); + } + } + } + + Point<3> point_a(-1.0 + offst_query, -1.0 + offst_query, -1.0 + offst_query); + Point<3> point_b(-0.5 + offst_query, -0.5 + offst_query, -0.5 + offst_query); + Point<3> point_c(10.2 + offst_query, 10.2 + offst_query, 10.2 + offst_query); + Point<3> point_d(10.6 + offst_query, 10.6 + offst_query, 10.6 + offst_query); + + std::vector> query_bounding_boxes; + query_bounding_boxes.emplace_back(std::make_pair(point_a, point_b)); + query_bounding_boxes.emplace_back(std::make_pair(point_c, point_d)); + + ArborXWrappers::DistributedTree distributed_tree(MPI_COMM_WORLD, + bounding_boxes); + ArborXWrappers::BoundingBoxNearestPredicate bb_nearest(query_bounding_boxes, + 1); + auto indices_ranks_offsets = distributed_tree.query(bb_nearest); + auto indices_ranks = indices_ranks_offsets.first; + auto offsets = indices_ranks_offsets.second; + + std::vector indices_ref = {0, 63}; + std::vector offsets_ref = {0, 1, 2}; + + AssertThrow(indices_ranks.size() == indices_ref.size(), ExcInternalError()); + AssertThrow(offsets.size() == offsets_ref.size(), ExcInternalError()); + for (unsigned int i = 0; i < offsets.size() - 1; ++i) + { + for (int j = offsets[i]; j < offsets[i + 1]; ++j) + { + // The indices associated to each query are not ordered. + bool found = false; + for (int k = offsets[i]; k < offsets[i + 1]; ++k) + { + if ((indices_ranks[j].first == indices_ref[k]) && + (indices_ranks[j].second == (rank + 1) % n_procs)) + { + found = true; + break; + } + } + AssertThrow(found, ExcInternalError()); + } + } + for (unsigned int i = 0; i < offsets.size(); ++i) + AssertThrow(offsets[i] == offsets_ref[i], ExcInternalError()); + deallog << "OK" << std::endl; +} + +void +test_point_3d() +{ + std::vector> points; + + unsigned int n_points_1d = 5; + const int rank = Utilities::MPI::this_mpi_process(MPI_COMM_WORLD); + const int n_procs = Utilities::MPI::n_mpi_processes(MPI_COMM_WORLD); + const int offset_pt = 2 * rank * n_points_1d; + const int offset_query = 2 * ((rank + 1) % n_procs) * n_points_1d; + for (unsigned int i = 0; i < n_points_1d; ++i) + { + for (unsigned int j = 0; j < n_points_1d; ++j) + { + for (unsigned int k = 0; k < n_points_1d; ++k) + { + points.emplace_back(k + offset_pt, j + offset_pt, i + offset_pt); + } + } + } + + Point<3> point_a(0.5 + offset_query, 0.5 + offset_query, 0.5 + offset_query); + Point<3> point_b(1.5 + offset_query, 1.5 + offset_query, 1.5 + offset_query); + Point<3> point_c(2.2 + offset_query, 2.2 + offset_query, 2.2 + offset_query); + Point<3> point_d(2.6 + offset_query, 2.6 + offset_query, 2.6 + offset_query); + + std::vector> query_bounding_boxes; + query_bounding_boxes.emplace_back(std::make_pair(point_a, point_b)); + query_bounding_boxes.emplace_back(std::make_pair(point_c, point_d)); + + ArborXWrappers::DistributedTree distributed_tree(MPI_COMM_WORLD, points); + ArborXWrappers::BoundingBoxNearestPredicate bb_nearest(query_bounding_boxes, + 1); + auto indices_ranks_offsets = distributed_tree.query(bb_nearest); + auto indices_ranks = indices_offset.first; + auto offsets = indices_offset.second; + + std::vector indices_ref = {31, 62}; + std::vector offsets_ref = {0, 1, 2}; + + AssertThrow(indices.size() == indices_ref.size(), ExcInternalError()); + AssertThrow(offsets.size() == offsets_ref.size(), ExcInternalError()); + for (unsigned int i = 0; i < offsets.size() - 1; ++i) + { + for (int j = offsets[i]; j < offsets[i + 1]; ++j) + { + // The indices associated to each query are not ordered. + bool found = false; + for (int k = offsets[i]; k < offsets[i + 1]; ++k) + { + if ((indices_ranks[j].first == indices_ref[k]) && + (indices_ranks[j].second == (rank + 1) % n_procs)) + { + found = true; + break; + } + } + AssertThrow(found, ExcInternalError()); + } + } + for (unsigned int i = 0; i < offsets.size(); ++i) + AssertThrow(offsets[i] == offsets_ref[i], ExcInternalError()); + deallog << "OK" << std::endl; +} + +int +main(int argc, char **argv) +{ + // Initialize Kokkos + Kokkos::initialize(argc, argv); + + initlog(); + + // tests + test_bounding_box_2d(); + test_bounding_box_3d(); + test_point_2d(); + test_point_3d(); + + Kokkos::finalize(); +} diff --git a/tests/arborx/distributed_tree_nearest.mpirun=2.output b/tests/arborx/distributed_tree_nearest.mpirun=2.output new file mode 100644 index 0000000000..9282f706bc --- /dev/null +++ b/tests/arborx/distributed_tree_nearest.mpirun=2.output @@ -0,0 +1,3 @@ + +DEAL::OK +DEAL::OK -- 2.39.5