Reference documentation for deal.II version 8.5.1
mg_level_global_transfer.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2003 - 2016 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 at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 
17 #include <deal.II/base/logstream.h>
18 #include <deal.II/base/function.h>
19 
20 #include <deal.II/lac/vector.h>
21 #include <deal.II/lac/block_vector.h>
22 #include <deal.II/lac/la_parallel_vector.h>
23 #include <deal.II/lac/la_parallel_block_vector.h>
24 #include <deal.II/lac/petsc_vector.h>
25 #include <deal.II/lac/petsc_block_vector.h>
26 #include <deal.II/lac/trilinos_vector.h>
27 #include <deal.II/lac/trilinos_block_vector.h>
28 #include <deal.II/grid/tria.h>
29 #include <deal.II/grid/tria_iterator.h>
30 #include <deal.II/fe/fe.h>
31 #include <deal.II/dofs/dof_accessor.h>
32 #include <deal.II/multigrid/mg_tools.h>
33 #include <deal.II/multigrid/mg_transfer.h>
34 #include <deal.II/multigrid/mg_transfer.templates.h>
35 #include <deal.II/multigrid/mg_transfer_internal.h>
36 
37 #include <algorithm>
38 
39 DEAL_II_NAMESPACE_OPEN
40 
41 
42 /* ------------------ MGLevelGlobalTransfer<VectorType> ----------------- */
43 
44 
45 template <typename VectorType>
46 template <int dim, int spacedim>
47 void
49 (const DoFHandler<dim,spacedim> &mg_dof)
50 {
51  internal::MGTransfer::fill_copy_indices(mg_dof, mg_constrained_dofs, copy_indices,
52  copy_indices_global_mine, copy_indices_level_mine);
53 
54  // check if we can run a plain copy operation between the global DoFs and
55  // the finest level.
56  perform_plain_copy =
57  (copy_indices.back().size() == mg_dof.locally_owned_dofs().n_elements())
58  &&
59  (mg_dof.locally_owned_dofs().n_elements() ==
60  mg_dof.locally_owned_mg_dofs(mg_dof.get_triangulation().n_global_levels()-1).n_elements());
61  if (perform_plain_copy)
62  {
63  AssertDimension(copy_indices_global_mine.back().size(), 0);
64  AssertDimension(copy_indices_level_mine.back().size(), 0);
65 
66  // check whether there is a renumbering of degrees of freedom on
67  // either the finest level or the global dofs, which means that we
68  // cannot apply a plain copy
69  for (unsigned int i=0; i<copy_indices.back().size(); ++i)
70  if (copy_indices.back()[i].first != copy_indices.back()[i].second)
71  {
72  perform_plain_copy = false;
73  break;
74  }
75  }
77  dynamic_cast<const parallel::Triangulation<dim, spacedim> *>
78  (&mg_dof.get_tria());
79  const MPI_Comm mpi_communicator = ptria != 0 ? ptria->get_communicator() :
80  MPI_COMM_SELF;
81  perform_plain_copy =
82  Utilities::MPI::min(static_cast<int>(perform_plain_copy),
83  mpi_communicator);
84 
85 }
86 
87 
88 
89 template <typename VectorType>
90 void
92 {
93  sizes.resize(0);
94  copy_indices.clear();
95  copy_indices_global_mine.clear();
96  copy_indices_level_mine.clear();
97  component_to_block_map.resize(0);
98  mg_constrained_dofs = 0;
99 }
100 
101 
102 
103 template <typename VectorType>
104 void
106 {
107  for (unsigned int level = 0; level<copy_indices.size(); ++level)
108  {
109  for (unsigned int i=0; i<copy_indices[level].size(); ++i)
110  os << "copy_indices[" << level
111  << "]\t" << copy_indices[level][i].first << '\t' << copy_indices[level][i].second << std::endl;
112  }
113 
114  for (unsigned int level = 0; level<copy_indices_level_mine.size(); ++level)
115  {
116  for (unsigned int i=0; i<copy_indices_level_mine[level].size(); ++i)
117  os << "copy_ifrom [" << level
118  << "]\t" << copy_indices_level_mine[level][i].first << '\t' << copy_indices_level_mine[level][i].second << std::endl;
119  }
120  for (unsigned int level = 0; level<copy_indices_global_mine.size(); ++level)
121  {
122  for (unsigned int i=0; i<copy_indices_global_mine[level].size(); ++i)
123  os << "copy_ito [" << level
124  << "]\t" << copy_indices_global_mine[level][i].first << '\t' << copy_indices_global_mine[level][i].second << std::endl;
125  }
126 }
127 
128 
129 
130 template <typename VectorType>
131 std::size_t
133 {
134  std::size_t result = sizeof(*this);
135  result += MemoryConsumption::memory_consumption(sizes);
136  result += MemoryConsumption::memory_consumption(copy_indices);
137  result += MemoryConsumption::memory_consumption(copy_indices_global_mine);
138  result += MemoryConsumption::memory_consumption(copy_indices_level_mine);
139 
140  return result;
141 }
142 
143 
144 
145 /* ------------------ MGLevelGlobalTransfer<VectorType> ----------------- */
146 
147 
148 template <typename Number>
149 template <int dim, int spacedim>
150 void
151 MGLevelGlobalTransfer<LinearAlgebra::distributed::Vector<Number> >::fill_and_communicate_copy_indices
153 {
154  // first go to the usual routine...
155  std::vector<std::vector<std::pair<types::global_dof_index, types::global_dof_index> > >
156  my_copy_indices;
157  std::vector<std::vector<std::pair<types::global_dof_index, types::global_dof_index> > >
158  my_copy_indices_global_mine;
159  std::vector<std::vector<std::pair<types::global_dof_index, types::global_dof_index> > >
160  my_copy_indices_level_mine;
161 
162  internal::MGTransfer::fill_copy_indices(mg_dof, mg_constrained_dofs, my_copy_indices,
163  my_copy_indices_global_mine, my_copy_indices_level_mine);
164 
165  // get all degrees of freedom that we need read access to in copy_to_mg
166  // and copy_from_mg, respectively. We fill an IndexSet once on each level
167  // (for the global_mine indices accessing remote level indices) and once
168  // globally (for the level_mine indices accessing remote global indices).
169 
170  // the variables index_set and level_index_set are going to define the
171  // ghost indices of the respective vectors (due to construction, these are
172  // precisely the indices that we need)
174  dynamic_cast<const parallel::Triangulation<dim, spacedim> *>
175  (&mg_dof.get_tria());
176  const MPI_Comm mpi_communicator = ptria != 0 ? ptria->get_communicator() :
177  MPI_COMM_SELF;
178 
179  IndexSet index_set(mg_dof.locally_owned_dofs().size());
180  std::vector<types::global_dof_index> accessed_indices;
181  ghosted_level_vector.resize(0, mg_dof.get_triangulation().n_global_levels()-1);
182  std::vector<IndexSet> level_index_set(mg_dof.get_triangulation().n_global_levels());
183  for (unsigned int l=0; l<mg_dof.get_triangulation().n_global_levels(); ++l)
184  {
185  for (unsigned int i=0; i<my_copy_indices_level_mine[l].size(); ++i)
186  accessed_indices.push_back(my_copy_indices_level_mine[l][i].first);
187  std::vector<types::global_dof_index> accessed_level_indices;
188  for (unsigned int i=0; i<my_copy_indices_global_mine[l].size(); ++i)
189  accessed_level_indices.push_back(my_copy_indices_global_mine[l][i].second);
190  std::sort(accessed_level_indices.begin(), accessed_level_indices.end());
191  level_index_set[l].set_size(mg_dof.locally_owned_mg_dofs(l).size());
192  level_index_set[l].add_indices(accessed_level_indices.begin(),
193  accessed_level_indices.end());
194  level_index_set[l].compress();
195  ghosted_level_vector[l].reinit(mg_dof.locally_owned_mg_dofs(l),
196  level_index_set[l],
197  mpi_communicator);
198  }
199  std::sort(accessed_indices.begin(), accessed_indices.end());
200  index_set.add_indices(accessed_indices.begin(), accessed_indices.end());
201  index_set.compress();
202  ghosted_global_vector.reinit(mg_dof.locally_owned_dofs(),
203  index_set,
204  mpi_communicator);
205 
206  // localize the copy indices for faster access. Since all access will be
207  // through the ghosted vector in 'data', we can use this (much faster)
208  // option
209  this->copy_indices.resize(mg_dof.get_triangulation().n_global_levels());
210  this->copy_indices_level_mine.resize(mg_dof.get_triangulation().n_global_levels());
211  this->copy_indices_global_mine.resize(mg_dof.get_triangulation().n_global_levels());
212  for (unsigned int level=0; level<mg_dof.get_triangulation().n_global_levels(); ++level)
213  {
214  const Utilities::MPI::Partitioner &global_partitioner =
215  *ghosted_global_vector.get_partitioner();
216  const Utilities::MPI::Partitioner &level_partitioner =
217  *ghosted_level_vector[level].get_partitioner();
218  // owned-owned case: the locally owned indices are going to control
219  // the local index
220  this->copy_indices[level].resize(my_copy_indices[level].size());
221  for (unsigned int i=0; i<my_copy_indices[level].size(); ++i)
222  this->copy_indices[level][i] =
223  std::pair<unsigned int,unsigned int>
224  (global_partitioner.global_to_local(my_copy_indices[level][i].first),
225  level_partitioner.global_to_local(my_copy_indices[level][i].second));
226 
227  // remote-owned case: the locally owned indices for the level and the
228  // ghost dofs for the global indices set the local index
229  this->copy_indices_level_mine[level].
230  resize(my_copy_indices_level_mine[level].size());
231  for (unsigned int i=0; i<my_copy_indices_level_mine[level].size(); ++i)
232  this->copy_indices_level_mine[level][i] =
233  std::pair<unsigned int,unsigned int>
234  (global_partitioner.global_to_local(my_copy_indices_level_mine[level][i].first),
235  level_partitioner.global_to_local(my_copy_indices_level_mine[level][i].second));
236 
237  // owned-remote case: the locally owned indices for the global dofs
238  // and the ghost dofs for the level indices set the local index
239  this->copy_indices_global_mine[level].
240  resize(my_copy_indices_global_mine[level].size());
241  for (unsigned int i=0; i<my_copy_indices_global_mine[level].size(); ++i)
242  this->copy_indices_global_mine[level][i] =
243  std::pair<unsigned int,unsigned int>
244  (global_partitioner.global_to_local(my_copy_indices_global_mine[level][i].first),
245  level_partitioner.global_to_local(my_copy_indices_global_mine[level][i].second));
246  }
247 
248  perform_plain_copy = this->copy_indices.back().size()
249  == mg_dof.locally_owned_dofs().n_elements();
250  if (perform_plain_copy)
251  {
252  AssertDimension(this->copy_indices_global_mine.back().size(), 0);
253  AssertDimension(this->copy_indices_level_mine.back().size(), 0);
254 
255  // check whether there is a renumbering of degrees of freedom on
256  // either the finest level or the global dofs, which means that we
257  // cannot apply a plain copy
258  for (unsigned int i=0; i<this->copy_indices.back().size(); ++i)
259  if (this->copy_indices.back()[i].first !=
260  this->copy_indices.back()[i].second)
261  {
262  perform_plain_copy = false;
263  break;
264  }
265  }
266  perform_plain_copy =
267  Utilities::MPI::min(static_cast<int>(perform_plain_copy),
268  mpi_communicator);
269 
270  // if we do a plain copy, no need to hold additional ghosted vectors
271  if (perform_plain_copy)
272  {
273  ghosted_global_vector.reinit(0);
274  ghosted_level_vector.resize(0, 0);
275  }
276 }
277 
278 
279 
280 template <typename Number>
281 void
283 {
284  sizes.resize(0);
285  copy_indices.clear();
286  copy_indices_global_mine.clear();
287  copy_indices_level_mine.clear();
288  component_to_block_map.resize(0);
289  mg_constrained_dofs = 0;
290  ghosted_global_vector.reinit(0);
291  ghosted_level_vector.resize(0, 0);
292 }
293 
294 
295 
296 template <typename Number>
297 void
299 {
300  for (unsigned int level = 0; level<copy_indices.size(); ++level)
301  {
302  for (unsigned int i=0; i<copy_indices[level].size(); ++i)
303  os << "copy_indices[" << level
304  << "]\t" << copy_indices[level][i].first << '\t' << copy_indices[level][i].second << std::endl;
305  }
306 
307  for (unsigned int level = 0; level<copy_indices_level_mine.size(); ++level)
308  {
309  for (unsigned int i=0; i<copy_indices_level_mine[level].size(); ++i)
310  os << "copy_ifrom [" << level
311  << "]\t" << copy_indices_level_mine[level][i].first << '\t' << copy_indices_level_mine[level][i].second << std::endl;
312  }
313  for (unsigned int level = 0; level<copy_indices_global_mine.size(); ++level)
314  {
315  for (unsigned int i=0; i<copy_indices_global_mine[level].size(); ++i)
316  os << "copy_ito [" << level
317  << "]\t" << copy_indices_global_mine[level][i].first << '\t' << copy_indices_global_mine[level][i].second << std::endl;
318  }
319 }
320 
321 
322 
323 template <typename Number>
324 std::size_t
326 {
327  std::size_t result = sizeof(*this);
328  result += MemoryConsumption::memory_consumption(sizes);
329  result += MemoryConsumption::memory_consumption(copy_indices);
330  result += MemoryConsumption::memory_consumption(copy_indices_global_mine);
331  result += MemoryConsumption::memory_consumption(copy_indices_level_mine);
332  result += ghosted_global_vector.memory_consumption();
333  for (unsigned int i=ghosted_level_vector.min_level();
334  i<=ghosted_level_vector.max_level(); ++i)
335  result += ghosted_level_vector[i].memory_consumption();
336 
337  return result;
338 }
339 
340 
341 
342 // explicit instantiation
343 #include "mg_level_global_transfer.inst"
344 
345 // create an additional instantiation currently not supported by the automatic
346 // template instantiation scheme
348 
349 
350 DEAL_II_NAMESPACE_CLOSE
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1146
std::size_t memory_consumption() const
const Triangulation< dim, spacedim > & get_tria() const 1
unsigned int global_to_local(const types::global_dof_index global_index) const
void print_indices(std::ostream &os) const
size_type size() const
Definition: index_set.h:1419
void fill_and_communicate_copy_indices(const DoFHandler< dim, spacedim > &mg_dof)
virtual MPI_Comm get_communicator() const
Definition: tria_base.cc:146
const IndexSet & locally_owned_mg_dofs(const unsigned int level) const
std_cxx11::enable_if< std_cxx11::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
T min(const T &t, const MPI_Comm &mpi_communicator)
const Triangulation< dim, spacedim > & get_triangulation() const
const IndexSet & locally_owned_dofs() const
size_type n_elements() const
Definition: index_set.h:1560