Reference documentation for deal.II version 9.1.0-pre
shared_tria.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2015 - 2018 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #include <deal.II/base/mpi.h>
17 #include <deal.II/base/utilities.h>
18 
19 #include <deal.II/distributed/shared_tria.h>
20 #include <deal.II/distributed/tria.h>
21 
22 #include <deal.II/grid/filtered_iterator.h>
23 #include <deal.II/grid/grid_tools.h>
24 #include <deal.II/grid/tria.h>
25 #include <deal.II/grid/tria_accessor.h>
26 #include <deal.II/grid/tria_iterator.h>
27 
28 #include <deal.II/lac/sparsity_tools.h>
29 
30 
31 DEAL_II_NAMESPACE_OPEN
32 
33 #ifdef DEAL_II_WITH_MPI
34 namespace parallel
35 {
36  namespace shared
37  {
38  template <int dim, int spacedim>
40  MPI_Comm mpi_communicator,
41  const typename ::Triangulation<dim, spacedim>::MeshSmoothing
42  smooth_grid,
43  const bool allow_artificial_cells,
44  const Settings settings)
45  : ::parallel::Triangulation<dim, spacedim>(mpi_communicator,
46  smooth_grid,
47  false)
48  , settings(settings)
49  , allow_artificial_cells(allow_artificial_cells)
50  {
51  const auto partition_settings =
54  settings;
55  (void)partition_settings;
56  Assert(
57  partition_settings == partition_auto ||
58  partition_settings == partition_metis ||
59  partition_settings == partition_zoltan ||
60  partition_settings == partition_zorder ||
61  partition_settings == partition_custom_signal,
62  ExcMessage(
63  "Settings must contain exactly one type of the active cell partitioning scheme."))
64 
65  if (settings & construct_multigrid_hierarchy) Assert(
66  allow_artificial_cells,
67  ExcMessage(
68  "construct_multigrid_hierarchy requires allow_artificial_cells to be set to true."))
69  }
70 
71 
72 
73  template <int dim, int spacedim>
74  void
76  {
77 # ifdef DEBUG
78  // Check that all meshes are the same (or at least have the same
79  // total number of active cells):
80  const unsigned int max_active_cells =
82  Assert(
83  max_active_cells == this->n_active_cells(),
84  ExcMessage(
85  "A parallel::shared::Triangulation needs to be refined in the same"
86  "way on all processors, but the participating processors don't "
87  "agree on the number of active cells."))
88 # endif
89 
90  auto partition_settings = (partition_zoltan | partition_metis |
92  settings;
93  if (partition_settings == partition_auto)
94 # ifdef DEAL_II_TRILINOS_WITH_ZOLTAN
95  partition_settings = partition_zoltan;
96 # elif defined DEAL_II_WITH_METIS
97  partition_settings = partition_metis;
98 # else
99  partition_settings = partition_zorder;
100 # endif
101 
102  if (partition_settings == partition_zoltan)
103  {
104 # ifndef DEAL_II_TRILINOS_WITH_ZOLTAN
105  AssertThrow(false,
106  ExcMessage(
107  "Choosing 'partition_zoltan' requires the library "
108  "to be compiled with support for Zoltan! "
109  "Instead, you might use 'partition_auto' to select "
110  "a partitioning algorithm that is supported "
111  "by your current configuration."));
112 # else
115 # endif
116  }
117  else if (partition_settings == partition_metis)
118  {
119 # ifndef DEAL_II_WITH_METIS
120  AssertThrow(false,
121  ExcMessage(
122  "Choosing 'partition_metis' requires the library "
123  "to be compiled with support for METIS! "
124  "Instead, you might use 'partition_auto' to select "
125  "a partitioning algorithm that is supported "
126  "by your current configuration."));
127 # else
129  *this,
131 # endif
132  }
133  else if (partition_settings == partition_zorder)
134  {
136  }
137  else if (partition_settings == partition_custom_signal)
138  {
139  // User partitions mesh manually
140  }
141  else
142  {
143  AssertThrow(false, ExcInternalError())
144  }
145 
146  // do not partition multigrid levels if user is
147  // defining a custom partition
150  ::GridTools::partition_multigrid_levels(*this);
151 
153 
154  // loop over all cells and mark artificial:
155  typename parallel::shared::Triangulation<dim,
156  spacedim>::active_cell_iterator
157  cell = this->begin_active(),
158  endc = this->end();
159 
161  {
162  // get active halo layer of (ghost) cells
163  // parallel::shared::Triangulation<dim>::
164  std::function<bool(
166  active_cell_iterator &)>
168 
169  const std::vector<typename parallel::shared::Triangulation<
170  dim,
171  spacedim>::active_cell_iterator>
172  active_halo_layer_vector =
173  ::GridTools::compute_active_cell_halo_layer(*this,
174  predicate);
175  std::set<typename parallel::shared::Triangulation<dim, spacedim>::
176  active_cell_iterator>
177  active_halo_layer(active_halo_layer_vector.begin(),
178  active_halo_layer_vector.end());
179 
180  for (unsigned int index = 0; cell != endc; cell++, index++)
181  {
182  // store original/true subdomain ids:
183  true_subdomain_ids_of_cells[index] = cell->subdomain_id();
184 
185  if (cell->is_locally_owned() == false &&
186  active_halo_layer.find(cell) == active_halo_layer.end())
187  cell->set_subdomain_id(numbers::artificial_subdomain_id);
188  }
189 
190  // loop over all cells in multigrid hierarchy and mark artificial:
191  if (settings & construct_multigrid_hierarchy)
192  {
194 
195  std::function<bool(
197  cell_iterator &)>
199  for (unsigned int lvl = 0; lvl < this->n_levels(); ++lvl)
200  {
202  this->n_cells(lvl));
203 
204  const std::vector<typename parallel::shared::Triangulation<
205  dim,
206  spacedim>::cell_iterator>
207  level_halo_layer_vector =
208  ::GridTools::compute_cell_halo_layer_on_level(
209  *this, predicate, lvl);
210  std::set<typename parallel::shared::
211  Triangulation<dim, spacedim>::cell_iterator>
212  level_halo_layer(level_halo_layer_vector.begin(),
213  level_halo_layer_vector.end());
214 
216  cell_iterator cell = this->begin(lvl),
217  endc = this->end(lvl);
218  for (unsigned int index = 0; cell != endc; cell++, index++)
219  {
220  // Store true level subdomain IDs before setting
221  // artificial
223  cell->level_subdomain_id();
224 
225  // for active cells, we must have knowledge of level
226  // subdomain ids of all neighbors to our subdomain, not
227  // just neighbors on the same level. if the cells
228  // subdomain id was not set to artitficial above, we will
229  // also keep its level subdomain id since it is either
230  // owned by this processor or in the ghost layer of the
231  // active mesh.
232  if (!cell->has_children() &&
233  cell->subdomain_id() !=
235  continue;
236 
237  // we must have knowledge of our parent in the hierarchy
238  if (cell->has_children())
239  {
240  bool keep_cell = false;
241  for (unsigned int c = 0;
242  c < GeometryInfo<dim>::max_children_per_cell;
243  ++c)
244  if (cell->child(c)->level_subdomain_id() ==
245  this->my_subdomain)
246  {
247  keep_cell = true;
248  break;
249  }
250  if (keep_cell)
251  continue;
252  }
253 
254  // we must have knowledge of our neighbors on the same
255  // level
256  if (!cell->is_locally_owned_on_level() &&
257  level_halo_layer.find(cell) != level_halo_layer.end())
258  continue;
259 
260  // mark all other cells to artificial
261  cell->set_level_subdomain_id(
263  }
264  }
265  }
266  }
267  else
268  {
269  // just store true subdomain ids
270  for (unsigned int index = 0; cell != endc; cell++, index++)
271  true_subdomain_ids_of_cells[index] = cell->subdomain_id();
272  }
273 
274 # ifdef DEBUG
275  {
276  // Assert that each cell is owned by a processor
277  unsigned int n_my_cells = 0;
278  typename parallel::shared::Triangulation<dim,
279  spacedim>::active_cell_iterator
280  cell = this->begin_active(),
281  endc = this->end();
282  for (; cell != endc; ++cell)
283  if (cell->is_locally_owned())
284  n_my_cells += 1;
285 
286  const unsigned int total_cells =
287  Utilities::MPI::sum(n_my_cells, this->get_communicator());
288  Assert(total_cells == this->n_active_cells(),
289  ExcMessage("Not all cells are assigned to a processor."))
290  }
291 
292  // If running with multigrid, assert that each level
293  // cell is owned by a processor
294  if (settings & construct_multigrid_hierarchy)
295  {
296  unsigned int n_my_cells = 0;
297  typename parallel::shared::Triangulation<dim, spacedim>::cell_iterator
298  cell = this->begin(),
299  endc = this->end();
300  for (; cell != endc; ++cell)
301  if (cell->is_locally_owned_on_level())
302  n_my_cells += 1;
303 
304  const unsigned int total_cells =
305  Utilities::MPI::sum(n_my_cells, this->get_communicator());
306  Assert(total_cells == this->n_cells(),
307  ExcMessage("Not all cells are assigned to a processor."))
308  }
309 # endif
310  }
311 
312 
313 
314  template <int dim, int spacedim>
315  bool
317  {
318  return allow_artificial_cells;
319  }
320 
321 
322 
323  template <int dim, int spacedim>
324  const std::vector<types::subdomain_id> &
326  {
328  }
329 
330 
331 
332  template <int dim, int spacedim>
333  const std::vector<types::subdomain_id> &
335  const unsigned int level) const
336  {
337  return true_level_subdomain_ids_of_cells[level];
338  }
339 
340 
341 
342  template <int dim, int spacedim>
343  void
345  {
347  partition();
348  this->update_number_cache();
349  }
350 
351 
352 
353  template <int dim, int spacedim>
354  void
356  const std::vector<Point<spacedim>> &vertices,
357  const std::vector<CellData<dim>> & cells,
358  const SubCellData & subcelldata)
359  {
360  try
361  {
363  vertices, cells, subcelldata);
364  }
365  catch (
366  const typename ::Triangulation<dim, spacedim>::DistortedCellList
367  &)
368  {
369  // the underlying triangulation should not be checking for distorted
370  // cells
371  Assert(false, ExcInternalError());
372  }
373  partition();
374  this->update_number_cache();
375  }
376 
377 
378 
379  template <int dim, int spacedim>
380  void
382  const ::Triangulation<dim, spacedim> &other_tria)
383  {
384  Assert(
385  (dynamic_cast<
386  const ::parallel::distributed::Triangulation<dim, spacedim> *>(
387  &other_tria) == nullptr),
388  ExcMessage(
389  "Cannot use this function on parallel::distributed::Triangulation."));
390 
392  other_tria);
393  partition();
394  this->update_number_cache();
395  }
396 
397 
398 
399  template <int dim, int spacedim>
400  void
402  {
404 
407  }
408  } // namespace shared
409 } // namespace parallel
410 
411 #else
412 
413 namespace parallel
414 {
415  namespace shared
416  {
417  template <int dim, int spacedim>
418  bool
420  {
421  Assert(false, ExcNotImplemented());
422  return true;
423  }
424 
425 
426 
427  template <int dim, int spacedim>
428  const std::vector<unsigned int> &
430  {
431  Assert(false, ExcNotImplemented());
433  }
434 
435 
436 
437  template <int dim, int spacedim>
438  const std::vector<unsigned int> &
440  const unsigned int) const
441  {
442  Assert(false, ExcNotImplemented());
444  }
445  } // namespace shared
446 } // namespace parallel
447 
448 
449 #endif
450 
451 
452 /*-------------- Explicit Instantiations -------------------------------*/
453 #include "shared_tria.inst"
454 
455 DEAL_II_NAMESPACE_CLOSE
std::vector< std::vector< types::subdomain_id > > true_level_subdomain_ids_of_cells
Definition: shared_tria.h:375
cell_iterator end() const
Definition: tria.cc:12004
types::subdomain_id my_subdomain
Definition: tria_base.h:184
std::vector< Point< spacedim > > vertices
Definition: tria.h:3662
const std::vector< types::subdomain_id > & get_true_subdomain_ids_of_cells() const
Definition: shared_tria.cc:325
virtual void execute_coarsening_and_refinement() override
Definition: shared_tria.cc:344
#define AssertThrow(cond, exc)
Definition: exceptions.h:1329
cell_iterator begin(const unsigned int level=0) const
Definition: tria.cc:11915
unsigned int n_active_cells() const
Definition: tria.cc:12509
void partition_triangulation_zorder(const unsigned int n_partitions, Triangulation< dim, spacedim > &triangulation)
Definition: grid_tools.cc:2657
unsigned int n_levels() const
void partition_triangulation(const unsigned int n_partitions, Triangulation< dim, spacedim > &triangulation, const SparsityTools::Partitioner partitioner=SparsityTools::Partitioner::metis)
Definition: grid_tools.cc:2454
virtual void execute_coarsening_and_refinement()
Definition: tria.cc:13229
virtual MPI_Comm get_communicator() const
Definition: tria_base.cc:155
virtual void copy_triangulation(const ::Triangulation< dim, spacedim > &old_tria) override
Definition: tria_base.cc:66
static::ExceptionBase & ExcMessage(std::string arg1)
virtual void update_number_cache() override
Definition: shared_tria.cc:401
unsigned int n_cells() const
Definition: tria.cc:12501
T sum(const T &t, const MPI_Comm &mpi_communicator)
virtual void create_triangulation(const std::vector< Point< spacedim >> &vertices, const std::vector< CellData< dim >> &cells, const SubCellData &subcelldata)
Definition: tria.cc:10556
#define Assert(cond, exc)
Definition: exceptions.h:1227
virtual void update_number_cache()
Definition: tria_base.cc:163
Triangulation(MPI_Comm mpi_communicator, const typename::Triangulation< dim, spacedim >::MeshSmoothing=(::Triangulation< dim, spacedim >::none), const bool allow_artificial_cells=false, const Settings settings=partition_auto)
Definition: shared_tria.cc:39
const types::subdomain_id artificial_subdomain_id
Definition: types.h:272
std::vector< types::subdomain_id > true_subdomain_ids_of_cells
Definition: shared_tria.h:364
virtual void create_triangulation(const std::vector< Point< spacedim >> &vertices, const std::vector< CellData< dim >> &cells, const SubCellData &subcelldata) override
Definition: shared_tria.cc:355
static::ExceptionBase & ExcNotImplemented()
active_cell_iterator begin_active(const unsigned int level=0) const
Definition: tria.cc:11935
virtual void copy_triangulation(const ::Triangulation< dim, spacedim > &other_tria) override
Definition: shared_tria.cc:381
T max(const T &t, const MPI_Comm &mpi_communicator)
const std::vector< types::subdomain_id > & get_true_level_subdomain_ids_of_cells(const unsigned int level) const
Definition: shared_tria.cc:334
types::subdomain_id n_subdomains
Definition: tria_base.h:189
static::ExceptionBase & ExcInternalError()