]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Introduce partition policies 12348/head
authorPeter Munch <peterrmuench@gmail.com>
Sat, 29 May 2021 15:14:55 +0000 (17:14 +0200)
committerPeter Munch <peterrmuench@gmail.com>
Mon, 31 May 2021 22:15:16 +0000 (00:15 +0200)
include/deal.II/distributed/repartitioning_policy_tools.h [new file with mode: 0644]
source/distributed/CMakeLists.txt
source/distributed/repartitioning_policy_tools.cc [new file with mode: 0644]
source/distributed/repartitioning_policy_tools.inst.in [new file with mode: 0644]
tests/fullydistributed_grids/repartitioning_02.cc [new file with mode: 0644]
tests/fullydistributed_grids/repartitioning_02.mpirun=5.output [new file with mode: 0644]

diff --git a/include/deal.II/distributed/repartitioning_policy_tools.h b/include/deal.II/distributed/repartitioning_policy_tools.h
new file mode 100644 (file)
index 0000000..58cc832
--- /dev/null
@@ -0,0 +1,134 @@
+// ---------------------------------------------------------------------
+//
+// 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.
+//
+// ---------------------------------------------------------------------
+
+#ifndef dealii_distributed_repartitioning_policy_tools_h
+#define dealii_distributed_repartitioning_policy_tools_h
+
+#include <deal.II/grid/tria.h>
+
+#include <deal.II/lac/la_parallel_vector.h>
+
+DEAL_II_NAMESPACE_OPEN
+
+/**
+ * A namespace with repartitioning policies. These classes return vectors of
+ * of the new owners of the active locally owned and ghost cells of a
+ * Triangulation object. The returned vectors can be used, e.g., in
+ * TriangulationDescription::Utilities::create_description_from_triangulation()
+ * to create a TriangulationDescription::Description based on a given
+ * Triangulation and the predescribed partition, which can be used to
+ * set up a parallel::fullydistributed::Triangulation objects.
+ *
+ * These policies can be also used in context of
+ * MGTransferGlobalCoarseningTools::create_geometric_coarsening_sequence() to
+ * prescribe arbitrary partitioning in multgrid levels of global coarsening
+ * multigrid schmeme.
+ */
+namespace RepartitioningPolicyTools
+{
+  /**
+   * A base class of a repartitioning policy.
+   */
+  template <int dim, int spacedim = dim>
+  class Base
+  {
+  public:
+    /**
+     * Return a vector of the new owners of the active locally owned and ghost
+     * cells.
+     */
+    virtual LinearAlgebra::distributed::Vector<double>
+    partition(const Triangulation<dim, spacedim> &tria_coarse_in) const = 0;
+  };
+
+  /**
+   * A dummy policy that simply returns an empty vector, which is interpreted
+   * in MGTransferGlobalCoarseningTools::create_geometric_coarsening_sequence()
+   * in a way that the triangulation is not repartitioned.
+   */
+  template <int dim, int spacedim = dim>
+  class DefaultPolicy : public Base<dim, spacedim>
+  {
+  public:
+    virtual LinearAlgebra::distributed::Vector<double>
+    partition(
+      const Triangulation<dim, spacedim> &tria_coarse_in) const override;
+  };
+
+  /**
+   * A policy that partitions coarse grids based on a base triangulation
+   * according to a first-child policy. The triangulation to be partitioned
+   * should be able to be obtained by a sequence of (global) coarsening steps.
+   */
+  template <int dim, int spacedim = dim>
+  class FirstChildPolicy : public Base<dim, spacedim>
+  {
+  public:
+    /**
+     * Constructor taking the base (fine) triangulation.
+     */
+    FirstChildPolicy(const Triangulation<dim, spacedim> &tria_fine);
+
+    virtual LinearAlgebra::distributed::Vector<double>
+    partition(
+      const Triangulation<dim, spacedim> &tria_coarse_in) const override;
+
+  private:
+    /**
+     * Number of coarse cells.
+     */
+    const unsigned int n_coarse_cells;
+
+    /**
+     * Number of global levels.
+     */
+    const unsigned int n_global_levels;
+
+    /**
+     * Index set constructed from the triangulation passed to the constructor.
+     * It contains all the cells that would be owned by the current process
+     * if the levels would be partitioned according to a first-child policy.
+     */
+    IndexSet is_level_partitions;
+  };
+
+  /**
+   * A policy that allows to specify a minimal number of cells per process. If
+   * a threshold is reached, processes might be left without cells.
+   */
+  template <int dim, int spacedim = dim>
+  class MinimalGranularityPolicy : public Base<dim, spacedim>
+  {
+  public:
+    /**
+     * Constructor taking the minimum number of cells per process.
+     */
+    MinimalGranularityPolicy(const unsigned int n_min_cells);
+
+    virtual LinearAlgebra::distributed::Vector<double>
+    partition(const Triangulation<dim, spacedim> &tria_in) const override;
+
+  private:
+    /**
+     * Minimum number of cells per process.
+     */
+    const unsigned int n_min_cells;
+  };
+
+} // namespace RepartitioningPolicyTools
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
index 1e374aac08e552b918459970795888aadfc8f7a4..836602ef8dffcfad2a8b2417354ca0a6a04342bf 100644 (file)
@@ -20,6 +20,7 @@ SET(_unity_include_src
   cell_weights.cc
   cell_data_transfer.cc
   fully_distributed_tria.cc
+  repartitioning_policy_tools.cc
   solution_transfer.cc
   tria.cc
   tria_base.cc
@@ -44,6 +45,7 @@ SET(_inst
   cell_weights.inst.in
   cell_data_transfer.inst.in
   fully_distributed_tria.inst.in
+  repartitioning_policy_tools.inst.in
   solution_transfer.inst.in
   tria.inst.in
   shared_tria.inst.in
diff --git a/source/distributed/repartitioning_policy_tools.cc b/source/distributed/repartitioning_policy_tools.cc
new file mode 100644 (file)
index 0000000..264bfb6
--- /dev/null
@@ -0,0 +1,235 @@
+// ---------------------------------------------------------------------
+//
+// 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.
+//
+// ---------------------------------------------------------------------
+
+
+#include <deal.II/base/mpi_compute_index_owner_internal.h>
+#include <deal.II/base/mpi_consensus_algorithms.h>
+
+#include <deal.II/distributed/repartitioning_policy_tools.h>
+
+#include <deal.II/multigrid/mg_transfer_global_coarsening.templates.h>
+
+DEAL_II_NAMESPACE_OPEN
+
+
+namespace RepartitioningPolicyTools
+{
+  namespace
+  {
+    template <typename MeshType>
+    unsigned int
+    compute_n_coarse_cells(const MeshType &mesh)
+    {
+      types::coarse_cell_id n_coarse_cells = 0;
+
+      for (const auto &cell :
+           mesh.get_triangulation().cell_iterators_on_level(0))
+        n_coarse_cells =
+          std::max(n_coarse_cells, cell->id().get_coarse_cell_id());
+
+      return Utilities::MPI::max(n_coarse_cells, mesh.get_communicator()) + 1;
+    }
+
+
+
+    template <typename MeshType>
+    unsigned int
+    compute_n_global_levels(const MeshType &mesh)
+    {
+      return mesh.get_triangulation().n_global_levels();
+    }
+
+
+
+    template <int dim, int spacedim>
+    void
+    add_indices_recursevly_for_first_child_policy(
+      const TriaIterator<CellAccessor<dim, spacedim>> &cell,
+      const internal::CellIDTranslator<dim> &          cell_id_translator,
+      IndexSet &                                       is_fine)
+    {
+      is_fine.add_index(cell_id_translator.translate(cell));
+
+      if (cell->level() > 0 &&
+          (cell->index() % GeometryInfo<dim>::max_children_per_cell) == 0)
+        add_indices_recursevly_for_first_child_policy(cell->parent(),
+                                                      cell_id_translator,
+                                                      is_fine);
+    }
+  } // namespace
+
+  template <int dim, int spacedim>
+  LinearAlgebra::distributed::Vector<double>
+  DefaultPolicy<dim, spacedim>::partition(
+    const Triangulation<dim, spacedim> &) const
+  {
+    return {}; // nothing to do
+  }
+
+
+
+  template <int dim, int spacedim>
+  FirstChildPolicy<dim, spacedim>::FirstChildPolicy(
+    const Triangulation<dim, spacedim> &tria_fine)
+    : n_coarse_cells(compute_n_coarse_cells(tria_fine))
+    , n_global_levels(compute_n_global_levels(tria_fine))
+  {
+    Assert(
+      tria_fine.all_reference_cells_are_hyper_cube(),
+      ExcMessage(
+        "FirstChildPolicy is only working for pure hex meshes at the moment."))
+
+      const internal::CellIDTranslator<dim>
+        cell_id_translator(n_coarse_cells, n_global_levels);
+    is_level_partitions.set_size(cell_id_translator.size());
+
+    for (const auto &cell : tria_fine.active_cell_iterators())
+      if (cell->is_locally_owned())
+        add_indices_recursevly_for_first_child_policy(cell,
+                                                      cell_id_translator,
+                                                      is_level_partitions);
+  }
+
+
+
+  template <int dim, int spacedim>
+  LinearAlgebra::distributed::Vector<double>
+  FirstChildPolicy<dim, spacedim>::partition(
+    const Triangulation<dim, spacedim> &tria_coarse_in) const
+  {
+    const auto communicator = tria_coarse_in.get_communicator();
+
+    const internal::CellIDTranslator<dim> cell_id_translator(n_coarse_cells,
+                                                             n_global_levels);
+
+    IndexSet is_coarse(cell_id_translator.size());
+
+    for (const auto &cell : tria_coarse_in.active_cell_iterators())
+      if (cell->is_locally_owned())
+        is_coarse.add_index(cell_id_translator.translate(cell));
+
+    std::vector<unsigned int> owning_ranks_of_coarse_cells(
+      is_coarse.n_elements());
+    {
+      Utilities::MPI::internal::ComputeIndexOwner::ConsensusAlgorithmsPayload
+        process(is_level_partitions,
+                is_coarse,
+                communicator,
+                owning_ranks_of_coarse_cells,
+                false);
+
+      Utilities::MPI::ConsensusAlgorithms::Selector<
+        std::pair<types::global_cell_index, types::global_cell_index>,
+        unsigned int>
+        consensus_algorithm(process, communicator);
+      consensus_algorithm.run();
+    }
+
+    const auto tria =
+      dynamic_cast<const parallel::TriangulationBase<dim, spacedim> *>(
+        &tria_coarse_in);
+
+    Assert(tria, ExcNotImplemented());
+
+    LinearAlgebra::distributed::Vector<double> partition(
+      tria->global_active_cell_index_partitioner().lock());
+
+    for (const auto &cell : tria_coarse_in.active_cell_iterators())
+      if (cell->is_locally_owned())
+        partition[cell->global_active_cell_index()] =
+          owning_ranks_of_coarse_cells[is_coarse.index_within_set(
+            cell_id_translator.translate(cell))];
+
+    partition.update_ghost_values();
+
+    return partition;
+  }
+
+
+  template <int dim, int spacedim>
+  MinimalGranularityPolicy<dim, spacedim>::MinimalGranularityPolicy(
+    const unsigned int n_min_cells)
+    : n_min_cells(n_min_cells)
+  {}
+
+
+
+  template <int dim, int spacedim>
+  LinearAlgebra::distributed::Vector<double>
+  MinimalGranularityPolicy<dim, spacedim>::partition(
+    const Triangulation<dim, spacedim> &tria_in) const
+  {
+    const auto tria =
+      dynamic_cast<const parallel::TriangulationBase<dim, spacedim> *>(
+        &tria_in);
+
+    Assert(tria, ExcNotImplemented());
+
+    LinearAlgebra::distributed::Vector<double> partition(
+      tria->global_active_cell_index_partitioner().lock());
+
+    // step 1) check if all processes have enough cells
+
+    unsigned int n_locally_owned_active_cells = 0;
+    for (const auto &cell : tria_in.active_cell_iterators())
+      if (cell->is_locally_owned())
+        ++n_locally_owned_active_cells;
+
+    const auto comm = tria_in.get_communicator();
+
+    if (Utilities::MPI::min(n_locally_owned_active_cells, comm) >= n_min_cells)
+      return {}; // all processes have enough cells
+
+    // step 2) there are processes which do not have enough cells so that
+    // a repartitioning kicks in with the aim that all processes that own
+    // cells have at least the specified number of cells
+
+    const unsigned int n_global_active_cells = tria_in.n_global_active_cells();
+
+    const unsigned int n_partitions =
+      std::max<unsigned int>(1,
+                             std::min(n_global_active_cells / n_min_cells,
+                                      Utilities::MPI::n_mpi_processes(comm)));
+
+    const unsigned int min_cells = n_global_active_cells / n_partitions;
+
+    const auto convert = [&](const unsigned int i) {
+      // determine the owner of a given index: we try to assign each process
+      // the same number of cells; if there is a remainder, we assign the
+      // first processes an additional cell (so that the difference of number of
+      // locally owned cells is never larger than one between processes).
+      if (i < (i / min_cells) * min_cells + (n_global_active_cells % min_cells))
+        return i / (min_cells + 1);
+      else
+        return (i - (n_global_active_cells % min_cells)) / min_cells;
+    };
+
+    for (const auto i : partition.locally_owned_elements())
+      partition[i] = convert(i);
+
+    partition.update_ghost_values();
+
+    return partition;
+  }
+
+
+} // namespace RepartitioningPolicyTools
+
+
+
+/*-------------- Explicit Instantiations -------------------------------*/
+#include "repartitioning_policy_tools.inst"
+
+DEAL_II_NAMESPACE_CLOSE
diff --git a/source/distributed/repartitioning_policy_tools.inst.in b/source/distributed/repartitioning_policy_tools.inst.in
new file mode 100644 (file)
index 0000000..7ed65d4
--- /dev/null
@@ -0,0 +1,31 @@
+// ---------------------------------------------------------------------
+//
+// 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.
+//
+// ---------------------------------------------------------------------
+
+
+
+for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS)
+  {
+#if deal_II_dimension <= deal_II_space_dimension
+    template class RepartitioningPolicyTools::
+      DefaultPolicy<deal_II_dimension, deal_II_space_dimension>;
+
+    template class RepartitioningPolicyTools::
+      FirstChildPolicy<deal_II_dimension, deal_II_space_dimension>;
+
+    template class RepartitioningPolicyTools::
+      MinimalGranularityPolicy<deal_II_dimension, deal_II_space_dimension>;
+
+#endif
+  }
diff --git a/tests/fullydistributed_grids/repartitioning_02.cc b/tests/fullydistributed_grids/repartitioning_02.cc
new file mode 100644 (file)
index 0000000..582d52e
--- /dev/null
@@ -0,0 +1,118 @@
+// ---------------------------------------------------------------------
+//
+// 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 different partitioning policies from RepartitioningPolicyTools.
+
+
+#include <deal.II/base/mpi_consensus_algorithms.h>
+
+#include <deal.II/distributed/fully_distributed_tria.h>
+#include <deal.II/distributed/repartitioning_policy_tools.h>
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/fe/fe_q.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/grid_out.h>
+#include <deal.II/grid/grid_tools.h>
+#include <deal.II/grid/tria_description.h>
+
+#include <deal.II/lac/la_parallel_vector.h>
+
+#include <deal.II/numerics/data_out.h>
+
+#include "tests.h"
+
+using namespace dealii;
+
+template <int dim, int spacedim>
+void
+create_triangulation(Triangulation<dim, spacedim> &tria)
+{
+  const unsigned int n_ref_global = 3;
+  const unsigned int n_ref_local  = 3;
+  GridGenerator::hyper_cube(tria, -1.0, +1.0);
+  tria.refine_global(n_ref_global);
+
+  for (unsigned int i = 0; i < n_ref_local; ++i)
+    {
+      for (auto cell : tria.active_cell_iterators())
+        if (cell->is_locally_owned())
+          {
+            bool flag = true;
+            for (unsigned int d = 0; d < dim; d++)
+              if (cell->center()[d] > 0.0)
+                flag = false;
+            if (flag)
+              cell->set_refine_flag();
+          }
+      tria.execute_coarsening_and_refinement();
+    }
+}
+
+int
+main(int argc, char **argv)
+{
+  Utilities::MPI::MPI_InitFinalize mpi(argc, argv, 1);
+  MPILogInitAll                    all;
+
+  const unsigned int dim  = 2;
+  const MPI_Comm     comm = MPI_COMM_WORLD;
+
+  parallel::distributed::Triangulation<dim> tria(comm);
+  create_triangulation(tria);
+
+  const auto test = [&](const auto &policy, const std::string &label) {
+    const auto partition_new = policy.partition(tria);
+    partition_new.update_ghost_values();
+
+    // repartition triangulation so that it has strided partitioning
+    const auto construction_data =
+      partition_new.size() == 0 ?
+        TriangulationDescription::Utilities::
+          create_description_from_triangulation(tria, comm) :
+        TriangulationDescription::Utilities::
+          create_description_from_triangulation(tria, partition_new);
+
+    parallel::fullydistributed::Triangulation<dim> tria_pft(comm);
+    tria_pft.create_triangulation(construction_data);
+
+    FE_Q<dim>       fe(2);
+    DoFHandler<dim> dof_handler(tria_pft);
+    dof_handler.distribute_dofs(fe);
+
+    // print statistics
+    deallog.push(label);
+    print_statistics(tria_pft);
+    print_statistics(dof_handler);
+    deallog.pop();
+  };
+
+  // default policy (simply copy p:d:T)
+  test(RepartitioningPolicyTools::DefaultPolicy<dim>(), "grid_policy_default");
+
+  // first-child policy
+  test(RepartitioningPolicyTools::FirstChildPolicy<dim>(tria),
+       "grid_policy_first");
+
+  // first-child policy
+  test(RepartitioningPolicyTools::MinimalGranularityPolicy<dim>(4),
+       "grid_policy_minimal_4");
+  test(RepartitioningPolicyTools::MinimalGranularityPolicy<dim>(100),
+       "grid_policy_minimal_100");
+  test(RepartitioningPolicyTools::MinimalGranularityPolicy<dim>(500),
+       "grid_policy_minimal_500");
+}
diff --git a/tests/fullydistributed_grids/repartitioning_02.mpirun=5.output b/tests/fullydistributed_grids/repartitioning_02.mpirun=5.output
new file mode 100644 (file)
index 0000000..76c746b
--- /dev/null
@@ -0,0 +1,184 @@
+
+DEAL:0:grid_policy_default::n_levels:                  7
+DEAL:0:grid_policy_default::n_cells:                   465
+DEAL:0:grid_policy_default::n_active_cells:            349
+DEAL:0:grid_policy_default::
+DEAL:0:grid_policy_default::n_dofs:                             4813
+DEAL:0:grid_policy_default::n_locally_owned_dofs:               993
+DEAL:0:grid_policy_default::
+DEAL:0:grid_policy_first::n_levels:                  7
+DEAL:0:grid_policy_first::n_cells:                   465
+DEAL:0:grid_policy_first::n_active_cells:            349
+DEAL:0:grid_policy_first::
+DEAL:0:grid_policy_first::n_dofs:                             4813
+DEAL:0:grid_policy_first::n_locally_owned_dofs:               993
+DEAL:0:grid_policy_first::
+DEAL:0:grid_policy_minimal_4::n_levels:                  7
+DEAL:0:grid_policy_minimal_4::n_cells:                   465
+DEAL:0:grid_policy_minimal_4::n_active_cells:            349
+DEAL:0:grid_policy_minimal_4::
+DEAL:0:grid_policy_minimal_4::n_dofs:                             4813
+DEAL:0:grid_policy_minimal_4::n_locally_owned_dofs:               993
+DEAL:0:grid_policy_minimal_4::
+DEAL:0:grid_policy_minimal_100::n_levels:                  7
+DEAL:0:grid_policy_minimal_100::n_cells:                   465
+DEAL:0:grid_policy_minimal_100::n_active_cells:            349
+DEAL:0:grid_policy_minimal_100::
+DEAL:0:grid_policy_minimal_100::n_dofs:                             4813
+DEAL:0:grid_policy_minimal_100::n_locally_owned_dofs:               993
+DEAL:0:grid_policy_minimal_100::
+DEAL:0:grid_policy_minimal_500::n_levels:                  7
+DEAL:0:grid_policy_minimal_500::n_cells:                   1001
+DEAL:0:grid_policy_minimal_500::n_active_cells:            751
+DEAL:0:grid_policy_minimal_500::
+DEAL:0:grid_policy_minimal_500::n_dofs:                             4813
+DEAL:0:grid_policy_minimal_500::n_locally_owned_dofs:               2417
+DEAL:0:grid_policy_minimal_500::
+
+DEAL:1:grid_policy_default::n_levels:                  7
+DEAL:1:grid_policy_default::n_cells:                   577
+DEAL:1:grid_policy_default::n_active_cells:            433
+DEAL:1:grid_policy_default::
+DEAL:1:grid_policy_default::n_dofs:                             4813
+DEAL:1:grid_policy_default::n_locally_owned_dofs:               944
+DEAL:1:grid_policy_default::
+DEAL:1:grid_policy_first::n_levels:                  7
+DEAL:1:grid_policy_first::n_cells:                   577
+DEAL:1:grid_policy_first::n_active_cells:            433
+DEAL:1:grid_policy_first::
+DEAL:1:grid_policy_first::n_dofs:                             4813
+DEAL:1:grid_policy_first::n_locally_owned_dofs:               944
+DEAL:1:grid_policy_first::
+DEAL:1:grid_policy_minimal_4::n_levels:                  7
+DEAL:1:grid_policy_minimal_4::n_cells:                   577
+DEAL:1:grid_policy_minimal_4::n_active_cells:            433
+DEAL:1:grid_policy_minimal_4::
+DEAL:1:grid_policy_minimal_4::n_dofs:                             4813
+DEAL:1:grid_policy_minimal_4::n_locally_owned_dofs:               944
+DEAL:1:grid_policy_minimal_4::
+DEAL:1:grid_policy_minimal_100::n_levels:                  7
+DEAL:1:grid_policy_minimal_100::n_cells:                   577
+DEAL:1:grid_policy_minimal_100::n_active_cells:            433
+DEAL:1:grid_policy_minimal_100::
+DEAL:1:grid_policy_minimal_100::n_dofs:                             4813
+DEAL:1:grid_policy_minimal_100::n_locally_owned_dofs:               944
+DEAL:1:grid_policy_minimal_100::
+DEAL:1:grid_policy_minimal_500::n_levels:                  7
+DEAL:1:grid_policy_minimal_500::n_cells:                   977
+DEAL:1:grid_policy_minimal_500::n_active_cells:            733
+DEAL:1:grid_policy_minimal_500::
+DEAL:1:grid_policy_minimal_500::n_dofs:                             4813
+DEAL:1:grid_policy_minimal_500::n_locally_owned_dofs:               2396
+DEAL:1:grid_policy_minimal_500::
+
+
+DEAL:2:grid_policy_default::n_levels:                  7
+DEAL:2:grid_policy_default::n_cells:                   665
+DEAL:2:grid_policy_default::n_active_cells:            499
+DEAL:2:grid_policy_default::
+DEAL:2:grid_policy_default::n_dofs:                             4813
+DEAL:2:grid_policy_default::n_locally_owned_dofs:               960
+DEAL:2:grid_policy_default::
+DEAL:2:grid_policy_first::n_levels:                  7
+DEAL:2:grid_policy_first::n_cells:                   665
+DEAL:2:grid_policy_first::n_active_cells:            499
+DEAL:2:grid_policy_first::
+DEAL:2:grid_policy_first::n_dofs:                             4813
+DEAL:2:grid_policy_first::n_locally_owned_dofs:               960
+DEAL:2:grid_policy_first::
+DEAL:2:grid_policy_minimal_4::n_levels:                  7
+DEAL:2:grid_policy_minimal_4::n_cells:                   665
+DEAL:2:grid_policy_minimal_4::n_active_cells:            499
+DEAL:2:grid_policy_minimal_4::
+DEAL:2:grid_policy_minimal_4::n_dofs:                             4813
+DEAL:2:grid_policy_minimal_4::n_locally_owned_dofs:               960
+DEAL:2:grid_policy_minimal_4::
+DEAL:2:grid_policy_minimal_100::n_levels:                  7
+DEAL:2:grid_policy_minimal_100::n_cells:                   665
+DEAL:2:grid_policy_minimal_100::n_active_cells:            499
+DEAL:2:grid_policy_minimal_100::
+DEAL:2:grid_policy_minimal_100::n_dofs:                             4813
+DEAL:2:grid_policy_minimal_100::n_locally_owned_dofs:               960
+DEAL:2:grid_policy_minimal_100::
+DEAL:2:grid_policy_minimal_500::n_levels:                  1
+DEAL:2:grid_policy_minimal_500::n_cells:                   1
+DEAL:2:grid_policy_minimal_500::n_active_cells:            1
+DEAL:2:grid_policy_minimal_500::
+DEAL:2:grid_policy_minimal_500::n_dofs:                             4813
+DEAL:2:grid_policy_minimal_500::n_locally_owned_dofs:               0
+DEAL:2:grid_policy_minimal_500::
+
+
+DEAL:3:grid_policy_default::n_levels:                  7
+DEAL:3:grid_policy_default::n_cells:                   657
+DEAL:3:grid_policy_default::n_active_cells:            493
+DEAL:3:grid_policy_default::
+DEAL:3:grid_policy_default::n_dofs:                             4813
+DEAL:3:grid_policy_default::n_locally_owned_dofs:               912
+DEAL:3:grid_policy_default::
+DEAL:3:grid_policy_first::n_levels:                  7
+DEAL:3:grid_policy_first::n_cells:                   657
+DEAL:3:grid_policy_first::n_active_cells:            493
+DEAL:3:grid_policy_first::
+DEAL:3:grid_policy_first::n_dofs:                             4813
+DEAL:3:grid_policy_first::n_locally_owned_dofs:               912
+DEAL:3:grid_policy_first::
+DEAL:3:grid_policy_minimal_4::n_levels:                  7
+DEAL:3:grid_policy_minimal_4::n_cells:                   657
+DEAL:3:grid_policy_minimal_4::n_active_cells:            493
+DEAL:3:grid_policy_minimal_4::
+DEAL:3:grid_policy_minimal_4::n_dofs:                             4813
+DEAL:3:grid_policy_minimal_4::n_locally_owned_dofs:               912
+DEAL:3:grid_policy_minimal_4::
+DEAL:3:grid_policy_minimal_100::n_levels:                  7
+DEAL:3:grid_policy_minimal_100::n_cells:                   657
+DEAL:3:grid_policy_minimal_100::n_active_cells:            493
+DEAL:3:grid_policy_minimal_100::
+DEAL:3:grid_policy_minimal_100::n_dofs:                             4813
+DEAL:3:grid_policy_minimal_100::n_locally_owned_dofs:               912
+DEAL:3:grid_policy_minimal_100::
+DEAL:3:grid_policy_minimal_500::n_levels:                  1
+DEAL:3:grid_policy_minimal_500::n_cells:                   1
+DEAL:3:grid_policy_minimal_500::n_active_cells:            1
+DEAL:3:grid_policy_minimal_500::
+DEAL:3:grid_policy_minimal_500::n_dofs:                             4813
+DEAL:3:grid_policy_minimal_500::n_locally_owned_dofs:               0
+DEAL:3:grid_policy_minimal_500::
+
+
+DEAL:4:grid_policy_default::n_levels:                  7
+DEAL:4:grid_policy_default::n_cells:                   541
+DEAL:4:grid_policy_default::n_active_cells:            406
+DEAL:4:grid_policy_default::
+DEAL:4:grid_policy_default::n_dofs:                             4813
+DEAL:4:grid_policy_default::n_locally_owned_dofs:               1004
+DEAL:4:grid_policy_default::
+DEAL:4:grid_policy_first::n_levels:                  7
+DEAL:4:grid_policy_first::n_cells:                   541
+DEAL:4:grid_policy_first::n_active_cells:            406
+DEAL:4:grid_policy_first::
+DEAL:4:grid_policy_first::n_dofs:                             4813
+DEAL:4:grid_policy_first::n_locally_owned_dofs:               1004
+DEAL:4:grid_policy_first::
+DEAL:4:grid_policy_minimal_4::n_levels:                  7
+DEAL:4:grid_policy_minimal_4::n_cells:                   541
+DEAL:4:grid_policy_minimal_4::n_active_cells:            406
+DEAL:4:grid_policy_minimal_4::
+DEAL:4:grid_policy_minimal_4::n_dofs:                             4813
+DEAL:4:grid_policy_minimal_4::n_locally_owned_dofs:               1004
+DEAL:4:grid_policy_minimal_4::
+DEAL:4:grid_policy_minimal_100::n_levels:                  7
+DEAL:4:grid_policy_minimal_100::n_cells:                   541
+DEAL:4:grid_policy_minimal_100::n_active_cells:            406
+DEAL:4:grid_policy_minimal_100::
+DEAL:4:grid_policy_minimal_100::n_dofs:                             4813
+DEAL:4:grid_policy_minimal_100::n_locally_owned_dofs:               1004
+DEAL:4:grid_policy_minimal_100::
+DEAL:4:grid_policy_minimal_500::n_levels:                  1
+DEAL:4:grid_policy_minimal_500::n_cells:                   1
+DEAL:4:grid_policy_minimal_500::n_active_cells:            1
+DEAL:4:grid_policy_minimal_500::
+DEAL:4:grid_policy_minimal_500::n_dofs:                             4813
+DEAL:4:grid_policy_minimal_500::n_locally_owned_dofs:               0
+DEAL:4:grid_policy_minimal_500::
+

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.