*/
namespace fullydistributed
{
- /**
- * Configuration flags for fully distributed Triangulations.
- * Settings can be combined using bitwise OR.
- *
- * @author Peter Munch, 2019
- */
- enum Settings
- {
- /**
- * Default settings, other options are disabled.
- */
- default_setting = 0x0,
- /**
- * This flags needs to be set to use the geometric multigrid
- * functionality. This option requires additional computation and
- * communication.
- */
- construct_multigrid_hierarchy = 0x1
- };
-
- /**
- * Information needed for each locally relevant cell, stored in
- * ConstructionData and used during construction of a
- * parallel::fullydistributed::Triangulation. This struct stores
- * the cell id, the subdomain_id and the level_subdomain_id as well as
- * information related to manifold_id and boundary_id.
- *
- * @author Peter Munch, 2019
- */
- template <int dim>
- struct CellData
- {
- /**
- * Constructor.
- */
- CellData() = default;
-
- /**
- * Boost serialization function
- */
- template <class Archive>
- void
- serialize(Archive &ar, const unsigned int /*version*/);
-
- /**
- * Comparison operator.
- */
- bool
- operator==(const CellData<dim> &other) const;
-
- /**
- * Unique CellID of the cell.
- */
- CellId::binary_type id;
-
- /**
- * subdomain_id of the cell.
- */
- types::subdomain_id subdomain_id;
-
- /**
- * level_subdomain_id of the cell.
- */
- types::subdomain_id level_subdomain_id;
-
- /**
- * Manifold id of the cell.
- */
- types::material_id manifold_id;
-
- /**
- * Manifold id of all lines of the cell.
- *
- * @note Only used for 2D and 3D.
- */
- std::array<types::manifold_id, GeometryInfo<dim>::lines_per_cell>
- manifold_line_ids;
-
- /**
- * Manifold id of all face quads of the cell.
- *
- * @note Only used for 3D.
- */
- std::array<types::manifold_id,
- dim == 1 ? 1 : GeometryInfo<3>::quads_per_cell>
- manifold_quad_ids;
-
- /**
- * List of face number and boundary id of all non-internal faces of the
- * cell.
- */
- std::vector<std::pair<unsigned int, types::boundary_id>> boundary_ids;
- };
-
-
-
- /**
- * Data used to construct a fully distributed triangulation in
- * parallel::fullydistributed::Triangulation::create_triangulation().
- *
- * @author Peter Munch, 2019
- */
- template <int dim, int spacedim>
- struct ConstructionData
- {
- /**
- * Boost serialization function
- */
- template <class Archive>
- void
- serialize(Archive &ar, const unsigned int /*version*/);
-
- /**
- * Comparison operator.
- */
- bool
- operator==(const ConstructionData<dim, spacedim> &other) const;
-
- /**
- * Cells of the locally-relevant coarse-grid triangulation.
- */
- std::vector<dealii::CellData<dim>> coarse_cells;
-
- /**
- * Vertices of the locally-relevant coarse-grid triangulation.
- */
- std::vector<Point<spacedim>> coarse_cell_vertices;
-
- /**
- * List that for each locally-relevant coarse cell provides the
- * corresponding global @ref GlossCoarseCellId.
- */
- std::vector<types::coarse_cell_id> coarse_cell_index_to_coarse_cell_id;
-
- /**
- * CellData for each locally relevant cell on each level. cell_infos[i]
- * contains the CellData for each locally relevant cell on the ith
- * level.
- */
- std::vector<std::vector<CellData<dim>>> cell_infos;
-
- /**
- * The MPI communicator used to create this struct. It will be compared
- * to the communicator inside of parallel::fullydistributed::Triangulation
- * and an assert is thrown if they do not match.
- *
- * @note This is necessary since the communicator inside of
- * parallel::TriangulationBase is const and cannot be changed after the
- * constructor has been called.
- *
- */
- MPI_Comm comm;
-
- /**
- * @note settings See the description of the Settings enumerator.
- */
- Settings settings;
- };
-
-
-
/**
* A distributed triangulation with a distributed coarse grid.
*
virtual ~Triangulation() = default;
/**
- * Create a triangulation from the provided ConstructionData.
- *
- * @note The namespace dealii::fullydistributed::Util contains functions
- * to create ConstructionData.
+ * @copydoc Triangulation::create_triangulation()
*
* @note This is the function to be used instead of
* Triangulation::create_triangulation() for some of the other
* triangulations of deal.II.
- *
- * @param construction_data The data needed for this process.
*/
void
create_triangulation(
- const ConstructionData<dim, spacedim> &construction_data);
+ const TriangulationDescription::Description<dim, spacedim>
+ &construction_data) override;
/**
* @note This function is not implemented for this class and throws
* an assertion. Instead, use
* the other create_triangulation() function to create the
- * triangulation.
+ * triangulation.
*/
virtual void
create_triangulation(const std::vector<Point<spacedim>> & vertices,
set_partitioner(
const std::function<void(dealii::Triangulation<dim, spacedim> &,
const unsigned int)> &partitioner,
- const Settings & settings);
+ const TriangulationDescription::Settings & settings);
/**
* Coarsen and refine the mesh according to refinement and coarsening
/**
* store the Settings.
*/
- Settings settings;
+ TriangulationDescription::Settings settings;
/**
* Partitioner used in copy_triangulation().
currently_processing_prepare_coarsening_and_refinement_for_internal_usage;
};
-
-#ifndef DOXYGEN
-
- template <int dim>
- template <class Archive>
- void
- CellData<dim>::serialize(Archive &ar, const unsigned int /*version*/)
- {
- ar &id;
- ar &subdomain_id;
- ar &level_subdomain_id;
- ar &manifold_id;
- if (dim >= 2)
- ar &manifold_line_ids;
- if (dim >= 3)
- ar &manifold_quad_ids;
- ar &boundary_ids;
- }
-
-
- template <int dim, int spacedim>
- template <class Archive>
- void
- ConstructionData<dim, spacedim>::serialize(Archive &ar,
- const unsigned int /*version*/)
- {
- ar &coarse_cells;
- ar &coarse_cell_vertices;
- ar &coarse_cell_index_to_coarse_cell_id;
- ar &cell_infos;
- ar &settings;
- }
-
-
-
- template <int dim>
- bool
- CellData<dim>::operator==(const CellData<dim> &other) const
- {
- if (this->id != other.id)
- return false;
- if (this->subdomain_id != other.subdomain_id)
- return false;
- if (this->level_subdomain_id != other.level_subdomain_id)
- return false;
- if (this->manifold_id != other.manifold_id)
- return false;
- if (dim >= 2 && this->manifold_line_ids != other.manifold_line_ids)
- return false;
- if (dim >= 3 && this->manifold_quad_ids != other.manifold_quad_ids)
- return false;
- if (this->boundary_ids != other.boundary_ids)
- return false;
-
- return true;
- }
-
-
-
- template <int dim, int spacedim>
- bool
- ConstructionData<dim, spacedim>::
- operator==(const ConstructionData<dim, spacedim> &other) const
- {
- if (this->coarse_cells != other.coarse_cells)
- return false;
- if (this->coarse_cell_vertices != other.coarse_cell_vertices)
- return false;
- if (this->coarse_cell_index_to_coarse_cell_id !=
- other.coarse_cell_index_to_coarse_cell_id)
- return false;
- if (this->cell_infos != other.cell_infos)
- return false;
- if (this->settings != other.settings)
- return false;
-
- return true;
- }
-
-#endif
-
} // namespace fullydistributed
} // namespace parallel
+++ /dev/null
-// ---------------------------------------------------------------------
-//
-// Copyright (C) 2019 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_fully_distributed_tria_util_h
-#define dealii_fully_distributed_tria_util_h
-
-#include <deal.II/base/config.h>
-
-#include <deal.II/distributed/fully_distributed_tria.h>
-
-DEAL_II_NAMESPACE_OPEN
-
-namespace parallel
-{
- namespace fullydistributed
- {
- /**
- * A namespace for fully distributed triangulation utility functions.
- *
- * @ingroup fullydistributed
- */
- namespace Utilities
- {
- /**
- * Construct parallel::fullydistributed::ConstructionData from a given
- * partitioned triangulation `tria` and a specified process.
- * The input triangulation can be either
- * a serial triangulation of type dealii::Triangulation which has been
- * colored (subdomain_id and/or level_subdomain_id has been set) or a
- * distributed triangulation of type dealii::distributed::Triangulation,
- * where the partitioning is adopted unaltered.
- *
- * @param tria Partitioned input triangulation.
- * @param comm MPI_Communicator to be used. In the case
- * of dealii::distributed::Triangulation, the communicators
- * have to match.
- * @param construct_multilevel_hierarchy Signal if the multigrid levels
- * should be constructed.
- * @param my_rank_in Construct ConstructionData for this rank (only
- * working for serial triangulations).
- * @return ConstructionData to be used to setup
- * parallel::fullydistributed::Triangulation.
- *
- * @note Multilevel hierarchies are supported if it is enabled in
- * parallel::fullydistributed::Triangulation.
- *
- * @note Hanging nodes in the input triangulation are supported. However,
- * to be able to use this
- * feature, the user has to enable multilevel hierarchy support in
- * parallel::fullydistributed::Triangulation.
- *
- * @author Peter Munch, 2019
- */
- template <int dim, int spacedim = dim>
- ConstructionData<dim, spacedim>
- create_construction_data_from_triangulation(
- const dealii::Triangulation<dim, spacedim> &tria,
- const MPI_Comm comm,
- const bool construct_multilevel_hierarchy = false,
- const unsigned int my_rank_in = numbers::invalid_unsigned_int);
-
-
- /**
- * Construct a parallel::fullydistributed::ConstructionData. In contrast
- * to the function above, this function is also responsible for creating
- * a serial triangulation and for its partitioning (by calling the
- * provided std::functions). Internally only selected processes (every
- * n-th/each root of a group of size group_size) create a serial
- * triangulation and the ConstructionData for all processes in its group,
- * which is communicated.
- *
- * @note A reasonable group size is the size of a NUMA domain or the
- * size of a compute node.
- *
- * @param serial_grid_generator A function, which creates a serial triangulation.
- * @param serial_grid_partitioner A function, which can partition a serial
- * triangulation, i.e., sets the sudomain_ids of the active cells.
- * The function takes as the first argument a serial triangulation,
- * as the second argument the MPI communicator, and as the third
- * argument the group size.
- * @param comm MPI communicator
- * @param group_size The size of each group.
- * @param construct_multilevel_hierarchy Construct multigrid levels.
- * @return ConstructionData to be used to setup
- * parallel::fullydistributed::Triangulation.
- *
- * @author Peter Munch, 2019
- */
- template <int dim, int spacedim = dim>
- ConstructionData<dim, spacedim>
- create_construction_data_from_triangulation_in_groups(
- std::function<void(dealii::Triangulation<dim, spacedim> &)>
- serial_grid_generator,
- std::function<void(dealii::Triangulation<dim, spacedim> &,
- const MPI_Comm,
- const unsigned int)> serial_grid_partitioner,
- const MPI_Comm comm,
- const int group_size = 1,
- const bool construct_multilevel_hierarchy = false);
-
- } // namespace Utilities
- } // namespace fullydistributed
-} // namespace parallel
-
-
-DEAL_II_NAMESPACE_CLOSE
-
-#endif
const std::vector<CellData<dim>> & cells,
const SubCellData &subcelldata) override;
+ /*
+ * @copydoc Triangulation::create_triangulation()
+ *
+ * @note Not inmplemented yet.
+ */
+ virtual void
+ create_triangulation(
+ const TriangulationDescription::Description<dim, spacedim>
+ &construction_data) override;
+
/**
* Copy @p other_tria to this triangulation.
*
const std::vector<CellData<dim>> & cells,
const SubCellData &subcelldata) override;
+ /*
+ * @copydoc Triangulation::create_triangulation()
+ *
+ * @note Not inmplemented yet.
+ */
+ virtual void
+ create_triangulation(
+ const TriangulationDescription::Description<dim, spacedim>
+ &construction_data) override;
+
/**
* Coarsen and refine the mesh according to refinement and coarsening
* flags set.
const std::vector<CellData<dim>> & cells,
const SubCellData &subcelldata) override;
+ /*
+ * @copydoc Triangulation::create_triangulation()
+ *
+ * @note Not inmplemented yet.
+ */
+ virtual void
+ create_triangulation(
+ const TriangulationDescription::Description<dim, spacedim>
+ &construction_data) override;
+
/**
* An overload of the respective function of the base class.
*
#include <deal.II/base/smartpointer.h>
#include <deal.II/base/subscriptor.h>
+#include <deal.II/grid/tria_description.h>
#include <deal.II/grid/tria_iterator_selector.h>
#include <boost/serialization/map.hpp>
template <int dim, int spacedim>
class Manifold;
+template <int dim>
+struct CellData;
+
+struct SubCellData;
+
+namespace TriangulationDescription
+{
+ template <int, int>
+ struct Description;
+}
+
namespace GridTools
{
template <typename CellIterator>
}
#endif
-/*------------------------------------------------------------------------*/
-
-/**
- * The CellData class (and the related SubCellData class) is used to
- * provide a comprehensive, but minimal, description of the cells when
- * creating a triangulation via Triangulation::create_triangulation().
- * Specifically, each CellData object -- describing one cell in a
- * triangulation -- has member variables for indices of the $2^d$ vertices
- * (the actual coordinates of the vertices are described in a separate
- * vector passed to Triangulation::create_triangulation(), so the CellData
- * object only needs to store indices into that vector), the material
- * id of the cell that can be used in applications to describe which
- * part of the domain a cell belongs to (see
- * @ref GlossMaterialId "the glossary entry on material ids"),
- * and a manifold id that is used to describe the geometry object
- * that is responsible for this cell (see
- * @ref GlossManifoldIndicator "the glossary entry on manifold ids")
- * to describe the manifold this object belongs to.
- *
- * This structure is also used to represent data for faces and edges when used
- * as a member of the SubCellData class. In this case, the template argument
- * @p structdim of an object will be less than the dimension @p dim of the
- * triangulation. If this is so, then #vertices array represents the indices of
- * the vertices of one face or edge of one of the cells passed to
- * Triangulation::create_triangulation(). Furthermore, for faces the
- * material id has no meaning, and the @p material_id field is reused
- * to store a @p boundary_id instead to designate which part of the boundary
- * the face or edge belongs to (see
- * @ref GlossBoundaryIndicator "the glossary entry on boundary ids").
- *
- * An example showing how this class can be used is in the
- * <code>create_coarse_grid()</code> function of step-14. There are also
- * many more use cases in the implementation of the functions of the
- * GridGenerator namespace.
- *
- * @ingroup grid
- */
-template <int structdim>
-struct CellData
-{
- /**
- * Indices of the vertices of this cell. These indices correspond
- * to entries in the vector of vertex locations passed to
- * Triangulation::create_triangulation().
- */
- unsigned int vertices[GeometryInfo<structdim>::vertices_per_cell];
-
- /**
- * Material or boundary indicator of this cell.
- * This field is a union that stores <i>either</i> a boundary or
- * a material id, depending on whether the current object is used
- * to describe a cell (in a vector of CellData objects) or a
- * face or edge (as part of a SubCellData object).
- */
- union
- {
- /**
- * The material id of the cell being described. See the documentation
- * of the CellData class for examples of how to use this field.
- *
- * This variable can only be used if the current object is used to
- * describe a cell, i.e., if @p structdim equals the dimension
- * @p dim of a triangulation.
- */
- types::material_id material_id;
-
- /**
- * The boundary id of a face or edge being described. See the documentation
- * of the CellData class for examples of how to use this field.
- *
- * This variable can only be used if the current object is used to
- * describe a face or edge, i.e., if @p structdim is less than the dimension
- * @p dim of a triangulation. In this case, the CellData object this
- * variable belongs to will be part of a SubCellData object.
- */
- types::boundary_id boundary_id;
- };
-
- /**
- * Manifold identifier of this object. This identifier should be used to
- * identify the manifold to which this object belongs, and from which this
- * object will collect information on how to add points upon refinement.
- *
- * See the documentation of the CellData class for examples of how to use
- * this field.
- */
- types::manifold_id manifold_id;
-
- /**
- * Default constructor. Sets the member variables to the following values:
- *
- * - vertex indices to invalid values
- * - boundary or material id zero (the default for boundary or material ids)
- * - manifold id to numbers::flat_manifold_id
- */
- CellData();
-
- /**
- * Comparison operator.
- */
- bool
- operator==(const CellData<structdim> &other) const;
-
- /**
- * Boost serialization function
- */
- template <class Archive>
- void
- serialize(Archive &ar, const unsigned int version);
-
- static_assert(structdim > 0,
- "The class CellData can only be used for structdim>0.");
-};
-
-
-
-/**
- * The SubCellData class is used to describe information about faces and
- * edges at the boundary of a mesh when creating a triangulation via
- * Triangulation::create_triangulation(). It contains member variables
- * that describe boundary edges and boundary quads.
- *
- * The class has no template argument and is used both in the description
- * of boundary edges in 2d (in which case the contents of the
- * @p boundary_quads member variable are ignored), as well as in the
- * description of boundary edges and faces in 3d (in which case both the
- * @p boundary_lines and @p boundary_quads members may be used). It is also
- * used as the argument to Triangulation::create_triangulation() in 1d,
- * where the contents of objects of the current type are simply ignored.
- *
- * By default, Triangulation::create_triangulation() simply assigns
- * default boundary indicators and manifold indicators to edges and
- * quads at the boundary of the mesh. (See the glossary entries on
- * @ref GlossBoundaryIndicator "boundary ids"
- * and
- * @ref GlossManifoldIndicator "manifold ids"
- * for more information on what they represent.) As a consequence,
- * it is not <i>necessary</i> to explicitly describe the properties
- * of boundary objects. In all cases, these properties can also be
- * set at a later time, once the triangulation has already been
- * created. On the other hand, it is sometimes convenient to describe
- * boundary indicators or manifold ids at the time of creation. In
- * these cases, the current class can be used by filling the
- * @p boundary_lines and @p boundary_quads vectors with
- * CellData<1> and CellData<2> objects that correspond to boundary
- * edges and quads for which properties other than the default
- * values should be used.
- *
- * Each entry in the @p boundary_lines and @p boundary_quads vectors
- * then needs to correspond to an edge or quad of the cells that
- * are described by the vector of CellData objects passed to
- * Triangulation::create_triangulation(). I.e., the vertex indices
- * stored in each entry need to correspond to an edge or face
- * of the triangulation that has the same set of vertex indices,
- * and in the same order. For these boundary edges or quads, one can
- * then set either or both the CellData::boundary_id and
- * CellData::manifold_id.
- *
- * There are also use cases where one may want to set the manifold id
- * of an <i>interior</i> edge or face. Such faces, identified by
- * their vertex indices, may also appear in the
- * @p boundary_lines and @p boundary_quads vectors (despite the names of
- * these member variables). However, it is then obviously not allowed
- * to set a boundary id (because the object is not actually part of
- * the boundary). As a consequence, to be valid, the CellData::boundary_id
- * of interior edges or faces needs to equal
- * numbers::internal_face_boundary_id.
- *
- * @ingroup grid
- */
-struct SubCellData
-{
- /**
- * A vector of CellData<1> objects that describe boundary and manifold
- * information for edges of 2d or 3d triangulations.
- *
- * This vector may not be used in the creation of 1d triangulations.
- */
- std::vector<CellData<1>> boundary_lines;
-
- /**
- * A vector of CellData<2> objects that describe boundary and manifold
- * information for quads of 3d triangulations.
- *
- * This vector may not be used in the creation of 1d or 2d triangulations.
- */
- std::vector<CellData<2>> boundary_quads;
-
- /**
- * Determine whether the member variables above which may not be used in a
- * given dimension are really empty. In other words, this function returns
- * whether
- * both @p boundary_lines and @p boundary_quads are empty vectors
- * when @p dim equals one, and whether the @p boundary_quads
- * vector is empty when @p dim equals two.
- */
- bool
- check_consistency(const unsigned int dim) const;
-};
-
/*------------------------------------------------------------------------*/
const std::vector<CellData<dim>> & cells,
const SubCellData & subcelldata);
+ /**
+ * Create a triangulation from the provided
+ * TriangulationDescription::Description.
+ *
+ * @note The namespace construction::Utilities contains functions
+ * to create TriangulationDescription::Description.
+ *
+ * @param construction_data The data needed for this process.
+ */
+ virtual void
+ create_triangulation(
+ const TriangulationDescription::Description<dim, spacedim>
+ &construction_data);
+
/**
* For backward compatibility, only. This function takes the cell data in
* the ordering as requested by deal.II versions up to 5.2, converts it to
#ifndef DOXYGEN
-template <int structdim>
-template <class Archive>
-void
-CellData<structdim>::serialize(Archive &ar, const unsigned int /*version*/)
-{
- ar &vertices;
- ar &material_id;
- ar &boundary_id;
- ar &manifold_id;
-}
-
-
namespace internal
{
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2019 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_grid_construction_utilities_h
+#define dealii_grid_construction_utilities_h
+
+#include <deal.II/base/config.h>
+
+#include <deal.II/base/mpi.h>
+
+#include <deal.II/grid/cell_id.h>
+#include <deal.II/grid/tria.h>
+
+
+DEAL_II_NAMESPACE_OPEN
+
+/*------------------------------------------------------------------------*/
+
+/**
+ * The CellData class (and the related SubCellData class) is used to
+ * provide a comprehensive, but minimal, description of the cells when
+ * creating a triangulation via Triangulation::create_triangulation().
+ * Specifically, each CellData object -- describing one cell in a
+ * triangulation -- has member variables for indices of the $2^d$ vertices
+ * (the actual coordinates of the vertices are described in a separate
+ * vector passed to Triangulation::create_triangulation(), so the CellData
+ * object only needs to store indices into that vector), the material
+ * id of the cell that can be used in applications to describe which
+ * part of the domain a cell belongs to (see
+ * @ref GlossMaterialId "the glossary entry on material ids"),
+ * and a manifold id that is used to describe the geometry object
+ * that is responsible for this cell (see
+ * @ref GlossManifoldIndicator "the glossary entry on manifold ids")
+ * to describe the manifold this object belongs to.
+ *
+ * This structure is also used to represent data for faces and edges when used
+ * as a member of the SubCellData class. In this case, the template argument
+ * @p structdim of an object will be less than the dimension @p dim of the
+ * triangulation. If this is so, then #vertices array represents the indices of
+ * the vertices of one face or edge of one of the cells passed to
+ * Triangulation::create_triangulation(). Furthermore, for faces the
+ * material id has no meaning, and the @p material_id field is reused
+ * to store a @p boundary_id instead to designate which part of the boundary
+ * the face or edge belongs to (see
+ * @ref GlossBoundaryIndicator "the glossary entry on boundary ids").
+ *
+ * An example showing how this class can be used is in the
+ * <code>create_coarse_grid()</code> function of step-14. There are also
+ * many more use cases in the implementation of the functions of the
+ * GridGenerator namespace.
+ *
+ * @ingroup grid
+ */
+template <int structdim>
+struct CellData
+{
+ /**
+ * Indices of the vertices of this cell. These indices correspond
+ * to entries in the vector of vertex locations passed to
+ * Triangulation::create_triangulation().
+ */
+ unsigned int vertices[GeometryInfo<structdim>::vertices_per_cell];
+
+ /**
+ * Material or boundary indicator of this cell.
+ * This field is a union that stores <i>either</i> a boundary or
+ * a material id, depending on whether the current object is used
+ * to describe a cell (in a vector of CellData objects) or a
+ * face or edge (as part of a SubCellData object).
+ */
+ union
+ {
+ /**
+ * The material id of the cell being described. See the documentation
+ * of the CellData class for examples of how to use this field.
+ *
+ * This variable can only be used if the current object is used to
+ * describe a cell, i.e., if @p structdim equals the dimension
+ * @p dim of a triangulation.
+ */
+ types::material_id material_id;
+
+ /**
+ * The boundary id of a face or edge being described. See the documentation
+ * of the CellData class for examples of how to use this field.
+ *
+ * This variable can only be used if the current object is used to
+ * describe a face or edge, i.e., if @p structdim is less than the dimension
+ * @p dim of a triangulation. In this case, the CellData object this
+ * variable belongs to will be part of a SubCellData object.
+ */
+ types::boundary_id boundary_id;
+ };
+
+ /**
+ * Manifold identifier of this object. This identifier should be used to
+ * identify the manifold to which this object belongs, and from which this
+ * object will collect information on how to add points upon refinement.
+ *
+ * See the documentation of the CellData class for examples of how to use
+ * this field.
+ */
+ types::manifold_id manifold_id;
+
+ /**
+ * Default constructor. Sets the member variables to the following values:
+ *
+ * - vertex indices to invalid values
+ * - boundary or material id zero (the default for boundary or material ids)
+ * - manifold id to numbers::flat_manifold_id
+ */
+ CellData();
+
+ /**
+ * Comparison operator.
+ */
+ bool
+ operator==(const CellData<structdim> &other) const;
+
+ /**
+ * Boost serialization function
+ */
+ template <class Archive>
+ void
+ serialize(Archive &ar, const unsigned int version);
+
+ static_assert(structdim > 0,
+ "The class CellData can only be used for structdim>0.");
+};
+
+
+
+/**
+ * The SubCellData class is used to describe information about faces and
+ * edges at the boundary of a mesh when creating a triangulation via
+ * Triangulation::create_triangulation(). It contains member variables
+ * that describe boundary edges and boundary quads.
+ *
+ * The class has no template argument and is used both in the description
+ * of boundary edges in 2d (in which case the contents of the
+ * @p boundary_quads member variable are ignored), as well as in the
+ * description of boundary edges and faces in 3d (in which case both the
+ * @p boundary_lines and @p boundary_quads members may be used). It is also
+ * used as the argument to Triangulation::create_triangulation() in 1d,
+ * where the contents of objects of the current type are simply ignored.
+ *
+ * By default, Triangulation::create_triangulation() simply assigns
+ * default boundary indicators and manifold indicators to edges and
+ * quads at the boundary of the mesh. (See the glossary entries on
+ * @ref GlossBoundaryIndicator "boundary ids"
+ * and
+ * @ref GlossManifoldIndicator "manifold ids"
+ * for more information on what they represent.) As a consequence,
+ * it is not <i>necessary</i> to explicitly describe the properties
+ * of boundary objects. In all cases, these properties can also be
+ * set at a later time, once the triangulation has already been
+ * created. On the other hand, it is sometimes convenient to describe
+ * boundary indicators or manifold ids at the time of creation. In
+ * these cases, the current class can be used by filling the
+ * @p boundary_lines and @p boundary_quads vectors with
+ * CellData<1> and CellData<2> objects that correspond to boundary
+ * edges and quads for which properties other than the default
+ * values should be used.
+ *
+ * Each entry in the @p boundary_lines and @p boundary_quads vectors
+ * then needs to correspond to an edge or quad of the cells that
+ * are described by the vector of CellData objects passed to
+ * Triangulation::create_triangulation(). I.e., the vertex indices
+ * stored in each entry need to correspond to an edge or face
+ * of the triangulation that has the same set of vertex indices,
+ * and in the same order. For these boundary edges or quads, one can
+ * then set either or both the CellData::boundary_id and
+ * CellData::manifold_id.
+ *
+ * There are also use cases where one may want to set the manifold id
+ * of an <i>interior</i> edge or face. Such faces, identified by
+ * their vertex indices, may also appear in the
+ * @p boundary_lines and @p boundary_quads vectors (despite the names of
+ * these member variables). However, it is then obviously not allowed
+ * to set a boundary id (because the object is not actually part of
+ * the boundary). As a consequence, to be valid, the CellData::boundary_id
+ * of interior edges or faces needs to equal
+ * numbers::internal_face_boundary_id.
+ *
+ * @ingroup grid
+ */
+struct SubCellData
+{
+ /**
+ * A vector of CellData<1> objects that describe boundary and manifold
+ * information for edges of 2d or 3d triangulations.
+ *
+ * This vector may not be used in the creation of 1d triangulations.
+ */
+ std::vector<CellData<1>> boundary_lines;
+
+ /**
+ * A vector of CellData<2> objects that describe boundary and manifold
+ * information for quads of 3d triangulations.
+ *
+ * This vector may not be used in the creation of 1d or 2d triangulations.
+ */
+ std::vector<CellData<2>> boundary_quads;
+
+ /**
+ * Determine whether the member variables above which may not be used in a
+ * given dimension are really empty. In other words, this function returns
+ * whether
+ * both @p boundary_lines and @p boundary_quads are empty vectors
+ * when @p dim equals one, and whether the @p boundary_quads
+ * vector is empty when @p dim equals two.
+ */
+ bool
+ check_consistency(const unsigned int dim) const;
+};
+
+
+template <int structdim>
+template <class Archive>
+void
+CellData<structdim>::serialize(Archive &ar, const unsigned int /*version*/)
+{
+ ar &vertices;
+ ar &material_id;
+ ar &boundary_id;
+ ar &manifold_id;
+}
+
+/**
+ * A namespace dedicated to the struct Description, which can be used in
+ * Triangulation::create_triangulation().
+ */
+namespace TriangulationDescription
+{
+ /**
+ * Configuration flags for Triangulations.
+ * Settings can be combined using bitwise OR.
+ *
+ * @author Peter Munch, 2019
+ */
+ enum Settings
+ {
+ /**
+ * Default settings, other options are disabled.
+ */
+ default_setting = 0x0,
+ /**
+ * This flag needs to be set to use the geometric multigrid
+ * functionality. This option requires additional computation and
+ * communication.
+ */
+ construct_multigrid_hierarchy = 0x1
+ };
+
+ /**
+ * Information needed for each locally relevant cell, stored in
+ * Description and used during construction of a
+ * Triangulation. This struct stores
+ * the cell id, the subdomain_id and the level_subdomain_id as well as
+ * information related to manifold_id and boundary_id.
+ *
+ * @author Peter Munch, 2019
+ */
+ template <int dim>
+ struct CellData
+ {
+ /**
+ * Constructor.
+ */
+ CellData() = default;
+
+ /**
+ * Boost serialization function
+ */
+ template <class Archive>
+ void
+ serialize(Archive &ar, const unsigned int /*version*/);
+
+ /**
+ * Comparison operator.
+ */
+ bool
+ operator==(const CellData<dim> &other) const;
+
+ /**
+ * Unique CellID of the cell.
+ */
+ CellId::binary_type id;
+
+ /**
+ * subdomain_id of the cell.
+ */
+ types::subdomain_id subdomain_id;
+
+ /**
+ * level_subdomain_id of the cell.
+ */
+ types::subdomain_id level_subdomain_id;
+
+ /**
+ * Manifold id of the cell.
+ */
+ types::material_id manifold_id;
+
+ /**
+ * Manifold id of all lines of the cell.
+ *
+ * @note Only used for 2D and 3D.
+ */
+ std::array<types::manifold_id, GeometryInfo<dim>::lines_per_cell>
+ manifold_line_ids;
+
+ /**
+ * Manifold id of all face quads of the cell.
+ *
+ * @note Only used for 3D.
+ */
+ std::array<types::manifold_id,
+ dim == 1 ? 1 : GeometryInfo<3>::quads_per_cell>
+ manifold_quad_ids;
+
+ /**
+ * List of face number and boundary id of all non-internal faces of the
+ * cell.
+ */
+ std::vector<std::pair<unsigned int, types::boundary_id>> boundary_ids;
+ };
+
+ /**
+ * Data used in Triangulation::create_triangulation().
+ *
+ * @author Peter Munch, 2019
+ */
+ template <int dim, int spacedim>
+ struct Description
+ {
+ /**
+ * Boost serialization function
+ */
+ template <class Archive>
+ void
+ serialize(Archive &ar, const unsigned int /*version*/);
+
+ /**
+ * Comparison operator.
+ */
+ bool
+ operator==(const Description<dim, spacedim> &other) const;
+
+ /**
+ * Cells of the locally-relevant coarse-grid triangulation.
+ */
+ std::vector<dealii::CellData<dim>> coarse_cells;
+
+ /**
+ * Vertices of the locally-relevant coarse-grid triangulation.
+ */
+ std::vector<Point<spacedim>> coarse_cell_vertices;
+
+ /**
+ * List that for each locally-relevant coarse cell provides the
+ * corresponding global @ref GlossCoarseCellId.
+ */
+ std::vector<types::coarse_cell_id> coarse_cell_index_to_coarse_cell_id;
+
+ /**
+ * CellData for each locally relevant cell on each level. cell_infos[i]
+ * contains the CellData for each locally relevant cell on the ith
+ * level.
+ */
+ std::vector<std::vector<CellData<dim>>> cell_infos;
+
+ /**
+ * The MPI communicator used to create this struct. It will be compared
+ * to the communicator inside of the Triangulation
+ * and an assert is thrown if they do not match.
+ *
+ * @note Please note this is necessary since the communicator inside of
+ * parallel::TriangulationBase is const and cannot be changed after the
+ * constructor has been called.
+ *
+ */
+ MPI_Comm comm;
+
+ /**
+ * Properties to be use in the construction of the triangulation.
+ */
+ Settings settings;
+ };
+
+
+ /**
+ * A namespace for TriangulationDescription::Description utility functions.
+ *
+ * @ingroup TriangulationDescription
+ */
+ namespace Utilities
+ {
+ /**
+ * Construct TriangulationDescription::Description from a given
+ * partitioned triangulation `tria` and a specified process.
+ * The input triangulation can be either
+ * a serial triangulation of type dealii::Triangulation which has been
+ * colored (subdomain_id and/or level_subdomain_id has been set) or a
+ * distributed triangulation of type dealii::distributed::Triangulation,
+ * where the partitioning is adopted unaltered.
+ *
+ * @param tria Partitioned input triangulation.
+ * @param comm MPI_Communicator to be used. In the case
+ * of dealii::distributed::Triangulation, the communicators
+ * have to match.
+ * @param construct_multilevel_hierarchy Signal if the multigrid levels
+ * should be constructed.
+ * @param my_rank_in Construct Description for this rank (only
+ * working for serial triangulations).
+ * @return Description to be used to setup a Triangulation.
+ *
+ * @note Multilevel hierarchies are supported if it is enabled in
+ * parallel::fullydistributed::Triangulation.
+ *
+ * @note Hanging nodes in the input triangulation are supported. However,
+ * to be able to use this
+ * feature in the case of parallel::fullydistributed::Triangulation,
+ * the user has to enable multilevel hierarchy support in
+ * parallel::fullydistributed::Triangulation.
+ *
+ * @author Peter Munch, 2019
+ */
+ template <int dim, int spacedim = dim>
+ Description<dim, spacedim>
+ create_description_from_triangulation(
+ const dealii::Triangulation<dim, spacedim> &tria,
+ const MPI_Comm comm,
+ const bool construct_multilevel_hierarchy = false,
+ const unsigned int my_rank_in = numbers::invalid_unsigned_int);
+
+
+ /**
+ * Construct a construction::Description. In contrast
+ * to the function above, this function is also responsible for creating
+ * a serial triangulation and for its partitioning (by calling the
+ * provided std::functions). Internally only selected processes (every
+ * n-th/each root of a group of size group_size) create a serial
+ * triangulation and the ConstructionData for all processes in its group,
+ * which is communicated.
+ *
+ * @note A reasonable group size is the size of a NUMA domain or the
+ * size of a compute node.
+ *
+ * @param serial_grid_generator A function, which creates a serial triangulation.
+ * @param serial_grid_partitioner A function, which can partition a serial
+ * triangulation, i.e., sets the sudomain_ids of the active cells.
+ * The function takes as the first argument a serial triangulation,
+ * as the second argument the MPI communicator, and as the third
+ * argument the group size.
+ * @param comm MPI communicator
+ * @param group_size The size of each group.
+ * @param construct_multilevel_hierarchy Construct multigrid levels.
+ * @return Description to be used to setup a Triangulation.
+ *
+ * @author Peter Munch, 2019
+ */
+ template <int dim, int spacedim = dim>
+ Description<dim, spacedim>
+ create_description_from_triangulation_in_groups(
+ const std::function<void(dealii::Triangulation<dim, spacedim> &)>
+ & serial_grid_generator,
+ const std::function<void(dealii::Triangulation<dim, spacedim> &,
+ const MPI_Comm,
+ const unsigned int)> &serial_grid_partitioner,
+ const MPI_Comm comm,
+ const int group_size = 1,
+ const bool construct_multilevel_hierarchy = false);
+
+ } // namespace Utilities
+
+
+
+ template <int dim>
+ template <class Archive>
+ void
+ CellData<dim>::serialize(Archive &ar, const unsigned int /*version*/)
+ {
+ ar &id;
+ ar &subdomain_id;
+ ar &level_subdomain_id;
+ ar &manifold_id;
+ if (dim >= 2)
+ ar &manifold_line_ids;
+ if (dim >= 3)
+ ar &manifold_quad_ids;
+ ar &boundary_ids;
+ }
+
+
+ template <int dim, int spacedim>
+ template <class Archive>
+ void
+ Description<dim, spacedim>::serialize(Archive &ar,
+ const unsigned int /*version*/)
+ {
+ ar &coarse_cells;
+ ar &coarse_cell_vertices;
+ ar &coarse_cell_index_to_coarse_cell_id;
+ ar &cell_infos;
+ ar &settings;
+ }
+
+
+
+ template <int dim>
+ bool
+ CellData<dim>::operator==(const CellData<dim> &other) const
+ {
+ if (this->id != other.id)
+ return false;
+ if (this->subdomain_id != other.subdomain_id)
+ return false;
+ if (this->level_subdomain_id != other.level_subdomain_id)
+ return false;
+ if (this->manifold_id != other.manifold_id)
+ return false;
+ if (dim >= 2 && this->manifold_line_ids != other.manifold_line_ids)
+ return false;
+ if (dim >= 3 && this->manifold_quad_ids != other.manifold_quad_ids)
+ return false;
+ if (this->boundary_ids != other.boundary_ids)
+ return false;
+
+ return true;
+ }
+
+
+
+ template <int dim, int spacedim>
+ bool
+ Description<dim, spacedim>::
+ operator==(const Description<dim, spacedim> &other) const
+ {
+ if (this->coarse_cells != other.coarse_cells)
+ return false;
+ if (this->coarse_cell_vertices != other.coarse_cell_vertices)
+ return false;
+ if (this->coarse_cell_index_to_coarse_cell_id !=
+ other.coarse_cell_index_to_coarse_cell_id)
+ return false;
+ if (this->cell_infos != other.cell_infos)
+ return false;
+ if (this->settings != other.settings)
+ return false;
+
+ return true;
+ }
+} // namespace TriangulationDescription
+
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
cell_weights.cc
cell_data_transfer.cc
fully_distributed_tria.cc
- fully_distributed_tria_util.cc
solution_transfer.cc
tria.cc
tria_base.cc
cell_weights.inst.in
cell_data_transfer.inst.in
fully_distributed_tria.inst.in
- fully_distributed_tria_util.inst.in
solution_transfer.inst.in
tria.inst.in
shared_tria.inst.in
#include <deal.II/base/mpi.h>
#include <deal.II/distributed/fully_distributed_tria.h>
-#include <deal.II/distributed/fully_distributed_tria_util.h>
#include <deal.II/grid/grid_tools.h>
template <int dim, int spacedim>
Triangulation<dim, spacedim>::Triangulation(MPI_Comm mpi_communicator)
: parallel::DistributedTriangulationBase<dim, spacedim>(mpi_communicator)
- , settings(Settings::default_setting)
+ , settings(TriangulationDescription::Settings::default_setting)
, partitioner([](dealii::Triangulation<dim, spacedim> &tria,
const unsigned int n_partitions) {
GridTools::partition_triangulation_zorder(n_partitions, tria);
template <int dim, int spacedim>
void
Triangulation<dim, spacedim>::create_triangulation(
- const ConstructionData<dim, spacedim> &construction_data)
+ const TriangulationDescription::Description<dim, spacedim>
+ &construction_data)
{
// check if the communicator of this parallel triangulation has been used
// to construct the ConstructionData
settings = construction_data.settings;
// set the smoothing properties
- if (settings & construct_multigrid_hierarchy)
+ if (settings &
+ TriangulationDescription::Settings::construct_multigrid_hierarchy)
this->set_mesh_smoothing(
static_cast<
typename dealii::Triangulation<dim, spacedim>::MeshSmoothing>(
for (auto i : coarse_cell_id_to_coarse_cell_index_vector)
this->coarse_cell_id_to_coarse_cell_index_vector.emplace_back(i);
- // 3) create coarse grid
- dealii::parallel::Triangulation<dim, spacedim>::create_triangulation(
- construction_data.coarse_cell_vertices,
- construction_data.coarse_cells,
- SubCellData());
-
- Assert(this->n_cells() ==
- this->coarse_cell_id_to_coarse_cell_index_vector.size(),
- ExcInternalError());
- Assert(this->n_cells() ==
- this->coarse_cell_index_to_coarse_cell_id_vector.size(),
- ExcInternalError());
+ // create locally-relevant
+ currently_processing_prepare_coarsening_and_refinement_for_internal_usage =
+ true;
+ currently_processing_create_triangulation_for_internal_usage = true;
+ dealii::Triangulation<dim, spacedim>::create_triangulation(
+ construction_data);
+ currently_processing_prepare_coarsening_and_refinement_for_internal_usage =
+ false;
+ currently_processing_create_triangulation_for_internal_usage = false;
// create a copy of cell_infos such that we can sort them
auto cell_infos = construction_data.cell_infos;
- // sort cell_infos on each level separately
- for (auto &cell_info : cell_infos)
- std::sort(cell_info.begin(),
- cell_info.end(),
- [&](CellData<dim> a, CellData<dim> b) {
- const CellId a_id(a.id);
- const CellId b_id(b.id);
-
- const auto a_coarse_cell_index =
- this->coarse_cell_id_to_coarse_cell_index(
- a_id.get_coarse_cell_id());
- const auto b_coarse_cell_index =
- this->coarse_cell_id_to_coarse_cell_index(
- b_id.get_coarse_cell_id());
-
- // according to their coarse-cell index and if that is
- // same according to their cell id (the result is that
- // cells on each level are sorted according to their
- // index on that level - what we need in the following
- // operations)
- if (a_coarse_cell_index != b_coarse_cell_index)
- return a_coarse_cell_index < b_coarse_cell_index;
- else
- return a_id < b_id;
- });
-
- // 4) create all levels via a sequence of refinements
- for (unsigned int level = 0; level < cell_infos.size(); ++level)
- {
- // a) set manifold ids here (because new vertices have to be
- // positioned correctly during each refinement step)
- {
- auto cell = this->begin(level);
- auto cell_info = cell_infos[level].begin();
- for (; cell_info != cell_infos[level].end(); ++cell_info)
- {
- while (cell_info->id !=
- cell->id().template to_binary<dim>())
- ++cell;
- if (spacedim == 3)
- for (unsigned int quad = 0;
- quad < GeometryInfo<spacedim>::quads_per_cell;
- ++quad)
- cell->quad(quad)->set_manifold_id(
- cell_info->manifold_quad_ids[quad]);
-
- if (spacedim >= 2)
- for (unsigned int line = 0;
- line < GeometryInfo<spacedim>::lines_per_cell;
- ++line)
- cell->line(line)->set_manifold_id(
- cell_info->manifold_line_ids[line]);
-
- cell->set_manifold_id(cell_info->manifold_id);
- }
- }
-
- // b) perform refinement on all levels but on the finest
- if (level + 1 != cell_infos.size())
- {
- // find cells that should have children and mark them for
- // refinement
- auto coarse_cell = this->begin(level);
- auto fine_cell_info = cell_infos[level + 1].begin();
-
- // loop over all cells on the next level
- for (; fine_cell_info != cell_infos[level + 1].end();
- ++fine_cell_info)
- {
- // find the parent of that cell
- while (!coarse_cell->id().is_parent_of(
- CellId(fine_cell_info->id)))
- ++coarse_cell;
-
- // set parent for refinement
- coarse_cell->set_refine_flag();
- }
-
- // execute refinement
- currently_processing_prepare_coarsening_and_refinement_for_internal_usage =
- true;
- dealii::Triangulation<dim, spacedim>::
- execute_coarsening_and_refinement();
- currently_processing_prepare_coarsening_and_refinement_for_internal_usage =
- false;
- }
- }
-
// 4a) set all cells artificial (and set the actual
// (level_)subdomain_ids in the next step)
for (auto cell = this->begin(); cell != this->end(); ++cell)
dealii::numbers::artificial_subdomain_id);
}
- // 4b) set actual (level_)subdomain_ids as well as boundary ids
+ // 4b) set actual (level_)subdomain_ids
for (unsigned int level = 0; level < cell_infos.size(); ++level)
{
auto cell = this->begin(level);
cell->set_subdomain_id(cell_info->subdomain_id);
// level subdomain id
- if (settings & construct_multigrid_hierarchy)
+ if (settings & TriangulationDescription::Settings::
+ construct_multigrid_hierarchy)
cell->set_level_subdomain_id(cell_info->level_subdomain_id);
-
- // boundary ids
- for (auto pair : cell_info->boundary_ids)
- {
- Assert(cell->at_boundary(pair.first),
- ExcMessage("Cell face is not on the boundary!"));
- cell->face(pair.first)->set_boundary_id(pair.second);
- }
}
}
}
}
// create construction data
- const auto construction_data =
- Utilities::create_construction_data_from_triangulation(
+ const auto construction_data = TriangulationDescription::Utilities::
+ create_description_from_triangulation(
*other_tria_ptr,
this->mpi_communicator,
this->is_multilevel_hierarchy_constructed());
Triangulation<dim, spacedim>::set_partitioner(
const std::function<void(dealii::Triangulation<dim, spacedim> &,
const unsigned int)> &partitioner,
- const Settings & settings)
+ const TriangulationDescription::Settings & settings)
{
this->partitioner = partitioner;
this->settings = settings;
{
parallel::Triangulation<dim, spacedim>::update_number_cache();
- if (settings & construct_multigrid_hierarchy)
+ if (settings &
+ TriangulationDescription::Settings::construct_multigrid_hierarchy)
parallel::Triangulation<dim, spacedim>::fill_level_ghost_owners();
}
bool
Triangulation<dim, spacedim>::is_multilevel_hierarchy_constructed() const
{
- return (settings & construct_multigrid_hierarchy);
+ return (
+ settings &
+ TriangulationDescription::Settings::construct_multigrid_hierarchy);
}
+ template <int dim, int spacedim>
+ void
+ Triangulation<dim, spacedim>::create_triangulation(
+ const TriangulationDescription::Description<dim, spacedim>
+ &construction_data)
+ {
+ (void)construction_data;
+
+ Assert(false, ExcInternalError());
+ }
+
+
+
template <int dim, int spacedim>
void
Triangulation<dim, spacedim>::copy_triangulation(
}
+
+ template <int dim, int spacedim>
+ void
+ Triangulation<dim, spacedim>::create_triangulation(
+ const TriangulationDescription::Description<dim, spacedim>
+ &construction_data)
+ {
+ (void)construction_data;
+
+ Assert(false, ExcInternalError());
+ }
+
+
+
// This anonymous namespace contains utility for
// the function Triangulation::communicate_locally_moved_vertices
namespace CommunicateLocallyMovedVertices
manifold_lib.cc
persistent_tria.cc
tria_accessor.cc
+ tria_description.cc
tria_faces.cc
tria_levels.cc
tria_objects.cc
manifold.inst.in
manifold_lib.inst.in
tria_accessor.inst.in
+ tria_description.inst.in
tria.inst.in
tria_objects.inst.in
)
+template <int dim, int spacedim>
+void
+PersistentTriangulation<dim, spacedim>::create_triangulation(
+ const TriangulationDescription::Description<dim, spacedim> &construction_data)
+{
+ (void)construction_data;
+
+ Assert(false, ExcInternalError());
+}
+
+
+
template <int dim, int spacedim>
void
PersistentTriangulation<dim, spacedim>::create_triangulation_compatibility(
+template <int dim, int spacedim>
+void
+Triangulation<dim, spacedim>::create_triangulation(
+ const TriangulationDescription::Description<dim, spacedim> &construction_data)
+{
+ // 1) create coarse grid
+ create_triangulation(construction_data.coarse_cell_vertices,
+ construction_data.coarse_cells,
+ SubCellData());
+
+ // create a copy of cell_infos such that we can sort them
+ auto cell_infos = construction_data.cell_infos;
+
+ // sort cell_infos on each level separately
+ for (auto &cell_info : cell_infos)
+ std::sort(
+ cell_info.begin(),
+ cell_info.end(),
+ [&](TriangulationDescription::CellData<dim> a,
+ TriangulationDescription::CellData<dim> b) {
+ const CellId a_id(a.id);
+ const CellId b_id(b.id);
+
+ const auto a_coarse_cell_index =
+ this->coarse_cell_id_to_coarse_cell_index(a_id.get_coarse_cell_id());
+ const auto b_coarse_cell_index =
+ this->coarse_cell_id_to_coarse_cell_index(b_id.get_coarse_cell_id());
+
+ // according to their coarse-cell index and if that is
+ // same according to their cell id (the result is that
+ // cells on each level are sorted according to their
+ // index on that level - what we need in the following
+ // operations)
+ if (a_coarse_cell_index != b_coarse_cell_index)
+ return a_coarse_cell_index < b_coarse_cell_index;
+ else
+ return a_id < b_id;
+ });
+
+ // 2) create all levels via a sequence of refinements
+ for (unsigned int level = 0; level < cell_infos.size(); ++level)
+ {
+ // a) set manifold ids here (because new vertices have to be
+ // positioned correctly during each refinement step)
+ {
+ auto cell = this->begin(level);
+ auto cell_info = cell_infos[level].begin();
+ for (; cell_info != cell_infos[level].end(); ++cell_info)
+ {
+ while (cell_info->id != cell->id().template to_binary<dim>())
+ ++cell;
+ if (spacedim == 3)
+ for (unsigned int quad = 0;
+ quad < GeometryInfo<spacedim>::quads_per_cell;
+ ++quad)
+ cell->quad(quad)->set_manifold_id(
+ cell_info->manifold_quad_ids[quad]);
+
+ if (spacedim >= 2)
+ for (unsigned int line = 0;
+ line < GeometryInfo<spacedim>::lines_per_cell;
+ ++line)
+ cell->line(line)->set_manifold_id(
+ cell_info->manifold_line_ids[line]);
+
+ cell->set_manifold_id(cell_info->manifold_id);
+ }
+ }
+
+ // b) perform refinement on all levels but on the finest
+ if (level + 1 != cell_infos.size())
+ {
+ // find cells that should have children and mark them for
+ // refinement
+ auto coarse_cell = this->begin(level);
+ auto fine_cell_info = cell_infos[level + 1].begin();
+
+ // loop over all cells on the next level
+ for (; fine_cell_info != cell_infos[level + 1].end();
+ ++fine_cell_info)
+ {
+ // find the parent of that cell
+ while (
+ !coarse_cell->id().is_parent_of(CellId(fine_cell_info->id)))
+ ++coarse_cell;
+
+ // set parent for refinement
+ coarse_cell->set_refine_flag();
+ }
+
+ // execute refinement
+ dealii::Triangulation<dim,
+ spacedim>::execute_coarsening_and_refinement();
+ }
+ }
+
+ // 3) set boundary ids
+ for (unsigned int level = 0; level < cell_infos.size(); ++level)
+ {
+ auto cell = this->begin(level);
+ auto cell_info = cell_infos[level].begin();
+ for (; cell_info != cell_infos[level].end(); ++cell_info)
+ {
+ // find cell that has the correct cell
+ while (cell_info->id != cell->id().template to_binary<dim>())
+ ++cell;
+
+ // boundary ids
+ for (auto pair : cell_info->boundary_ids)
+ {
+ Assert(cell->at_boundary(pair.first),
+ ExcMessage("Cell face is not on the boundary!"));
+ cell->face(pair.first)->set_boundary_id(pair.second);
+ }
+ }
+ }
+}
+
+
template <int dim, int spacedim>
void
Triangulation<dim, spacedim>::flip_all_direction_flags()
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2019 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/geometry_info.h>
+#include <deal.II/base/mpi.h>
+
+#include <deal.II/distributed/tria.h>
+
+#include <deal.II/dofs/dof_accessor.h>
+#include <deal.II/dofs/dof_handler.h>
+
+#include <deal.II/grid/grid_tools.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_description.h>
+
+DEAL_II_NAMESPACE_OPEN
+
+namespace TriangulationDescription
+{
+ namespace Utilities
+ {
+ namespace
+ {
+ /**
+ * Set the user_flag of a cell and of all its parent cells.
+ */
+ template <int dim, int spacedim>
+ void
+ set_user_flag_reverse(TriaIterator<CellAccessor<dim, spacedim>> cell)
+ {
+ cell->set_user_flag();
+ if (cell->level() != 0)
+ set_user_flag_reverse(cell->parent());
+ }
+
+
+ /**
+ * Convert the binary representation of a CellId to coarse-cell id as
+ * if the finest level were the coarsest level ("level coarse-grid id").
+ */
+ template <int dim>
+ types::coarse_cell_id
+ convert_cell_id_binary_type_to_level_coarse_cell_id(
+ const typename CellId::binary_type &binary_representation)
+ {
+ // exploiting the structure of CellId::binary_type
+ // see also the documentation of CellId
+
+ // actual coarse-grid id
+ const unsigned int coarse_cell_id = binary_representation[0];
+ const unsigned int n_child_indices = binary_representation[1] >> 2;
+
+ const unsigned int children_per_value =
+ sizeof(CellId::binary_type::value_type) * 8 / dim;
+ unsigned int child_level = 0;
+ unsigned int binary_entry = 2;
+
+ // path to the get to the cell
+ std::vector<unsigned int> cell_indices;
+ while (child_level < n_child_indices)
+ {
+ Assert(binary_entry < binary_representation.size(),
+ ExcInternalError());
+
+ for (unsigned int j = 0; j < children_per_value; ++j)
+ {
+ unsigned int cell_index =
+ (((binary_representation[binary_entry] >> (j * dim))) &
+ (GeometryInfo<dim>::max_children_per_cell - 1));
+ cell_indices.push_back(cell_index);
+ ++child_level;
+ if (child_level == n_child_indices)
+ break;
+ }
+ ++binary_entry;
+ }
+
+ // compute new coarse-grid id: c_{i+1} = c_{i}*2^dim + q;
+ types::coarse_cell_id level_coarse_cell_id = coarse_cell_id;
+ for (auto i : cell_indices)
+ level_coarse_cell_id =
+ level_coarse_cell_id * GeometryInfo<dim>::max_children_per_cell + i;
+
+ return level_coarse_cell_id;
+ }
+ } // namespace
+
+
+ template <int dim, int spacedim>
+ Description<dim, spacedim>
+ create_description_from_triangulation(
+ const dealii::Triangulation<dim, spacedim> &tria,
+ const MPI_Comm comm,
+ const bool construct_multilevel_hierarchy,
+ const unsigned int my_rank_in)
+ {
+ if (auto tria_pdt = dynamic_cast<
+ const parallel::distributed::Triangulation<dim, spacedim> *>(&tria))
+ AssertThrow(comm == tria_pdt->get_communicator(),
+ ExcMessage("MPI communicators do not match."));
+
+ // First, figure out for what rank we are supposed to build the
+ // ConstructionData object
+ unsigned int my_rank = my_rank_in;
+ AssertThrow(my_rank == numbers::invalid_unsigned_int ||
+ my_rank < dealii::Utilities::MPI::n_mpi_processes(comm),
+ ExcMessage(
+ "Rank has to be smaller than available processes."));
+
+ if (auto tria_pdt = dynamic_cast<
+ const parallel::distributed::Triangulation<dim, spacedim> *>(&tria))
+ {
+ AssertThrow(
+ my_rank == numbers::invalid_unsigned_int ||
+ my_rank == dealii::Utilities::MPI::this_mpi_process(comm),
+ ExcMessage(
+ "If parallel::distributed::Triangulation as source triangulation, my_rank has to equal global rank."));
+
+ my_rank = dealii::Utilities::MPI::this_mpi_process(comm);
+ }
+ else if (auto tria_serial =
+ dynamic_cast<const dealii::Triangulation<dim, spacedim> *>(
+ &tria))
+ {
+ if (my_rank == numbers::invalid_unsigned_int)
+ my_rank = dealii::Utilities::MPI::this_mpi_process(comm);
+ }
+ else
+ {
+ AssertThrow(
+ false, ExcMessage("This type of triangulation is not supported!"));
+ }
+
+ Description<dim, spacedim> construction_data;
+
+ // store the communicator
+ construction_data.comm = comm;
+
+
+ std::map<unsigned int, std::vector<unsigned int>>
+ coinciding_vertex_groups;
+ std::map<unsigned int, unsigned int> vertex_to_coinciding_vertex_group;
+
+ GridTools::collect_coinciding_vertices(tria,
+ coinciding_vertex_groups,
+ vertex_to_coinciding_vertex_group);
+
+ // helper function, which collects all vertices belonging to a cell
+ // (also taking into account periodicity)
+ auto add_vertices_of_cell_to_vertices_owned_by_locally_owned_cells =
+ [coinciding_vertex_groups, vertex_to_coinciding_vertex_group](
+ TriaIterator<CellAccessor<dim, spacedim>> &cell,
+ std::vector<bool> &vertices_owned_by_locally_owned_cells) {
+ // add local vertices
+ for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell;
+ ++v)
+ {
+ vertices_owned_by_locally_owned_cells[cell->vertex_index(v)] =
+ true;
+ const auto coinciding_vertex_group =
+ vertex_to_coinciding_vertex_group.find(cell->vertex_index(v));
+ if (coinciding_vertex_group !=
+ vertex_to_coinciding_vertex_group.end())
+ for (const auto &co_vertex : coinciding_vertex_groups.at(
+ coinciding_vertex_group->second))
+ vertices_owned_by_locally_owned_cells[co_vertex] = true;
+ }
+ };
+
+ // check if multilevel hierarchy should be constructed
+ if (construct_multilevel_hierarchy == false)
+ {
+ AssertThrow(
+ tria.has_hanging_nodes() == false,
+ ExcMessage(
+ "Hanging nodes are only supported if multilevel hierarchy is constructed!"));
+
+ construction_data.settings =
+ TriangulationDescription::Settings::default_setting;
+
+ // 1) collect vertices of active locally owned cells
+ std::vector<bool> vertices_owned_by_locally_owned_cells(
+ tria.n_vertices());
+ for (auto cell : tria.cell_iterators())
+ if (cell->is_active() && cell->subdomain_id() == my_rank)
+ add_vertices_of_cell_to_vertices_owned_by_locally_owned_cells(
+ cell, vertices_owned_by_locally_owned_cells);
+
+ // helper function to determine if cell is locally relevant
+ // (i.e. a cell which is connected to a vertex via a locally owned
+ // active cell)
+ auto is_locally_relevant = [&](
+ TriaIterator<CellAccessor<dim, spacedim>>
+ &cell) {
+ for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell;
+ ++v)
+ if (vertices_owned_by_locally_owned_cells[cell->vertex_index(v)])
+ return true;
+ return false;
+ };
+
+ // 2) process all local and ghost cells: set up needed data
+ // structures and collect all locally relevant vertices
+ // for second sweep
+ std::map<unsigned int, unsigned int> vertices_locally_relevant;
+ construction_data.cell_infos.resize(1);
+
+ for (auto cell : tria.cell_iterators())
+ if (cell->is_active() && is_locally_relevant(cell))
+ {
+ // to be filled
+ CellData<dim> cell_info;
+
+ // a) extract cell definition (with old numbering of
+ // vertices)
+ dealii::CellData<dim> cell_data;
+ cell_data.material_id = cell->material_id();
+ cell_data.manifold_id = cell->manifold_id();
+ for (unsigned int v = 0;
+ v < GeometryInfo<dim>::vertices_per_cell;
+ ++v)
+ cell_data.vertices[v] = cell->vertex_index(v);
+ construction_data.coarse_cells.push_back(cell_data);
+
+ // b) save indices of each vertex of this cell
+ for (unsigned int v = 0;
+ v < GeometryInfo<dim>::vertices_per_cell;
+ ++v)
+ vertices_locally_relevant[cell->vertex_index(v)] =
+ numbers::invalid_unsigned_int;
+
+ // c) save boundary_ids of each face of this cell
+ for (unsigned int f = 0; f < GeometryInfo<dim>::faces_per_cell;
+ ++f)
+ {
+ types::boundary_id boundary_ind =
+ cell->face(f)->boundary_id();
+ if (boundary_ind != numbers::internal_face_boundary_id)
+ cell_info.boundary_ids.emplace_back(f, boundary_ind);
+ }
+
+ // d) compute a new coarse-cell id (by ignoring all parent
+ // level)
+ types::coarse_cell_id new_coarse_cell_id =
+ convert_cell_id_binary_type_to_level_coarse_cell_id<dim>(
+ cell->id().template to_binary<dim>());
+
+ // store the coarse cell id
+ cell_info.id = CellId(new_coarse_cell_id, 0, nullptr)
+ .template to_binary<dim>();
+
+ // save coarse_cell_index -> coarse_cell_id mapping
+ construction_data.coarse_cell_index_to_coarse_cell_id.push_back(
+ new_coarse_cell_id);
+
+ // e) store manifold id of cell
+ cell_info.manifold_id = cell->manifold_id();
+
+ // ... of lines
+ if (dim >= 2)
+ for (unsigned int line = 0;
+ line < GeometryInfo<dim>::lines_per_cell;
+ ++line)
+ cell_info.manifold_line_ids[line] =
+ cell->line(line)->manifold_id();
+
+ // ... of quads
+ if (dim == 3)
+ for (unsigned int quad = 0;
+ quad < GeometryInfo<dim>::quads_per_cell;
+ ++quad)
+ cell_info.manifold_quad_ids[quad] =
+ cell->quad(quad)->manifold_id();
+
+ // f) store subdomain_id
+ cell_info.subdomain_id = cell->subdomain_id();
+
+ // g) store invalid level_subdomain_id (since multilevel
+ // hierarchy is not constructed)
+ cell_info.level_subdomain_id = numbers::invalid_subdomain_id;
+
+ construction_data.cell_infos[0].emplace_back(cell_info);
+ }
+
+ // 3) enumerate locally relevant vertices
+ unsigned int vertex_counter = 0;
+ for (auto &vertex : vertices_locally_relevant)
+ {
+ construction_data.coarse_cell_vertices.push_back(
+ tria.get_vertices()[vertex.first]);
+ vertex.second = vertex_counter++;
+ }
+
+ // 4) correct vertices of cells (make them local)
+ for (auto &cell : construction_data.coarse_cells)
+ for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell;
+ ++v)
+ cell.vertices[v] = vertices_locally_relevant[cell.vertices[v]];
+ }
+ else
+ {
+ construction_data.settings =
+ TriangulationDescription::Settings::construct_multigrid_hierarchy;
+
+ // 1) collect locally relevant cells (set user_flag)
+ std::vector<bool> old_user_flags;
+ tria.save_user_flags(old_user_flags);
+
+ // 1a) clear user_flags
+ const_cast<dealii::Triangulation<dim, spacedim> &>(tria)
+ .clear_user_flags();
+
+ // 1b) loop over levels (from fine to coarse) and mark on each level
+ // the locally relevant cells
+ for (unsigned int level =
+ tria.get_triangulation().n_global_levels() - 1;
+ level != numbers::invalid_unsigned_int;
+ level--)
+ {
+ // collect vertices connected to a (on any level) locally owned
+ // cell
+ std::vector<bool> vertices_owned_by_locally_owned_cells_on_level(
+ tria.n_vertices());
+ for (auto cell : tria.cell_iterators_on_level(level))
+ if (cell->level_subdomain_id() == my_rank ||
+ (cell->active() && cell->subdomain_id() == my_rank))
+ add_vertices_of_cell_to_vertices_owned_by_locally_owned_cells(
+ cell, vertices_owned_by_locally_owned_cells_on_level);
+
+ for (auto cell : tria.active_cell_iterators())
+ if (cell->subdomain_id() == my_rank)
+ add_vertices_of_cell_to_vertices_owned_by_locally_owned_cells(
+ cell, vertices_owned_by_locally_owned_cells_on_level);
+
+ // helper function to determine if cell is locally relevant
+ // (i.e. a cell which is connected to a vertex via a locally
+ // owned cell)
+ auto is_locally_relevant_on_level =
+ [&](TriaIterator<CellAccessor<dim, spacedim>> &cell) {
+ for (unsigned int v = 0;
+ v < GeometryInfo<dim>::vertices_per_cell;
+ ++v)
+ if (vertices_owned_by_locally_owned_cells_on_level
+ [cell->vertex_index(v)])
+ return true;
+ return false;
+ };
+
+ // mark all locally relevant cells
+ for (auto cell : tria.cell_iterators_on_level(level))
+ if (is_locally_relevant_on_level(cell))
+ set_user_flag_reverse(cell);
+ }
+
+ // 2) set_up coarse-grid triangulation
+ {
+ std::map<unsigned int, unsigned int> vertices_locally_relevant;
+
+ // a) loop over all cells
+ for (auto cell : tria.cell_iterators_on_level(0))
+ {
+ if (!cell->user_flag_set())
+ continue;
+
+ // extract cell definition (with old numbering of vertices)
+ dealii::CellData<dim> cell_data;
+ cell_data.material_id = cell->material_id();
+ cell_data.manifold_id = cell->manifold_id();
+ for (unsigned int v = 0;
+ v < GeometryInfo<dim>::vertices_per_cell;
+ ++v)
+ cell_data.vertices[v] = cell->vertex_index(v);
+ construction_data.coarse_cells.push_back(cell_data);
+
+ // save indices of each vertex of this cell
+ for (unsigned int v = 0;
+ v < GeometryInfo<dim>::vertices_per_cell;
+ ++v)
+ vertices_locally_relevant[cell->vertex_index(v)] =
+ numbers::invalid_unsigned_int;
+
+ // save translation for corase grid: lid -> gid
+ construction_data.coarse_cell_index_to_coarse_cell_id.push_back(
+ cell->id().get_coarse_cell_id());
+ }
+
+ // b) enumerate locally relevant vertices
+ unsigned int vertex_counter = 0;
+ for (auto &vertex : vertices_locally_relevant)
+ {
+ construction_data.coarse_cell_vertices.push_back(
+ tria.get_vertices()[vertex.first]);
+ vertex.second = vertex_counter++;
+ }
+
+ // c) correct vertices of cells (make them local)
+ for (auto &cell : construction_data.coarse_cells)
+ for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell;
+ ++v)
+ cell.vertices[v] = vertices_locally_relevant[cell.vertices[v]];
+ }
+
+
+ // 3) collect info of each cell
+ construction_data.cell_infos.resize(
+ tria.get_triangulation().n_global_levels());
+
+ // collect local vertices on active level
+ std::vector<bool> vertices_owned_by_locally_owned_active_cells(
+ tria.n_vertices());
+ for (auto cell : tria.active_cell_iterators())
+ if (cell->subdomain_id() == my_rank)
+ add_vertices_of_cell_to_vertices_owned_by_locally_owned_cells(
+ cell, vertices_owned_by_locally_owned_active_cells);
+
+ // helper function to determine if cell is locally relevant
+ // on active level
+ auto is_locally_relevant_on_active_level =
+ [&](TriaIterator<CellAccessor<dim, spacedim>> &cell) {
+ if (cell->active())
+ for (unsigned int v = 0;
+ v < GeometryInfo<dim>::vertices_per_cell;
+ ++v)
+ if (vertices_owned_by_locally_owned_active_cells
+ [cell->vertex_index(v)])
+ return true;
+ return false;
+ };
+
+ for (unsigned int level = 0;
+ level < tria.get_triangulation().n_global_levels();
+ ++level)
+ {
+ // collect local vertices on level
+ std::vector<bool> vertices_owned_by_locally_owned_cells_on_level(
+ tria.n_vertices());
+ for (auto cell : tria.cell_iterators_on_level(level))
+ if (cell->level_subdomain_id() == my_rank ||
+ (cell->active() && cell->subdomain_id() == my_rank))
+ add_vertices_of_cell_to_vertices_owned_by_locally_owned_cells(
+ cell, vertices_owned_by_locally_owned_cells_on_level);
+
+ // helper function to determine if cell is locally relevant
+ // on level
+ auto is_locally_relevant_on_level =
+ [&](TriaIterator<CellAccessor<dim, spacedim>> &cell) {
+ for (unsigned int v = 0;
+ v < GeometryInfo<dim>::vertices_per_cell;
+ ++v)
+ if (vertices_owned_by_locally_owned_cells_on_level
+ [cell->vertex_index(v)])
+ return true;
+ return false;
+ };
+
+ auto &level_cell_infos = construction_data.cell_infos[level];
+ for (auto cell : tria.cell_iterators_on_level(level))
+ {
+ // check if cell is locally relevant
+ if (!(cell->user_flag_set()))
+ continue;
+
+ CellData<dim> cell_info;
+
+ // save coarse-cell id
+ cell_info.id = cell->id().template to_binary<dim>();
+
+ // save boundary_ids of each face of this cell
+ for (unsigned int f = 0;
+ f < GeometryInfo<dim>::faces_per_cell;
+ ++f)
+ {
+ types::boundary_id boundary_ind =
+ cell->face(f)->boundary_id();
+ if (boundary_ind != numbers::internal_face_boundary_id)
+ cell_info.boundary_ids.emplace_back(f, boundary_ind);
+ }
+
+ // save manifold id
+ {
+ // ... of cell
+ cell_info.manifold_id = cell->manifold_id();
+
+ // ... of lines
+ if (dim >= 2)
+ for (unsigned int line = 0;
+ line < GeometryInfo<dim>::lines_per_cell;
+ ++line)
+ cell_info.manifold_line_ids[line] =
+ cell->line(line)->manifold_id();
+
+ // ... of quads
+ if (dim == 3)
+ for (unsigned int quad = 0;
+ quad < GeometryInfo<dim>::quads_per_cell;
+ ++quad)
+ cell_info.manifold_quad_ids[quad] =
+ cell->quad(quad)->manifold_id();
+ }
+
+ // subdomain and level subdomain id
+ cell_info.subdomain_id = numbers::artificial_subdomain_id;
+ cell_info.level_subdomain_id =
+ numbers::artificial_subdomain_id;
+
+ if (is_locally_relevant_on_active_level(cell))
+ {
+ cell_info.level_subdomain_id = cell->level_subdomain_id();
+ cell_info.subdomain_id = cell->subdomain_id();
+ }
+ else if (is_locally_relevant_on_level(cell))
+ {
+ cell_info.level_subdomain_id = cell->level_subdomain_id();
+ }
+ // else: cell is locally relevant but an artificial cell
+
+ level_cell_infos.emplace_back(cell_info);
+ }
+ }
+
+ const_cast<dealii::Triangulation<dim, spacedim> &>(tria)
+ .load_user_flags(old_user_flags);
+ }
+
+ return construction_data;
+ }
+
+
+
+ template <int dim, int spacedim>
+ Description<dim, spacedim>
+ create_description_from_triangulation_in_groups(
+ const std::function<void(dealii::Triangulation<dim, spacedim> &)>
+ & serial_grid_generator,
+ const std::function<void(dealii::Triangulation<dim, spacedim> &,
+ const MPI_Comm,
+ const unsigned int)> &serial_grid_partitioner,
+ const MPI_Comm comm,
+ const int group_size,
+ const bool construct_multilevel_hierarchy)
+ {
+#ifndef DEAL_II_WITH_MPI
+ (void)serial_grid_generator;
+ (void)serial_grid_partitioner;
+ (void)comm;
+ (void)group_size;
+ (void)construct_multilevel_hierarchy;
+
+ return Description<dim, spacedim>();
+#else
+ const unsigned int my_rank =
+ dealii::Utilities::MPI::this_mpi_process(comm);
+ const unsigned int group_root = (my_rank / group_size) * group_size;
+
+ const int mpi_tag =
+ dealii::Utilities::MPI::internal::Tags::fully_distributed_create;
+
+ // check if process is root of the group
+ if (my_rank == group_root)
+ {
+ // Step 1: create serial triangulation
+ dealii::Triangulation<dim, spacedim> tria(
+ construct_multilevel_hierarchy ?
+ dealii::Triangulation<dim, spacedim>::none :
+ dealii::Triangulation<dim, spacedim>::
+ limit_level_difference_at_vertices);
+ serial_grid_generator(tria);
+
+ // Step 2: partition active cells and ...
+ serial_grid_partitioner(tria, comm, group_size);
+
+ // ... cells on the levels if multigrid is required
+ if (construct_multilevel_hierarchy)
+ GridTools::partition_multigrid_levels(tria);
+
+ const unsigned int end_group =
+ std::min(group_root + group_size,
+ dealii::Utilities::MPI::n_mpi_processes(comm));
+
+ // 3) create ConstructionData for the other processes in group
+ for (unsigned int other_rank = group_root + 1; other_rank < end_group;
+ other_rank++)
+ {
+ // 3a) create construction data for other ranks
+ const auto construction_data =
+ create_description_from_triangulation(
+ tria, comm, construct_multilevel_hierarchy, other_rank);
+ // 3b) pack
+ std::vector<char> buffer;
+ dealii::Utilities::pack(construction_data, buffer, false);
+
+ // 3c) send ConstructionData
+ const auto ierr = MPI_Send(buffer.data(),
+ buffer.size(),
+ MPI_CHAR,
+ other_rank,
+ mpi_tag,
+ comm);
+ AssertThrowMPI(ierr);
+ }
+
+ // 4) create ConstructionData for this process (root of group)
+ return create_description_from_triangulation(
+ tria, comm, construct_multilevel_hierarchy, my_rank);
+ }
+ else
+ {
+ // 3a) recv packed ConstructionData from group-root process
+ // (counter-part of 3c of root process)
+ MPI_Status status;
+ auto ierr = MPI_Probe(group_root, mpi_tag, comm, &status);
+ AssertThrowMPI(ierr);
+
+ int len;
+ MPI_Get_count(&status, MPI_CHAR, &len);
+
+ std::vector<char> buf(len);
+ ierr = MPI_Recv(buf.data(),
+ len,
+ MPI_CHAR,
+ status.MPI_SOURCE,
+ status.MPI_TAG,
+ comm,
+ &status);
+ AssertThrowMPI(ierr);
+
+ // 3b) unpack ConstructionData (counter-part of 3b of root process)
+ auto construction_data =
+ dealii::Utilities::template unpack<Description<dim, spacedim>>(
+ buf, false);
+
+ // WARNING: serialization cannot handle the MPI communicator
+ // which is the reason why we have to set it here explicitly
+ construction_data.comm = comm;
+
+ return construction_data;
+ }
+#endif
+ }
+
+ } // namespace Utilities
+} // namespace TriangulationDescription
+
+
+
+/*-------------- Explicit Instantiations -------------------------------*/
+#include "tria_description.inst"
+
+
+DEAL_II_NAMESPACE_CLOSE
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2010 - 2018 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 : DIMENSIONS)
+ {
+ namespace TriangulationDescription
+ \{
+ namespace Utilities
+ \{
+#if deal_II_dimension <= deal_II_space_dimension
+ template Description<deal_II_dimension, deal_II_space_dimension>
+ create_description_from_triangulation(
+ const dealii::Triangulation<deal_II_dimension,
+ deal_II_space_dimension> &tria,
+ const MPI_Comm comm,
+ const bool construct_multilevel_hierarchy,
+ const unsigned int my_rank_in);
+
+ template Description<deal_II_dimension, deal_II_space_dimension>
+ create_description_from_triangulation_in_groups(
+ const std::function<void(
+ dealii::Triangulation<deal_II_dimension, deal_II_space_dimension>
+ &)> & serial_grid_generator,
+ const std::function<void(
+ dealii::Triangulation<deal_II_dimension, deal_II_space_dimension> &,
+ const MPI_Comm,
+ const unsigned int)> &serial_grid_partitioner,
+ const MPI_Comm comm,
+ const int group_size,
+ const bool construct_multilevel_hierarchy);
+#endif
+ \}
+ \}
+ }
#include <deal.II/base/mpi.h>
#include <deal.II/distributed/fully_distributed_tria.h>
-#include <deal.II/distributed/fully_distributed_tria_util.h>
#include <deal.II/distributed/shared_tria.h>
#include <deal.II/distributed/tria.h>
#include <deal.II/grid/grid_out.h>
#include <deal.II/grid/grid_tools.h>
#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_description.h>
#include "./tests.h"
parallel::fullydistributed::Triangulation<dim> tria_pft(comm);
// extract relevant information form serial triangulation
- auto construction_data = parallel::fullydistributed::Utilities::
- create_construction_data_from_triangulation(tria_pdt, comm);
+ auto construction_data =
+ TriangulationDescription::Utilities::create_description_from_triangulation(
+ tria_pdt, comm);
// actually create triangulation
tria_pft.create_triangulation(construction_data);
#include <deal.II/base/mpi.h>
#include <deal.II/distributed/fully_distributed_tria.h>
-#include <deal.II/distributed/fully_distributed_tria_util.h>
#include <deal.II/distributed/shared_tria.h>
#include <deal.II/distributed/tria.h>
#include <deal.II/grid/grid_out.h>
#include <deal.II/grid/grid_tools.h>
#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_description.h>
#include "./tests.h"
parallel::fullydistributed::Triangulation<dim> tria_pft(comm);
// extract relevant information form pdt
- auto construction_data = parallel::fullydistributed::Utilities::
- create_construction_data_from_triangulation(tria_pdt, comm, true);
+ auto construction_data =
+ TriangulationDescription::Utilities::create_description_from_triangulation(
+ tria_pdt, comm, true);
// actually create triangulation
tria_pft.create_triangulation(construction_data);
#include <deal.II/base/mpi.h>
#include <deal.II/distributed/fully_distributed_tria.h>
-#include <deal.II/distributed/fully_distributed_tria_util.h>
#include <deal.II/distributed/shared_tria.h>
#include <deal.II/distributed/tria.h>
#include <deal.II/grid/grid_out.h>
#include <deal.II/grid/grid_tools.h>
#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_description.h>
#include "./tests.h"
parallel::fullydistributed::Triangulation<dim> tria_pft(comm);
// extract relevant information form serial triangulation
- auto construction_data = parallel::fullydistributed::Utilities::
- create_construction_data_from_triangulation(basetria, comm);
+ auto construction_data =
+ TriangulationDescription::Utilities::create_description_from_triangulation(
+ basetria, comm);
// actually create triangulation
tria_pft.create_triangulation(construction_data);
#include <deal.II/base/mpi.h>
#include <deal.II/distributed/fully_distributed_tria.h>
-#include <deal.II/distributed/fully_distributed_tria_util.h>
#include <deal.II/distributed/shared_tria.h>
#include <deal.II/distributed/tria.h>
#include <deal.II/grid/grid_out.h>
#include <deal.II/grid/grid_tools.h>
#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_description.h>
#include "./tests.h"
parallel::fullydistributed::Triangulation<dim> tria_pft(comm);
// extract relevant information form serial triangulation
- auto construction_data = parallel::fullydistributed::Utilities::
- create_construction_data_from_triangulation(basetria, comm, true);
+ auto construction_data =
+ TriangulationDescription::Utilities::create_description_from_triangulation(
+ basetria, comm, true);
// actually create triangulation
tria_pft.create_triangulation(construction_data);
#include <deal.II/base/mpi.h>
#include <deal.II/distributed/fully_distributed_tria.h>
-#include <deal.II/distributed/fully_distributed_tria_util.h>
#include <deal.II/distributed/shared_tria.h>
#include <deal.II/distributed/tria.h>
#include <deal.II/grid/grid_tools.h>
#include <deal.II/grid/manifold_lib.h>
#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_description.h>
#include "./tests.h"
tria_pft.set_manifold(0, SphericalManifold<dim>(center));
// extract relevant information form pdt
- auto construction_data = parallel::fullydistributed::Utilities::
- create_construction_data_from_triangulation(basetria, comm, true);
+ auto construction_data =
+ TriangulationDescription::Utilities::create_description_from_triangulation(
+ basetria, comm, true);
// actually create triangulation
tria_pft.create_triangulation(construction_data);
#include <deal.II/base/mpi.h>
#include <deal.II/distributed/fully_distributed_tria.h>
-#include <deal.II/distributed/fully_distributed_tria_util.h>
#include <deal.II/distributed/shared_tria.h>
#include <deal.II/distributed/tria.h>
#include <deal.II/grid/grid_out.h>
#include <deal.II/grid/grid_tools.h>
#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_description.h>
#include "./tests.h"
parallel::fullydistributed::Triangulation<dim> tria_pft(comm);
// extract relevant information form serial triangulation
- auto construction_data = parallel::fullydistributed::Utilities::
- create_construction_data_from_triangulation(basetria, comm);
+ auto construction_data =
+ TriangulationDescription::Utilities::create_description_from_triangulation(
+ basetria, comm);
// actually create triangulation
tria_pft.create_triangulation(construction_data);
#include <deal.II/base/mpi.h>
#include <deal.II/distributed/fully_distributed_tria.h>
-#include <deal.II/distributed/fully_distributed_tria_util.h>
#include <deal.II/distributed/shared_tria.h>
#include <deal.II/distributed/tria.h>
#include <deal.II/grid/grid_out.h>
#include <deal.II/grid/grid_tools.h>
#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_description.h>
#include "./tests.h"
parallel::fullydistributed::Triangulation<dim> tria_pft(comm);
// extract relevant information form serial triangulation
- auto construction_data = parallel::fullydistributed::Utilities::
- create_construction_data_from_triangulation(basetria, comm, true);
+ auto construction_data =
+ TriangulationDescription::Utilities::create_description_from_triangulation(
+ basetria, comm, true);
// actually create triangulation
tria_pft.create_triangulation(construction_data);
#include <deal.II/base/mpi.h>
#include <deal.II/distributed/fully_distributed_tria.h>
-#include <deal.II/distributed/fully_distributed_tria_util.h>
#include <deal.II/distributed/shared_tria.h>
#include <deal.II/distributed/tria.h>
#include <deal.II/grid/grid_out.h>
#include <deal.II/grid/grid_tools.h>
#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_description.h>
#include <deal.II/matrix_free/matrix_free.h>
parallel::fullydistributed::Triangulation<dim> tria_pft(comm);
// extract relevant information form serial triangulation
- auto construction_data = parallel::fullydistributed::Utilities::
- create_construction_data_from_triangulation(basetria, comm);
+ auto construction_data =
+ TriangulationDescription::Utilities::create_description_from_triangulation(
+ basetria, comm);
// actually create triangulation
tria_pft.create_triangulation(construction_data);
#include <deal.II/base/mpi.h>
#include <deal.II/distributed/fully_distributed_tria.h>
-#include <deal.II/distributed/fully_distributed_tria_util.h>
#include <deal.II/distributed/shared_tria.h>
#include <deal.II/distributed/tria.h>
[](dealii::Triangulation<dim> &tria, const unsigned int n_partitions) {
GridTools::partition_triangulation_zorder(n_partitions, tria);
},
- parallel::fullydistributed::Settings::construct_multigrid_hierarchy);
+ TriangulationDescription::Settings::construct_multigrid_hierarchy);
// actually create triangulation
tria_pft.copy_triangulation(basetria);
// Create the ConstructionData with
-// create_construction_data_from_triangulation_in_groups, i.e. by a set of
+// create_description_from_triangulation_in_groups, i.e. by a set of
// master processes.
#include <deal.II/base/mpi.h>
#include <deal.II/distributed/fully_distributed_tria.h>
-#include <deal.II/distributed/fully_distributed_tria_util.h>
#include <deal.II/distributed/shared_tria.h>
#include <deal.II/distributed/tria.h>
#include <deal.II/grid/grid_out.h>
#include <deal.II/grid/grid_tools.h>
#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_description.h>
#include <boost/archive/text_oarchive.hpp>
void
test(int n_refinements, MPI_Comm comm)
{
- // 1) create ConstructionData with create_construction_data_from_triangulation
+ // 1) create ConstructionData with create_description_from_triangulation
Triangulation<dim> basetria(
Triangulation<dim>::limit_level_difference_at_vertices);
GridGenerator::hyper_L(basetria);
Utilities::MPI::n_mpi_processes(comm), basetria);
GridTools::partition_multigrid_levels(basetria);
- auto construction_data_1 = parallel::fullydistributed::Utilities::
- create_construction_data_from_triangulation(basetria, comm, true);
+ auto construction_data_1 =
+ TriangulationDescription::Utilities::create_description_from_triangulation(
+ basetria, comm, true);
// 2) create ConstructionData with
- // create_construction_data_from_triangulation_in_groups
- auto construction_data_2 = parallel::fullydistributed::Utilities::
- create_construction_data_from_triangulation_in_groups<dim, spacedim>(
+ // create_description_from_triangulation_in_groups
+ auto construction_data_2 = TriangulationDescription::Utilities::
+ create_description_from_triangulation_in_groups<dim, spacedim>(
[n_refinements](dealii::Triangulation<dim, spacedim> &tria) {
GridGenerator::hyper_L(tria);
tria.refine_global(n_refinements);
#include <deal.II/base/utilities.h>
#include <deal.II/distributed/fully_distributed_tria.h>
-#include <deal.II/distributed/fully_distributed_tria_util.h>
#include <deal.II/distributed/tria.h>
#include <deal.II/dofs/dof_handler.h>
#include <deal.II/grid/grid_generator.h>
#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_description.h>
#include <deal.II/lac/affine_constraints.h>
#include <deal.II/lac/la_parallel_vector.h>
parallel::fullydistributed::Triangulation<dim> tria_pft(MPI_COMM_WORLD);
// extract relevant information form pdt
- auto construction_data = parallel::fullydistributed::Utilities::
- create_construction_data_from_triangulation(tria, MPI_COMM_WORLD, true);
+ auto construction_data = TriangulationDescription::Utilities::
+ create_description_from_triangulation(tria, MPI_COMM_WORLD, true);
// actually create triangulation
tria_pft.create_triangulation(construction_data);
parallel::fullydistributed::Triangulation<dim> tria_pft(MPI_COMM_WORLD);
// extract relevant information form pdt
- auto construction_data = parallel::fullydistributed::Utilities::
- create_construction_data_from_triangulation(tria,
- MPI_COMM_WORLD,
- true);
+ auto construction_data = TriangulationDescription::Utilities::
+ create_description_from_triangulation(tria, MPI_COMM_WORLD, true);
// actually create triangulation
tria_pft.create_triangulation(construction_data);
// check serialization for ConstructionData<dim, spacedim>
#include <deal.II/distributed/fully_distributed_tria.h>
-#include <deal.II/distributed/fully_distributed_tria_util.h>
#include <deal.II/distributed/tria.h>
#include <deal.II/grid/grid_generator.h>
#include <deal.II/grid/grid_tools.h>
#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_description.h>
#include <boost/serialization/vector.hpp>
GridTools::partition_triangulation_zorder(
Utilities::MPI::n_mpi_processes(comm), basetria);
- auto t1 = parallel::fullydistributed::Utilities::
- create_construction_data_from_triangulation(basetria, comm);
+ auto t1 =
+ TriangulationDescription::Utilities::create_description_from_triangulation(
+ basetria, comm);
// compare equal ConstructionDatas
auto t2 = t1;
GridTools::partition_triangulation_zorder(
Utilities::MPI::n_mpi_processes(comm), basetria);
- auto t3 = parallel::fullydistributed::Utilities::
- create_construction_data_from_triangulation(basetria, comm);
+ auto t3 =
+ TriangulationDescription::Utilities::create_description_from_triangulation(
+ basetria, comm);
// compare different ConstructionDatas
verify(t1, t3);