Reference documentation for deal.II version 9.0.0
mg_transfer_prebuilt.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2003 - 2017 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/trilinos_epetra_vector.h>
25 #include <deal.II/lac/trilinos_vector.h>
26 #include <deal.II/lac/trilinos_parallel_block_vector.h>
27 #include <deal.II/lac/sparse_matrix.h>
28 #include <deal.II/lac/block_sparse_matrix.h>
29 #include <deal.II/lac/dynamic_sparsity_pattern.h>
30 #include <deal.II/grid/tria.h>
31 #include <deal.II/grid/tria_iterator.h>
32 #include <deal.II/dofs/dof_tools.h>
33 #include <deal.II/fe/fe.h>
34 #include <deal.II/dofs/dof_accessor.h>
35 #include <deal.II/multigrid/mg_tools.h>
36 #include <deal.II/multigrid/mg_transfer.h>
37 
38 #include <algorithm>
39 
40 DEAL_II_NAMESPACE_OPEN
41 
42 
43 template <typename VectorType>
45 {
46  this->mg_constrained_dofs = &mg_c;
47 }
48 
49 
50 
51 template <typename VectorType>
53 {
54  this->mg_constrained_dofs = &mg_c;
55 }
56 
57 
58 
59 template <typename VectorType>
61 (const MGConstrainedDoFs &mg_c)
62 {
63  this->mg_constrained_dofs = &mg_c;
64 }
65 
66 
67 
68 template <typename VectorType>
70 (const ConstraintMatrix &/*c*/, const MGConstrainedDoFs &mg_c)
71 {
72  initialize_constraints(mg_c);
73 }
74 
75 
76 
77 template <typename VectorType>
79 {
81  prolongation_matrices.resize(0);
82  prolongation_sparsities.resize(0);
83  interface_dofs.resize(0);
84 }
85 
86 
87 
88 template <typename VectorType>
89 void MGTransferPrebuilt<VectorType>::prolongate (const unsigned int to_level,
90  VectorType &dst,
91  const VectorType &src) const
92 {
93  Assert ((to_level >= 1) && (to_level<=prolongation_matrices.size()),
94  ExcIndexRange (to_level, 1, prolongation_matrices.size()+1));
95 
96  prolongation_matrices[to_level-1]->vmult (dst, src);
97 }
98 
99 
100 
101 template <typename VectorType>
102 void MGTransferPrebuilt<VectorType>::restrict_and_add (const unsigned int from_level,
103  VectorType &dst,
104  const VectorType &src) const
105 {
106  Assert ((from_level >= 1) && (from_level<=prolongation_matrices.size()),
107  ExcIndexRange (from_level, 1, prolongation_matrices.size()+1));
108  (void)from_level;
109 
110  prolongation_matrices[from_level-1]->Tvmult_add (dst, src);
111 }
112 
113 
114 namespace
115 {
120  void replace (const MGConstrainedDoFs *mg_constrained_dofs,
121  const unsigned int level,
122  std::vector<types::global_dof_index> &dof_indices)
123  {
124  if (mg_constrained_dofs != nullptr &&
125  mg_constrained_dofs->get_level_constraint_matrix(level).n_constraints() > 0)
126  for (auto &ind : dof_indices)
127  if (mg_constrained_dofs->get_level_constraint_matrix(level).is_identity_constrained(ind))
128  {
129  Assert(mg_constrained_dofs->get_level_constraint_matrix(level).get_constraint_entries(ind)->size() == 1,
130  ExcInternalError());
131  ind = mg_constrained_dofs->get_level_constraint_matrix(level).get_constraint_entries(ind)->front().first;
132  }
133  }
134 }
135 
136 template <typename VectorType>
137 template <int dim, int spacedim>
140 {
141  const unsigned int n_levels = mg_dof.get_triangulation().n_global_levels();
142  const unsigned int dofs_per_cell = mg_dof.get_fe().dofs_per_cell;
143 
144  this->sizes.resize(n_levels);
145  for (unsigned int l=0; l<n_levels; ++l)
146  this->sizes[l] = mg_dof.n_dofs(l);
147 
148  // reset the size of the array of
149  // matrices. call resize(0) first,
150  // in order to delete all elements
151  // and clear their memory. then
152  // repopulate these arrays
153  //
154  // note that on resize(0), the
155  // shared_ptr class takes care of
156  // deleting the object it points to
157  // by itself
158  prolongation_matrices.resize (0);
159  prolongation_sparsities.resize (0);
160  prolongation_matrices.reserve (n_levels - 1);
161  prolongation_sparsities.reserve (n_levels - 1);
162 
163  for (unsigned int i=0; i<n_levels-1; ++i)
164  {
165  prolongation_sparsities.emplace_back
167  prolongation_matrices.emplace_back
169  }
170 
171  // two fields which will store the
172  // indices of the multigrid dofs
173  // for a cell and one of its children
174  std::vector<types::global_dof_index> dof_indices_parent (dofs_per_cell);
175  std::vector<types::global_dof_index> dof_indices_child (dofs_per_cell);
176  std::vector<types::global_dof_index> entries (dofs_per_cell);
177 
178  // for each level: first build the sparsity
179  // pattern of the matrices and then build the
180  // matrices themselves. note that we only
181  // need to take care of cells on the coarser
182  // level which have children
183  for (unsigned int level=0; level<n_levels-1; ++level)
184  {
185  // reset the dimension of the structure. note that for the number of
186  // entries per row, the number of parent dofs coupling to a child dof is
187  // necessary. this, of course, is the number of degrees of freedom per
188  // cell
189  //
190  // increment dofs_per_cell since a useless diagonal element will be
191  // stored
192  IndexSet level_p1_relevant_dofs;
194  level_p1_relevant_dofs);
195  DynamicSparsityPattern dsp (this->sizes[level+1],
196  this->sizes[level],
197  level_p1_relevant_dofs);
198  typename DoFHandler<dim>::cell_iterator cell, endc = mg_dof.end(level);
199  for (cell=mg_dof.begin(level); cell != endc; ++cell)
200  if (cell->has_children() &&
201  ( mg_dof.get_triangulation().locally_owned_subdomain()==numbers::invalid_subdomain_id
202  || cell->level_subdomain_id()==mg_dof.get_triangulation().locally_owned_subdomain()
203  ))
204  {
205  cell->get_mg_dof_indices (dof_indices_parent);
206 
207  replace(this->mg_constrained_dofs, level, dof_indices_parent);
208 
211  for (unsigned int child=0; child<cell->n_children(); ++child)
212  {
213  // set an alias to the prolongation matrix for this child
214  const FullMatrix<double> &prolongation
215  = mg_dof.get_fe().get_prolongation_matrix (child,
216  cell->refinement_case());
217 
218  Assert (prolongation.n() != 0, ExcNoProlongation());
219 
220  cell->child(child)->get_mg_dof_indices (dof_indices_child);
221 
222  replace(this->mg_constrained_dofs, level+1, dof_indices_child);
223 
224  // now tag the entries in the
225  // matrix which will be used
226  // for this pair of parent/child
227  for (unsigned int i=0; i<dofs_per_cell; ++i)
228  {
229  entries.resize(0);
230  for (unsigned int j=0; j<dofs_per_cell; ++j)
231  if (prolongation(i,j) != 0)
232  entries.push_back (dof_indices_parent[j]);
233  dsp.add_entries (dof_indices_child[i],
234  entries.begin(), entries.end());
235  }
236  }
237  }
238 
239  internal::MatrixSelector<VectorType>::reinit(*prolongation_matrices[level],
240  *prolongation_sparsities[level],
241  level,
242  dsp,
243  mg_dof);
244  dsp.reinit(0,0);
245 
246  FullMatrix<double> prolongation;
247 
248  // now actually build the matrices
249  for (cell=mg_dof.begin(level); cell != endc; ++cell)
250  if (cell->has_children() &&
251  (mg_dof.get_triangulation().locally_owned_subdomain()==numbers::invalid_subdomain_id
252  || cell->level_subdomain_id()==mg_dof.get_triangulation().locally_owned_subdomain())
253  )
254  {
255  cell->get_mg_dof_indices (dof_indices_parent);
256 
257  replace(this->mg_constrained_dofs, level, dof_indices_parent);
258 
261  for (unsigned int child=0; child<cell->n_children(); ++child)
262  {
263  // set an alias to the prolongation matrix for this child
264  prolongation
265  = mg_dof.get_fe().get_prolongation_matrix (child,
266  cell->refinement_case());
267 
268  if (this->mg_constrained_dofs != nullptr &&
269  this->mg_constrained_dofs->have_boundary_indices())
270  for (unsigned int j=0; j<dofs_per_cell; ++j)
271  if (this->mg_constrained_dofs->is_boundary_index(level, dof_indices_parent[j]))
272  for (unsigned int i=0; i<dofs_per_cell; ++i)
273  prolongation(i,j) = 0.;
274 
275  cell->child(child)->get_mg_dof_indices (dof_indices_child);
276 
277  replace(this->mg_constrained_dofs, level+1, dof_indices_child);
278 
279  // now set the entries in the matrix
280  for (unsigned int i=0; i<dofs_per_cell; ++i)
281  prolongation_matrices[level]->set (dof_indices_child[i],
282  dofs_per_cell,
283  dof_indices_parent.data(),
284  &prolongation(i,0),
285  true);
286  }
287  }
288  prolongation_matrices[level]->compress(VectorOperation::insert);
289  }
290 
291  this->fill_and_communicate_copy_indices(mg_dof);
292 }
293 
294 
295 
296 template <typename VectorType>
297 void
299 {
300  for (unsigned int level = 0; level<prolongation_matrices.size(); ++level)
301  {
302  os << "Level " << level << std::endl;
303  prolongation_matrices[level]->print(os);
304  os << std::endl;
305  }
306 }
307 
308 
309 
310 template <typename VectorType>
311 std::size_t
313 {
315  for (unsigned int i=0; i<prolongation_matrices.size(); ++i)
316  result += prolongation_matrices[i]->memory_consumption()
317  + prolongation_sparsities[i]->memory_consumption();
318 
319  return result;
320 }
321 
322 
323 // explicit instantiation
324 #include "mg_transfer_prebuilt.inst"
325 
326 
327 DEAL_II_NAMESPACE_CLOSE
void initialize_constraints(const MGConstrainedDoFs &mg_constrained_dofs)
MGTransferPrebuilt()=default
void add_entries(const size_type row, ForwardIterator begin, ForwardIterator end, const bool indices_are_unique_and_sorted=false)
const types::subdomain_id invalid_subdomain_id
Definition: types.h:248
std::size_t memory_consumption() const
cell_iterator begin(const unsigned int level=0) const
Definition: dof_handler.cc:723
void build_matrices(const DoFHandler< dim, spacedim > &mg_dof)
bool is_boundary_index(const unsigned int level, const types::global_dof_index index) const
cell_iterator end() const
Definition: dof_handler.cc:751
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
void extract_locally_relevant_level_dofs(const DoFHandlerType &dof_handler, const unsigned int level, IndexSet &dof_set)
Definition: dof_tools.cc:1127
void print_matrices(std::ostream &os) const
std::size_t memory_consumption() const
size_type n() const
#define Assert(cond, exc)
Definition: exceptions.h:1142
void reinit(const size_type m, const size_type n, const IndexSet &rowset=IndexSet())
size_type n_constraints() const
const FiniteElement< dim, spacedim > & get_fe(const unsigned int index=0) const
const ConstraintMatrix & get_level_constraint_matrix(const unsigned int level) const
types::global_dof_index n_dofs() const
virtual void prolongate(const unsigned int to_level, VectorType &dst, const VectorType &src) const
bool is_identity_constrained(const size_type index) const
static ::ExceptionBase & ExcNotImplemented()
const Triangulation< dim, spacedim > & get_triangulation() const
const std::vector< std::pair< size_type, double > > * get_constraint_entries(const size_type line) const
bool have_boundary_indices() const
static ::ExceptionBase & ExcInternalError()
virtual void restrict_and_add(const unsigned int from_level, VectorType &dst, const VectorType &src) const