From: Peter Munch Date: Wed, 12 May 2021 16:54:06 +0000 (+0200) Subject: Allow to enforce unique mapping in RemotePointEvaluation X-Git-Tag: v9.3.0-rc1~39^2 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d52e1d9733dec4b997e87734702bc3c840c01c42;p=dealii.git Allow to enforce unique mapping in RemotePointEvaluation --- diff --git a/include/deal.II/base/mpi_remote_point_evaluation.h b/include/deal.II/base/mpi_remote_point_evaluation.h index bf1624a6a7..ebd3f3a5b8 100644 --- a/include/deal.II/base/mpi_remote_point_evaluation.h +++ b/include/deal.II/base/mpi_remote_point_evaluation.h @@ -53,8 +53,11 @@ namespace Utilities * the tolerance in order to be able to identify a cell. * Floating point arithmetic implies that a point will, in general, not * lie exactly on a vertex, edge, or face. + * @param enforce_unique_mapping Enforce unique mapping, i.e., + * (one-to-one) relation of points and cells. */ - RemotePointEvaluation(const double tolerance = 1e-6); + RemotePointEvaluation(const double tolerance = 1e-6, + const bool enforce_unique_mapping = false); /** * Destructor. @@ -168,6 +171,12 @@ namespace Utilities */ const double tolerance; + /** + * Enforce unique mapping, i.e., (one-to-one) relation of points and + * cells. + */ + const bool enforce_unique_mapping; + /** * Storage for the status of the triangulation signal. */ diff --git a/include/deal.II/base/mpi_tags.h b/include/deal.II/base/mpi_tags.h index ae7eff13e7..a59594d59c 100644 --- a/include/deal.II/base/mpi_tags.h +++ b/include/deal.II/base/mpi_tags.h @@ -146,6 +146,9 @@ namespace Utilities // global coarsening transfer fine_dof_handler_view_reinit, + // GridTools::internal::distributed_compute_point_locations + distributed_compute_point_locations, + }; } // namespace Tags } // namespace internal diff --git a/include/deal.II/grid/grid_tools.h b/include/deal.II/grid/grid_tools.h index 3ce447ad36..9b578de60d 100644 --- a/include/deal.II/grid/grid_tools.h +++ b/include/deal.II/grid/grid_tools.h @@ -1149,7 +1149,8 @@ namespace GridTools const std::vector> & points, const std::vector>> &global_bboxes, const double tolerance, - const bool perform_handshake); + const bool perform_handshake, + const bool enforce_unique_mapping = false); } // namespace internal diff --git a/source/base/mpi_remote_point_evaluation.cc b/source/base/mpi_remote_point_evaluation.cc index 8f7a01f4fa..f7ceca3aef 100644 --- a/source/base/mpi_remote_point_evaluation.cc +++ b/source/base/mpi_remote_point_evaluation.cc @@ -37,8 +37,10 @@ namespace Utilities { template RemotePointEvaluation::RemotePointEvaluation( - const double tolerance) + const double tolerance, + const bool enforce_unique_mapping) : tolerance(tolerance) + , enforce_unique_mapping(enforce_unique_mapping) , ready_flag(false) {} @@ -94,7 +96,12 @@ namespace Utilities const auto data = GridTools::internal::distributed_compute_point_locations( - cache, points, global_bboxes, tolerance, true); + cache, + points, + global_bboxes, + tolerance, + true, + enforce_unique_mapping); this->recv_ranks = data.recv_ranks; this->recv_ptrs = data.recv_ptrs; diff --git a/source/grid/grid_tools.cc b/source/grid/grid_tools.cc index 94abc37f78..a30232ab13 100644 --- a/source/grid/grid_tools.cc +++ b/source/grid/grid_tools.cc @@ -5761,6 +5761,11 @@ namespace GridTools if (cell.first->is_locally_owned()) locally_owned_active_cells_around_point.push_back(cell); } + + std::sort(locally_owned_active_cells_around_point.begin(), + locally_owned_active_cells_around_point.end(), + [](const auto &a, const auto &b) { return a.first < b.first; }); + return locally_owned_active_cells_around_point; } @@ -5773,8 +5778,11 @@ namespace GridTools const std::vector> & points, const std::vector>> &global_bboxes, const double tolerance, - const bool perform_handshake) + const bool perform_handshake, + const bool enforce_unique_mapping) { + Assert(!enforce_unique_mapping || perform_handshake, ExcInternalError()); + DistributedComputePointLocationsInternal result; auto &send_components = result.send_components; @@ -5860,10 +5868,18 @@ namespace GridTools cell_and_reference_position.second, index_and_point.second, numbers::invalid_unsigned_int); + + if (enforce_unique_mapping) + break; // in the case of unique mapping, we only need a + // single cell (we take the first) } if (perform_handshake) - request_buffer_temp[i] = cells_and_reference_positions.size(); + request_buffer_temp[i] = + enforce_unique_mapping ? + std::min( + 1, cells_and_reference_positions.size()) : + cells_and_reference_positions.size(); } if (perform_handshake) @@ -5905,6 +5921,143 @@ namespace GridTools process, cache.get_triangulation().get_communicator()) .run(); + // for unique mapping, we need to modify recv_components and + // send_components consistently + if (enforce_unique_mapping) + { + std::vector mask_recv(recv_components.size()); + std::vector mask_send(send_components.size()); + + // set up new recv_components and monitor which entries (we keep + // the entry of the lowest rank) have been eliminated so that we can + // communicate it + auto recv_components_copy = recv_components; + recv_components.clear(); + + for (unsigned int i = 0; i < recv_components_copy.size(); ++i) + std::get<2>(recv_components_copy[i]) = i; + + std::sort(recv_components_copy.begin(), + recv_components_copy.end(), + [&](const auto &a, const auto &b) { + if (std::get<0>(a) != std::get<0>(b)) // rank + return std::get<0>(a) < std::get<0>(b); + + return std::get<2>(a) < std::get<2>(b); // enumeration + }); + + std::vector unique(points.size(), false); + + std::vector recv_ranks; + std::vector recv_ptrs; + + for (unsigned int i = 0, dummy = numbers::invalid_unsigned_int; + i < recv_components_copy.size(); + ++i) + { + if (dummy != std::get<0>(recv_components_copy[i])) + { + dummy = std::get<0>(recv_components_copy[i]); + recv_ranks.push_back(dummy); + recv_ptrs.push_back(i); + } + + if (unique[std::get<1>(recv_components_copy[i])] == false) + { + recv_components.emplace_back(recv_components_copy[i]); + mask_recv[i] = 1; + unique[std::get<1>(recv_components_copy[i])] = true; + } + else + { + mask_recv[i] = 0; + } + } + recv_ptrs.push_back(recv_components_copy.size()); + + Assert(std::all_of(unique.begin(), + unique.end(), + [](const auto &v) { return v; }), + ExcInternalError()); + + + // prepare send_components so that not needed entries can be + // eliminated later on + auto send_components_copy = send_components; + send_components.clear(); + + for (unsigned int i = 0; i < send_components_copy.size(); ++i) + std::get<5>(send_components_copy[i]) = i; + + std::sort(send_components_copy.begin(), + send_components_copy.end(), + [&](const auto &a, const auto &b) { + if (std::get<1>(a) != std::get<1>(b)) // rank + return std::get<1>(a) < std::get<1>(b); + + return std::get<5>(a) < std::get<5>(b); // enumeration + }); + + std::vector send_ranks; + std::vector send_ptrs; + + for (unsigned int i = 0, dummy = numbers::invalid_unsigned_int; + i < send_components_copy.size(); + ++i) + { + if (dummy != std::get<1>(send_components_copy[i])) + { + dummy = std::get<1>(send_components_copy[i]); + send_ranks.push_back(dummy); + send_ptrs.push_back(i); + } + } + send_ptrs.push_back(send_components_copy.size()); + + // perform communication +#ifdef DEAL_II_WITH_MPI + std::vector req(send_ranks.size() + recv_ranks.size()); + + for (unsigned int i = 0; i < send_ranks.size(); ++i) + { + const auto ierr = + MPI_Irecv(mask_send.data() + send_ptrs[i], + send_ptrs[i + 1] - send_ptrs[i], + MPI_UNSIGNED, + send_ranks[i], + Utilities::MPI::internal::Tags:: + distributed_compute_point_locations, + cache.get_triangulation().get_communicator(), + &req[i]); + AssertThrowMPI(ierr); + } + + for (unsigned int i = 0; i < recv_ranks.size(); ++i) + { + const auto ierr = + MPI_Isend(mask_recv.data() + recv_ptrs[i], + recv_ptrs[i + 1] - recv_ptrs[i], + MPI_UNSIGNED, + recv_ranks[i], + Utilities::MPI::internal::Tags:: + distributed_compute_point_locations, + cache.get_triangulation().get_communicator(), + &req[i] + send_ranks.size()); + AssertThrowMPI(ierr); + } + + auto ierr = MPI_Waitall(req.size(), req.data(), MPI_STATUSES_IGNORE); + AssertThrowMPI(ierr); +#else + mask_send = mask_recv; +#endif + + // eliminate not needed entries + for (unsigned int i = 0; i < send_components_copy.size(); ++i) + if (mask_send[i] == 1) + send_components.emplace_back(send_components_copy[i]); + } + if (true) { // sort according to rank (and point index and cell) -> make diff --git a/source/grid/grid_tools.inst.in b/source/grid/grid_tools.inst.in index 467be82266..e8fefe6909 100644 --- a/source/grid/grid_tools.inst.in +++ b/source/grid/grid_tools.inst.in @@ -143,6 +143,7 @@ for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS) const std::vector> &, const std::vector>> &, const double, + const bool, const bool); \} diff --git a/tests/remote_point_evaluation/mapping_01.cc b/tests/remote_point_evaluation/mapping_01.cc new file mode 100644 index 0000000000..31e5562b77 --- /dev/null +++ b/tests/remote_point_evaluation/mapping_01.cc @@ -0,0 +1,95 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2021 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. +// +// --------------------------------------------------------------------- + +// Test Utilities::MPI::RemotePointEvaluation with and without unique mapping. + +#include + +#include + +#include +#include + +#include + +#include + +#include + +#include "../tests.h" + +using namespace dealii; + + +template +void +test(const bool enforce_unique_map) +{ + parallel::distributed::Triangulation tria(MPI_COMM_WORLD); + GridGenerator::subdivided_hyper_cube(tria, 2); + tria.refine_global(1); + + FE_DGQ fe(0); + DoFHandler dof_handler(tria); + dof_handler.distribute_dofs(fe); + + Vector vec(dof_handler.n_dofs()); + + for (const auto &cell : dof_handler.active_cell_iterators()) + if (cell->is_locally_owned()) + vec[cell->global_active_cell_index()] = cell->global_active_cell_index(); + + MappingQ1 mapping; + + std::vector> evaluation_points; + + for (unsigned int j = 0; j <= 4; ++j) + for (unsigned int i = 0; i <= 4; ++i) + evaluation_points.emplace_back(i * 0.25, j * 0.25); + + Utilities::MPI::RemotePointEvaluation eval(1e-6, enforce_unique_map); + + const auto result_avg = + VectorTools::evaluate_at_points<1>(mapping, + dof_handler, + vec, + evaluation_points, + eval, + VectorTools::EvaluationFlags::avg); + const auto result_min = VectorTools::evaluate_at_points<1>( + eval, dof_handler, vec, VectorTools::EvaluationFlags::min); + const auto result_max = VectorTools::evaluate_at_points<1>( + eval, dof_handler, vec, VectorTools::EvaluationFlags::max); + const auto result_insert = VectorTools::evaluate_at_points<1>( + eval, dof_handler, vec, VectorTools::EvaluationFlags::insert); + + for (unsigned int i = 0; i < evaluation_points.size(); ++i) + deallog << i << " " << result_avg[i] << " " << result_min[i] << " " + << result_max[i] << " " << result_insert[i] << " " + << eval.get_point_ptrs()[i + 1] - eval.get_point_ptrs()[i] + << std::endl; +} + + + +int +main(int argc, char **argv) +{ + Utilities::MPI::MPI_InitFinalize mpi(argc, argv, 1); + MPILogInitAll all; + + test<2>(false); + test<2>(true); +} diff --git a/tests/remote_point_evaluation/mapping_01.mpirun=1.output b/tests/remote_point_evaluation/mapping_01.mpirun=1.output new file mode 100644 index 0000000000..3bc28613a2 --- /dev/null +++ b/tests/remote_point_evaluation/mapping_01.mpirun=1.output @@ -0,0 +1,51 @@ + +DEAL:0::0 0.00000 0.00000 0.00000 0.00000 1 +DEAL:0::1 0.500000 0.00000 1.00000 0.00000 2 +DEAL:0::2 2.50000 1.00000 4.00000 1.00000 2 +DEAL:0::3 4.50000 4.00000 5.00000 4.00000 2 +DEAL:0::4 5.00000 5.00000 5.00000 5.00000 1 +DEAL:0::5 1.00000 0.00000 2.00000 0.00000 2 +DEAL:0::6 1.50000 0.00000 3.00000 0.00000 4 +DEAL:0::7 3.50000 1.00000 6.00000 1.00000 4 +DEAL:0::8 5.50000 4.00000 7.00000 4.00000 4 +DEAL:0::9 6.00000 5.00000 7.00000 5.00000 2 +DEAL:0::10 5.00000 2.00000 8.00000 2.00000 2 +DEAL:0::11 5.50000 2.00000 9.00000 2.00000 4 +DEAL:0::12 7.50000 3.00000 12.0000 3.00000 4 +DEAL:0::13 9.50000 6.00000 13.0000 6.00000 4 +DEAL:0::14 10.0000 7.00000 13.0000 7.00000 2 +DEAL:0::15 9.00000 8.00000 10.0000 8.00000 2 +DEAL:0::16 9.50000 8.00000 11.0000 8.00000 4 +DEAL:0::17 11.5000 9.00000 14.0000 9.00000 4 +DEAL:0::18 13.5000 12.0000 15.0000 12.0000 4 +DEAL:0::19 14.0000 13.0000 15.0000 13.0000 2 +DEAL:0::20 10.0000 10.0000 10.0000 10.0000 1 +DEAL:0::21 10.5000 10.0000 11.0000 10.0000 2 +DEAL:0::22 12.5000 11.0000 14.0000 11.0000 2 +DEAL:0::23 14.5000 14.0000 15.0000 14.0000 2 +DEAL:0::24 15.0000 15.0000 15.0000 15.0000 1 +DEAL:0::0 0.00000 0.00000 0.00000 0.00000 1 +DEAL:0::1 0.00000 0.00000 0.00000 0.00000 1 +DEAL:0::2 1.00000 1.00000 1.00000 1.00000 1 +DEAL:0::3 4.00000 4.00000 4.00000 4.00000 1 +DEAL:0::4 5.00000 5.00000 5.00000 5.00000 1 +DEAL:0::5 0.00000 0.00000 0.00000 0.00000 1 +DEAL:0::6 0.00000 0.00000 0.00000 0.00000 1 +DEAL:0::7 1.00000 1.00000 1.00000 1.00000 1 +DEAL:0::8 4.00000 4.00000 4.00000 4.00000 1 +DEAL:0::9 5.00000 5.00000 5.00000 5.00000 1 +DEAL:0::10 2.00000 2.00000 2.00000 2.00000 1 +DEAL:0::11 2.00000 2.00000 2.00000 2.00000 1 +DEAL:0::12 3.00000 3.00000 3.00000 3.00000 1 +DEAL:0::13 6.00000 6.00000 6.00000 6.00000 1 +DEAL:0::14 7.00000 7.00000 7.00000 7.00000 1 +DEAL:0::15 8.00000 8.00000 8.00000 8.00000 1 +DEAL:0::16 8.00000 8.00000 8.00000 8.00000 1 +DEAL:0::17 9.00000 9.00000 9.00000 9.00000 1 +DEAL:0::18 12.0000 12.0000 12.0000 12.0000 1 +DEAL:0::19 13.0000 13.0000 13.0000 13.0000 1 +DEAL:0::20 10.0000 10.0000 10.0000 10.0000 1 +DEAL:0::21 10.0000 10.0000 10.0000 10.0000 1 +DEAL:0::22 11.0000 11.0000 11.0000 11.0000 1 +DEAL:0::23 14.0000 14.0000 14.0000 14.0000 1 +DEAL:0::24 15.0000 15.0000 15.0000 15.0000 1 diff --git a/tests/remote_point_evaluation/mapping_01.mpirun=4.output b/tests/remote_point_evaluation/mapping_01.mpirun=4.output new file mode 100644 index 0000000000..d5a34b5563 --- /dev/null +++ b/tests/remote_point_evaluation/mapping_01.mpirun=4.output @@ -0,0 +1,207 @@ + +DEAL:0::0 0.00000 0.00000 0.00000 0.00000 1 +DEAL:0::1 0.500000 0.00000 1.00000 0.00000 2 +DEAL:0::2 2.50000 1.00000 4.00000 1.00000 2 +DEAL:0::3 4.50000 4.00000 5.00000 4.00000 2 +DEAL:0::4 5.00000 5.00000 5.00000 5.00000 1 +DEAL:0::5 1.00000 0.00000 2.00000 0.00000 2 +DEAL:0::6 1.50000 0.00000 3.00000 0.00000 4 +DEAL:0::7 3.50000 1.00000 6.00000 1.00000 4 +DEAL:0::8 5.50000 4.00000 7.00000 4.00000 4 +DEAL:0::9 6.00000 5.00000 7.00000 5.00000 2 +DEAL:0::10 5.00000 2.00000 8.00000 2.00000 2 +DEAL:0::11 5.50000 2.00000 9.00000 2.00000 4 +DEAL:0::12 7.50000 3.00000 12.0000 3.00000 4 +DEAL:0::13 9.50000 6.00000 13.0000 6.00000 4 +DEAL:0::14 10.0000 7.00000 13.0000 7.00000 2 +DEAL:0::15 9.00000 8.00000 10.0000 8.00000 2 +DEAL:0::16 9.50000 8.00000 11.0000 8.00000 4 +DEAL:0::17 11.5000 9.00000 14.0000 9.00000 4 +DEAL:0::18 13.5000 12.0000 15.0000 12.0000 4 +DEAL:0::19 14.0000 13.0000 15.0000 13.0000 2 +DEAL:0::20 10.0000 10.0000 10.0000 10.0000 1 +DEAL:0::21 10.5000 10.0000 11.0000 10.0000 2 +DEAL:0::22 12.5000 11.0000 14.0000 11.0000 2 +DEAL:0::23 14.5000 14.0000 15.0000 14.0000 2 +DEAL:0::24 15.0000 15.0000 15.0000 15.0000 1 +DEAL:0::0 0.00000 0.00000 0.00000 0.00000 1 +DEAL:0::1 0.00000 0.00000 0.00000 0.00000 1 +DEAL:0::2 1.00000 1.00000 1.00000 1.00000 1 +DEAL:0::3 4.00000 4.00000 4.00000 4.00000 1 +DEAL:0::4 5.00000 5.00000 5.00000 5.00000 1 +DEAL:0::5 0.00000 0.00000 0.00000 0.00000 1 +DEAL:0::6 0.00000 0.00000 0.00000 0.00000 1 +DEAL:0::7 1.00000 1.00000 1.00000 1.00000 1 +DEAL:0::8 4.00000 4.00000 4.00000 4.00000 1 +DEAL:0::9 5.00000 5.00000 5.00000 5.00000 1 +DEAL:0::10 2.00000 2.00000 2.00000 2.00000 1 +DEAL:0::11 2.00000 2.00000 2.00000 2.00000 1 +DEAL:0::12 3.00000 3.00000 3.00000 3.00000 1 +DEAL:0::13 6.00000 6.00000 6.00000 6.00000 1 +DEAL:0::14 7.00000 7.00000 7.00000 7.00000 1 +DEAL:0::15 8.00000 8.00000 8.00000 8.00000 1 +DEAL:0::16 8.00000 8.00000 8.00000 8.00000 1 +DEAL:0::17 9.00000 9.00000 9.00000 9.00000 1 +DEAL:0::18 12.0000 12.0000 12.0000 12.0000 1 +DEAL:0::19 13.0000 13.0000 13.0000 13.0000 1 +DEAL:0::20 10.0000 10.0000 10.0000 10.0000 1 +DEAL:0::21 10.0000 10.0000 10.0000 10.0000 1 +DEAL:0::22 11.0000 11.0000 11.0000 11.0000 1 +DEAL:0::23 14.0000 14.0000 14.0000 14.0000 1 +DEAL:0::24 15.0000 15.0000 15.0000 15.0000 1 + +DEAL:1::0 0.00000 0.00000 0.00000 0.00000 1 +DEAL:1::1 0.500000 0.00000 1.00000 0.00000 2 +DEAL:1::2 2.50000 1.00000 4.00000 1.00000 2 +DEAL:1::3 4.50000 4.00000 5.00000 4.00000 2 +DEAL:1::4 5.00000 5.00000 5.00000 5.00000 1 +DEAL:1::5 1.00000 0.00000 2.00000 0.00000 2 +DEAL:1::6 1.50000 0.00000 3.00000 0.00000 4 +DEAL:1::7 3.50000 1.00000 6.00000 1.00000 4 +DEAL:1::8 5.50000 4.00000 7.00000 4.00000 4 +DEAL:1::9 6.00000 5.00000 7.00000 5.00000 2 +DEAL:1::10 5.00000 2.00000 8.00000 2.00000 2 +DEAL:1::11 5.50000 2.00000 9.00000 2.00000 4 +DEAL:1::12 7.50000 3.00000 12.0000 3.00000 4 +DEAL:1::13 9.50000 6.00000 13.0000 6.00000 4 +DEAL:1::14 10.0000 7.00000 13.0000 7.00000 2 +DEAL:1::15 9.00000 8.00000 10.0000 8.00000 2 +DEAL:1::16 9.50000 8.00000 11.0000 8.00000 4 +DEAL:1::17 11.5000 9.00000 14.0000 9.00000 4 +DEAL:1::18 13.5000 12.0000 15.0000 12.0000 4 +DEAL:1::19 14.0000 13.0000 15.0000 13.0000 2 +DEAL:1::20 10.0000 10.0000 10.0000 10.0000 1 +DEAL:1::21 10.5000 10.0000 11.0000 10.0000 2 +DEAL:1::22 12.5000 11.0000 14.0000 11.0000 2 +DEAL:1::23 14.5000 14.0000 15.0000 14.0000 2 +DEAL:1::24 15.0000 15.0000 15.0000 15.0000 1 +DEAL:1::0 0.00000 0.00000 0.00000 0.00000 1 +DEAL:1::1 0.00000 0.00000 0.00000 0.00000 1 +DEAL:1::2 1.00000 1.00000 1.00000 1.00000 1 +DEAL:1::3 4.00000 4.00000 4.00000 4.00000 1 +DEAL:1::4 5.00000 5.00000 5.00000 5.00000 1 +DEAL:1::5 0.00000 0.00000 0.00000 0.00000 1 +DEAL:1::6 0.00000 0.00000 0.00000 0.00000 1 +DEAL:1::7 1.00000 1.00000 1.00000 1.00000 1 +DEAL:1::8 4.00000 4.00000 4.00000 4.00000 1 +DEAL:1::9 5.00000 5.00000 5.00000 5.00000 1 +DEAL:1::10 2.00000 2.00000 2.00000 2.00000 1 +DEAL:1::11 2.00000 2.00000 2.00000 2.00000 1 +DEAL:1::12 3.00000 3.00000 3.00000 3.00000 1 +DEAL:1::13 6.00000 6.00000 6.00000 6.00000 1 +DEAL:1::14 7.00000 7.00000 7.00000 7.00000 1 +DEAL:1::15 8.00000 8.00000 8.00000 8.00000 1 +DEAL:1::16 8.00000 8.00000 8.00000 8.00000 1 +DEAL:1::17 9.00000 9.00000 9.00000 9.00000 1 +DEAL:1::18 12.0000 12.0000 12.0000 12.0000 1 +DEAL:1::19 13.0000 13.0000 13.0000 13.0000 1 +DEAL:1::20 10.0000 10.0000 10.0000 10.0000 1 +DEAL:1::21 10.0000 10.0000 10.0000 10.0000 1 +DEAL:1::22 11.0000 11.0000 11.0000 11.0000 1 +DEAL:1::23 14.0000 14.0000 14.0000 14.0000 1 +DEAL:1::24 15.0000 15.0000 15.0000 15.0000 1 + + +DEAL:2::0 0.00000 0.00000 0.00000 0.00000 1 +DEAL:2::1 0.500000 0.00000 1.00000 0.00000 2 +DEAL:2::2 2.50000 1.00000 4.00000 1.00000 2 +DEAL:2::3 4.50000 4.00000 5.00000 4.00000 2 +DEAL:2::4 5.00000 5.00000 5.00000 5.00000 1 +DEAL:2::5 1.00000 0.00000 2.00000 0.00000 2 +DEAL:2::6 1.50000 0.00000 3.00000 0.00000 4 +DEAL:2::7 3.50000 1.00000 6.00000 1.00000 4 +DEAL:2::8 5.50000 4.00000 7.00000 4.00000 4 +DEAL:2::9 6.00000 5.00000 7.00000 5.00000 2 +DEAL:2::10 5.00000 2.00000 8.00000 2.00000 2 +DEAL:2::11 5.50000 2.00000 9.00000 2.00000 4 +DEAL:2::12 7.50000 3.00000 12.0000 3.00000 4 +DEAL:2::13 9.50000 6.00000 13.0000 6.00000 4 +DEAL:2::14 10.0000 7.00000 13.0000 7.00000 2 +DEAL:2::15 9.00000 8.00000 10.0000 8.00000 2 +DEAL:2::16 9.50000 8.00000 11.0000 8.00000 4 +DEAL:2::17 11.5000 9.00000 14.0000 9.00000 4 +DEAL:2::18 13.5000 12.0000 15.0000 12.0000 4 +DEAL:2::19 14.0000 13.0000 15.0000 13.0000 2 +DEAL:2::20 10.0000 10.0000 10.0000 10.0000 1 +DEAL:2::21 10.5000 10.0000 11.0000 10.0000 2 +DEAL:2::22 12.5000 11.0000 14.0000 11.0000 2 +DEAL:2::23 14.5000 14.0000 15.0000 14.0000 2 +DEAL:2::24 15.0000 15.0000 15.0000 15.0000 1 +DEAL:2::0 0.00000 0.00000 0.00000 0.00000 1 +DEAL:2::1 0.00000 0.00000 0.00000 0.00000 1 +DEAL:2::2 1.00000 1.00000 1.00000 1.00000 1 +DEAL:2::3 4.00000 4.00000 4.00000 4.00000 1 +DEAL:2::4 5.00000 5.00000 5.00000 5.00000 1 +DEAL:2::5 0.00000 0.00000 0.00000 0.00000 1 +DEAL:2::6 0.00000 0.00000 0.00000 0.00000 1 +DEAL:2::7 1.00000 1.00000 1.00000 1.00000 1 +DEAL:2::8 4.00000 4.00000 4.00000 4.00000 1 +DEAL:2::9 5.00000 5.00000 5.00000 5.00000 1 +DEAL:2::10 2.00000 2.00000 2.00000 2.00000 1 +DEAL:2::11 2.00000 2.00000 2.00000 2.00000 1 +DEAL:2::12 3.00000 3.00000 3.00000 3.00000 1 +DEAL:2::13 6.00000 6.00000 6.00000 6.00000 1 +DEAL:2::14 7.00000 7.00000 7.00000 7.00000 1 +DEAL:2::15 8.00000 8.00000 8.00000 8.00000 1 +DEAL:2::16 8.00000 8.00000 8.00000 8.00000 1 +DEAL:2::17 9.00000 9.00000 9.00000 9.00000 1 +DEAL:2::18 12.0000 12.0000 12.0000 12.0000 1 +DEAL:2::19 13.0000 13.0000 13.0000 13.0000 1 +DEAL:2::20 10.0000 10.0000 10.0000 10.0000 1 +DEAL:2::21 10.0000 10.0000 10.0000 10.0000 1 +DEAL:2::22 11.0000 11.0000 11.0000 11.0000 1 +DEAL:2::23 14.0000 14.0000 14.0000 14.0000 1 +DEAL:2::24 15.0000 15.0000 15.0000 15.0000 1 + + +DEAL:3::0 0.00000 0.00000 0.00000 0.00000 1 +DEAL:3::1 0.500000 0.00000 1.00000 0.00000 2 +DEAL:3::2 2.50000 1.00000 4.00000 1.00000 2 +DEAL:3::3 4.50000 4.00000 5.00000 4.00000 2 +DEAL:3::4 5.00000 5.00000 5.00000 5.00000 1 +DEAL:3::5 1.00000 0.00000 2.00000 0.00000 2 +DEAL:3::6 1.50000 0.00000 3.00000 0.00000 4 +DEAL:3::7 3.50000 1.00000 6.00000 1.00000 4 +DEAL:3::8 5.50000 4.00000 7.00000 4.00000 4 +DEAL:3::9 6.00000 5.00000 7.00000 5.00000 2 +DEAL:3::10 5.00000 2.00000 8.00000 2.00000 2 +DEAL:3::11 5.50000 2.00000 9.00000 2.00000 4 +DEAL:3::12 7.50000 3.00000 12.0000 3.00000 4 +DEAL:3::13 9.50000 6.00000 13.0000 6.00000 4 +DEAL:3::14 10.0000 7.00000 13.0000 7.00000 2 +DEAL:3::15 9.00000 8.00000 10.0000 8.00000 2 +DEAL:3::16 9.50000 8.00000 11.0000 8.00000 4 +DEAL:3::17 11.5000 9.00000 14.0000 9.00000 4 +DEAL:3::18 13.5000 12.0000 15.0000 12.0000 4 +DEAL:3::19 14.0000 13.0000 15.0000 13.0000 2 +DEAL:3::20 10.0000 10.0000 10.0000 10.0000 1 +DEAL:3::21 10.5000 10.0000 11.0000 10.0000 2 +DEAL:3::22 12.5000 11.0000 14.0000 11.0000 2 +DEAL:3::23 14.5000 14.0000 15.0000 14.0000 2 +DEAL:3::24 15.0000 15.0000 15.0000 15.0000 1 +DEAL:3::0 0.00000 0.00000 0.00000 0.00000 1 +DEAL:3::1 0.00000 0.00000 0.00000 0.00000 1 +DEAL:3::2 1.00000 1.00000 1.00000 1.00000 1 +DEAL:3::3 4.00000 4.00000 4.00000 4.00000 1 +DEAL:3::4 5.00000 5.00000 5.00000 5.00000 1 +DEAL:3::5 0.00000 0.00000 0.00000 0.00000 1 +DEAL:3::6 0.00000 0.00000 0.00000 0.00000 1 +DEAL:3::7 1.00000 1.00000 1.00000 1.00000 1 +DEAL:3::8 4.00000 4.00000 4.00000 4.00000 1 +DEAL:3::9 5.00000 5.00000 5.00000 5.00000 1 +DEAL:3::10 2.00000 2.00000 2.00000 2.00000 1 +DEAL:3::11 2.00000 2.00000 2.00000 2.00000 1 +DEAL:3::12 3.00000 3.00000 3.00000 3.00000 1 +DEAL:3::13 6.00000 6.00000 6.00000 6.00000 1 +DEAL:3::14 7.00000 7.00000 7.00000 7.00000 1 +DEAL:3::15 8.00000 8.00000 8.00000 8.00000 1 +DEAL:3::16 8.00000 8.00000 8.00000 8.00000 1 +DEAL:3::17 9.00000 9.00000 9.00000 9.00000 1 +DEAL:3::18 12.0000 12.0000 12.0000 12.0000 1 +DEAL:3::19 13.0000 13.0000 13.0000 13.0000 1 +DEAL:3::20 10.0000 10.0000 10.0000 10.0000 1 +DEAL:3::21 10.0000 10.0000 10.0000 10.0000 1 +DEAL:3::22 11.0000 11.0000 11.0000 11.0000 1 +DEAL:3::23 14.0000 14.0000 14.0000 14.0000 1 +DEAL:3::24 15.0000 15.0000 15.0000 15.0000 1 +