Reference documentation for deal.II version 8.5.1
dof_tools.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1999 - 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 #include <deal.II/base/thread_management.h>
17 #include <deal.II/base/quadrature_lib.h>
18 #include <deal.II/base/table.h>
19 #include <deal.II/base/template_constraints.h>
20 #include <deal.II/base/utilities.h>
21 #include <deal.II/lac/sparsity_pattern.h>
22 #include <deal.II/lac/dynamic_sparsity_pattern.h>
23 #include <deal.II/lac/trilinos_sparsity_pattern.h>
24 #include <deal.II/lac/block_sparsity_pattern.h>
25 #include <deal.II/lac/vector.h>
26 #include <deal.II/lac/constraint_matrix.h>
27 #include <deal.II/grid/tria.h>
28 #include <deal.II/grid/tria_iterator.h>
29 #include <deal.II/grid/intergrid_map.h>
30 #include <deal.II/grid/filtered_iterator.h>
31 #include <deal.II/grid/grid_tools.h>
32 #include <deal.II/dofs/dof_handler.h>
33 #include <deal.II/dofs/dof_accessor.h>
34 #include <deal.II/fe/fe.h>
35 #include <deal.II/fe/fe_values.h>
36 #include <deal.II/fe/fe_tools.h>
37 #include <deal.II/hp/dof_handler.h>
38 #include <deal.II/hp/fe_collection.h>
39 #include <deal.II/hp/fe_values.h>
40 #include <deal.II/hp/mapping_collection.h>
41 #include <deal.II/hp/q_collection.h>
42 #include <deal.II/dofs/dof_tools.h>
43 #include <deal.II/distributed/tria.h>
44 #include <deal.II/distributed/shared_tria.h>
45 
46 #include <algorithm>
47 #include <numeric>
48 
49 DEAL_II_NAMESPACE_OPEN
50 
51 
52 
53 namespace DoFTools
54 {
55  namespace internal
56  {
67  template <int dim,typename Number=double>
69  {
76  const Point<dim, Number> &rhs) const
77  {
78  for (unsigned int d=0; d<dim; ++d)
79  {
80  if (lhs[d] == rhs[d])
81  continue;
82  return lhs[d]<rhs[d];
83  }
84  return false;
85  }
86 
87  };
88 
89 
90 
91  // return an array that for each dof on the reference cell
92  // lists the corresponding vector component.
93  //
94  // if an element is non-primitive then we assign to each degree of freedom
95  // the following component:
96  // - if the nonzero components that belong to a shape function are not
97  // selected in the component_mask, then the shape function is assigned
98  // to the first nonzero vector component that corresponds to this
99  // shape function
100  // - otherwise, the shape function is assigned the first component selected
101  // in the component_mask that corresponds to this shape function
102  template <int dim, int spacedim>
103  std::vector<unsigned char>
104  get_local_component_association (const FiniteElement<dim,spacedim> &fe,
105  const ComponentMask &component_mask)
106  {
107  std::vector<unsigned char> local_component_association (fe.dofs_per_cell,
108  (unsigned char)(-1));
109 
110  // compute the component each local dof belongs to.
111  // if the shape function is primitive, then this
112  // is simple and we can just associate it with
113  // what system_to_component_index gives us
114  for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
115  if (fe.is_primitive(i))
116  local_component_association[i] =
117  fe.system_to_component_index(i).first;
118  else
119  // if the shape function is not primitive, then either use the
120  // component of the first nonzero component corresponding
121  // to this shape function (if the component is not specified
122  // in the component_mask), or the first component of this block
123  // that is listed in the component_mask (if the block this
124  // component corresponds to is indeed specified in the component
125  // mask)
126  {
127  const unsigned int first_comp =
129 
130  if ((fe.get_nonzero_components(i)
131  &
132  component_mask).n_selected_components(fe.n_components()) == 0)
133  local_component_association[i] = first_comp;
134  else
135  // pick the component selected. we know from the previous 'if'
136  // that within the components that are nonzero for this
137  // shape function there must be at least one for which the
138  // mask is true, so we will for sure run into the break()
139  // at one point
140  for (unsigned int c=first_comp; c<fe.n_components(); ++c)
141  if (component_mask[c] == true)
142  {
143  local_component_association[i] = c;
144  break;
145  }
146  }
147 
148  Assert (std::find (local_component_association.begin(),
149  local_component_association.end(),
150  (unsigned char)(-1))
151  ==
152  local_component_association.end(),
153  ExcInternalError());
154 
155  return local_component_association;
156  }
157 
158 
159  // this internal function assigns to each dof the respective component
160  // of the vector system.
161  //
162  // the output array dofs_by_component lists for each dof the
163  // corresponding vector component. if the DoFHandler is based on a
164  // parallel distributed triangulation then the output array is index by
165  // dof.locally_owned_dofs().index_within_set(indices[i])
166  //
167  // if an element is non-primitive then we assign to each degree of
168  // freedom the following component:
169  // - if the nonzero components that belong to a shape function are not
170  // selected in the component_mask, then the shape function is assigned
171  // to the first nonzero vector component that corresponds to this
172  // shape function
173  // - otherwise, the shape function is assigned the first component selected
174  // in the component_mask that corresponds to this shape function
175  template <typename DoFHandlerType>
176  void
177  get_component_association (const DoFHandlerType &dof,
178  const ComponentMask &component_mask,
179  std::vector<unsigned char> &dofs_by_component)
180  {
181  const ::hp::FECollection<DoFHandlerType::dimension,DoFHandlerType::space_dimension>
182  fe_collection (dof.get_fe());
183  Assert (fe_collection.n_components() < 256, ExcNotImplemented());
184  Assert (dofs_by_component.size() == dof.n_locally_owned_dofs(),
185  ExcDimensionMismatch(dofs_by_component.size(),
186  dof.n_locally_owned_dofs()));
187 
188  // next set up a table for the degrees of freedom on each of the
189  // cells (regardless of the fact whether it is listed in the
190  // component_select argument or not)
191  //
192  // for each element 'f' of the FECollection,
193  // local_component_association[f][d] then returns the vector
194  // component that degree of freedom 'd' belongs to
195  std::vector<std::vector<unsigned char> >
196  local_component_association (fe_collection.size());
197  for (unsigned int f=0; f<fe_collection.size(); ++f)
198  {
200  fe_collection[f];
201  local_component_association[f]
202  = get_local_component_association (fe, component_mask);
203  }
204 
205  // then loop over all cells and do the work
206  std::vector<types::global_dof_index> indices;
207  for (typename DoFHandlerType::active_cell_iterator c=dof.begin_active();
208  c!=dof.end(); ++ c)
209  if (c->is_locally_owned())
210  {
211  const unsigned int fe_index = c->active_fe_index();
212  const unsigned int dofs_per_cell = c->get_fe().dofs_per_cell;
213  indices.resize(dofs_per_cell);
214  c->get_dof_indices(indices);
215  for (unsigned int i=0; i<dofs_per_cell; ++i)
216  if (dof.locally_owned_dofs().is_element(indices[i]))
217  dofs_by_component[dof.locally_owned_dofs().index_within_set(indices[i])]
218  = local_component_association[fe_index][i];
219  }
220  }
221 
222 
223  // this is the function corresponding to the one above but working on
224  // blocks instead of components.
225  //
226  // the output array dofs_by_block lists for each dof the corresponding
227  // vector block. if the DoFHandler is based on a parallel distributed
228  // triangulation then the output array is index by
229  // dof.locally_owned_dofs().index_within_set(indices[i])
230  template <typename DoFHandlerType>
231  inline
232  void
233  get_block_association (const DoFHandlerType &dof,
234  std::vector<unsigned char> &dofs_by_block)
235  {
236  const ::hp::FECollection<DoFHandlerType::dimension,DoFHandlerType::space_dimension>
237  fe_collection (dof.get_fe());
238  Assert (fe_collection.n_components() < 256, ExcNotImplemented());
239  Assert (dofs_by_block.size() == dof.n_locally_owned_dofs(),
240  ExcDimensionMismatch(dofs_by_block.size(),
241  dof.n_locally_owned_dofs()));
242 
243  // next set up a table for the degrees of freedom on each of the
244  // cells (regardless of the fact whether it is listed in the
245  // component_select argument or not)
246  //
247  // for each element 'f' of the FECollection,
248  // local_block_association[f][d] then returns the vector block that
249  // degree of freedom 'd' belongs to
250  std::vector<std::vector<unsigned char> > local_block_association
251  (fe_collection.size());
252  for (unsigned int f=0; f<fe_collection.size(); ++f)
253  {
255  fe_collection[f];
256  local_block_association[f].resize(fe.dofs_per_cell,
257  (unsigned char)(-1));
258  for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
259  local_block_association[f][i] = fe.system_to_block_index(i).first;
260 
261  Assert (std::find (local_block_association[f].begin(),
262  local_block_association[f].end(),
263  (unsigned char)(-1))
264  ==
265  local_block_association[f].end(),
266  ExcInternalError());
267  }
268 
269  // then loop over all cells and do the work
270  std::vector<types::global_dof_index> indices;
271  for (typename DoFHandlerType::active_cell_iterator c=dof.begin_active();
272  c!=dof.end(); ++ c)
273  if (c->is_locally_owned())
274  {
275  const unsigned int fe_index = c->active_fe_index();
276  const unsigned int dofs_per_cell = c->get_fe().dofs_per_cell;
277  indices.resize(dofs_per_cell);
278  c->get_dof_indices(indices);
279  for (unsigned int i=0; i<dofs_per_cell; ++i)
280  if (dof.locally_owned_dofs().is_element(indices[i]))
281  dofs_by_block[dof.locally_owned_dofs().index_within_set(indices[i])]
282  = local_block_association[fe_index][i];
283  }
284  }
285  }
286 
287 
288 
289  template <typename DoFHandlerType, typename Number>
290  void distribute_cell_to_dof_vector (const DoFHandlerType &dof_handler,
291  const Vector<Number> &cell_data,
292  Vector<double> &dof_data,
293  const unsigned int component)
294  {
295  const unsigned int dim = DoFHandlerType::dimension;
296  const unsigned int spacedim = DoFHandlerType::space_dimension;
297  const Triangulation<dim,spacedim> &tria = dof_handler.get_triangulation();
298  (void)tria;
299 
300  AssertDimension (cell_data.size(), tria.n_active_cells());
301  AssertDimension (dof_data.size(), dof_handler.n_dofs());
302  AssertIndexRange (component, n_components(dof_handler));
303  Assert (fe_is_primitive(dof_handler) == true,
305 
306  // store a flag whether we should care about different components. this
307  // is just a simplification, we could ask for this at every single
308  // place equally well
309  const bool consider_components = (n_components(dof_handler) != 1);
310 
311  // zero out the components that we will touch
312  if (consider_components == false)
313  dof_data = 0;
314  else
315  {
316  std::vector<unsigned char> component_dofs (dof_handler.n_locally_owned_dofs());
317  internal::get_component_association (dof_handler,
318  dof_handler.get_fe().component_mask
319  (FEValuesExtractors::Scalar(component)),
320  component_dofs);
321 
322  for (unsigned int i=0; i<dof_data.size(); ++i)
323  if (component_dofs[i] == static_cast<unsigned char>(component))
324  dof_data(i) = 0;
325  }
326 
327  // count how often we have added a value in the sum for each dof
328  std::vector<unsigned char> touch_count (dof_handler.n_dofs(), 0);
329 
330  typename DoFHandlerType::active_cell_iterator cell = dof_handler.begin_active(),
331  endc = dof_handler.end();
332  std::vector<types::global_dof_index> dof_indices;
333  dof_indices.reserve (max_dofs_per_cell(dof_handler));
334 
335  for (unsigned int present_cell = 0; cell!=endc; ++cell, ++present_cell)
336  {
337  const unsigned int dofs_per_cell = cell->get_fe().dofs_per_cell;
338  dof_indices.resize (dofs_per_cell);
339  cell->get_dof_indices (dof_indices);
340 
341  for (unsigned int i=0; i<dofs_per_cell; ++i)
342  // consider this dof only if it is the right component. if there
343  // is only one component, short cut the test
344  if (!consider_components ||
345  (cell->get_fe().system_to_component_index(i).first == component))
346  {
347  // sum up contribution of the present_cell to this dof
348  dof_data(dof_indices[i]) += cell_data(present_cell);
349 
350  // note that we added another summand
351  ++touch_count[dof_indices[i]];
352  }
353  }
354 
355  // compute the mean value on all the dofs by dividing with the number
356  // of summands.
357  for (types::global_dof_index i=0; i<dof_handler.n_dofs(); ++i)
358  {
359  // assert that each dof was used at least once. this needs not be
360  // the case if the vector has more than one component
361  Assert (consider_components || (touch_count[i]!=0),
362  ExcInternalError());
363  if (touch_count[i] != 0)
364  dof_data(i) /= touch_count[i];
365  }
366  }
367 
368 
369 
370  template <int dim, int spacedim>
371  void
373  const ComponentMask &component_mask,
374  std::vector<bool> &selected_dofs)
375  {
376  const FiniteElement<dim,spacedim> &fe = dof.get_fe();
377  (void)fe;
378 
379  Assert(component_mask.represents_n_components(fe.n_components()),
380  ExcMessage ("The given component mask is not sized correctly to represent the "
381  "components of the given finite element."));
382  Assert(selected_dofs.size() == dof.n_locally_owned_dofs(),
383  ExcDimensionMismatch(selected_dofs.size(), dof.n_locally_owned_dofs()));
384 
385  // two special cases: no component is selected, and all components are
386  // selected; both rather stupid, but easy to catch
387  if (component_mask.n_selected_components(n_components(dof)) == 0)
388  {
389  std::fill_n (selected_dofs.begin(), dof.n_locally_owned_dofs(), false);
390  return;
391  }
392  else if (component_mask.n_selected_components(n_components(dof)) == n_components(dof))
393  {
394  std::fill_n (selected_dofs.begin(), dof.n_locally_owned_dofs(), true);
395  return;
396  }
397 
398 
399  // preset all values by false
400  std::fill_n (selected_dofs.begin(), dof.n_locally_owned_dofs(), false);
401 
402  // get the component association of each DoF and then select the ones
403  // that match the given set of blocks
404  std::vector<unsigned char> dofs_by_component (dof.n_locally_owned_dofs());
405  internal::get_component_association (dof, component_mask,
406  dofs_by_component);
407 
408  for (types::global_dof_index i=0; i<dof.n_locally_owned_dofs(); ++i)
409  if (component_mask[dofs_by_component[i]] == true)
410  selected_dofs[i] = true;
411  }
412 
413 
414  // TODO: Unify the following two functions with the non-hp case
415 
416  template <int dim, int spacedim>
417  void
419  const ComponentMask &component_mask,
420  std::vector<bool> &selected_dofs)
421  {
422  const FiniteElement<dim,spacedim> &fe = dof.begin_active()->get_fe();
423  (void)fe;
424 
425  Assert(component_mask.represents_n_components(fe.n_components()),
426  ExcMessage ("The given component mask is not sized correctly to represent the "
427  "components of the given finite element."));
428  Assert(selected_dofs.size() == dof.n_dofs(),
429  ExcDimensionMismatch(selected_dofs.size(), dof.n_dofs()));
430 
431  // two special cases: no component is selected, and all components are
432  // selected; both rather stupid, but easy to catch
433  if (component_mask.n_selected_components(n_components(dof)) == 0)
434  {
435  std::fill_n (selected_dofs.begin(), dof.n_dofs(), false);
436  return;
437  }
438  else if (component_mask.n_selected_components(n_components(dof)) == n_components(dof))
439  {
440  std::fill_n (selected_dofs.begin(), dof.n_dofs(), true);
441  return;
442  }
443 
444 
445  // preset all values by false
446  std::fill_n (selected_dofs.begin(), dof.n_dofs(), false);
447 
448  // get the component association of each DoF and then select the ones
449  // that match the given set of components
450  std::vector<unsigned char> dofs_by_component (dof.n_dofs());
451  internal::get_component_association (dof, component_mask,
452  dofs_by_component);
453 
454  for (types::global_dof_index i=0; i<dof.n_dofs(); ++i)
455  if (component_mask[dofs_by_component[i]] == true)
456  selected_dofs[i] = true;
457  }
458 
459 
460 
461  template <int dim, int spacedim>
462  void
464  const BlockMask &block_mask,
465  std::vector<bool> &selected_dofs)
466  {
467  // simply forward to the function that works based on a component mask
468  extract_dofs (dof, dof.get_fe().component_mask (block_mask),
469  selected_dofs);
470  }
471 
472 
473 
474  template <int dim, int spacedim>
475  void
477  const BlockMask &block_mask,
478  std::vector<bool> &selected_dofs)
479  {
480  // simply forward to the function that works based on a component mask
481  extract_dofs (dof, dof.get_fe().component_mask (block_mask),
482  selected_dofs);
483  }
484 
485 
486 
487  template<typename DoFHandlerType>
488  void
489  extract_level_dofs (const unsigned int level,
490  const DoFHandlerType &dof,
491  const ComponentMask &component_mask,
492  std::vector<bool> &selected_dofs)
493  {
495 
496  Assert(component_mask.represents_n_components(n_components(dof)),
497  ExcMessage ("The given component mask is not sized correctly to represent the "
498  "components of the given finite element."));
499  Assert(selected_dofs.size() == dof.n_dofs(level),
500  ExcDimensionMismatch(selected_dofs.size(), dof.n_dofs(level)));
501 
502  // two special cases: no component is selected, and all components are
503  // selected, both rather stupid, but easy to catch
504  if (component_mask.n_selected_components(n_components(dof)) == 0)
505  {
506  std::fill_n (selected_dofs.begin(), dof.n_dofs(level), false);
507  return;
508  }
509  else if (component_mask.n_selected_components(n_components(dof)) == n_components(dof))
510  {
511  std::fill_n (selected_dofs.begin(), dof.n_dofs(level), true);
512  return;
513  }
514 
515  // preset all values by false
516  std::fill_n (selected_dofs.begin(), dof.n_dofs(level), false);
517 
518  // next set up a table for the degrees of freedom on each of the cells
519  // whether it is something interesting or not
520  std::vector<unsigned char> local_component_asssociation
521  = internal::get_local_component_association (fe, component_mask);
522  std::vector<bool> local_selected_dofs (fe.dofs_per_cell);
523  for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
524  local_selected_dofs[i] = component_mask[local_component_asssociation[i]];
525 
526  // then loop over all cells and do work
527  std::vector<types::global_dof_index> indices(fe.dofs_per_cell);
528  typename DoFHandlerType::level_cell_iterator c;
529  for (c = dof.begin(level) ; c != dof.end(level) ; ++ c)
530  {
531  c->get_mg_dof_indices(indices);
532  for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
533  selected_dofs[indices[i]] = local_selected_dofs[i];
534  }
535  }
536 
537 
538 
539  template<typename DoFHandlerType>
540  void
541  extract_level_dofs (const unsigned int level,
542  const DoFHandlerType &dof,
543  const BlockMask &block_mask,
544  std::vector<bool> &selected_dofs)
545  {
546  // simply defer to the other extract_level_dofs() function
547  extract_level_dofs (level, dof, dof.get_fe().component_mask(block_mask),
548  selected_dofs);
549  }
550 
551 
552 
553  template <typename DoFHandlerType>
554  void
555  extract_boundary_dofs (const DoFHandlerType &dof_handler,
556  const ComponentMask &component_mask,
557  std::vector<bool> &selected_dofs,
558  const std::set<types::boundary_id> &boundary_ids)
559  {
561  (&dof_handler.get_triangulation())
562  == 0),
563  ExcMessage ("This function can not be used with distributed triangulations."
564  "See the documentation for more information."));
565 
566  IndexSet indices;
567  extract_boundary_dofs (dof_handler, component_mask,
568  indices, boundary_ids);
569 
570  // clear and reset array by default values
571  selected_dofs.clear ();
572  selected_dofs.resize (dof_handler.n_dofs(), false);
573 
574  // then convert the values computed above to the binary vector
575  indices.fill_binary_vector(selected_dofs);
576  }
577 
578 
579  template <typename DoFHandlerType>
580  void
581  extract_boundary_dofs (const DoFHandlerType &dof_handler,
582  const ComponentMask &component_mask,
583  IndexSet &selected_dofs,
584  const std::set<types::boundary_id> &boundary_ids)
585  {
586  Assert (component_mask.represents_n_components(n_components(dof_handler)),
587  ExcMessage ("Component mask has invalid size."));
588  Assert (boundary_ids.find (numbers::internal_face_boundary_id) == boundary_ids.end(),
590  const unsigned int dim=DoFHandlerType::dimension;
591 
592  // first reset output argument
593  selected_dofs.clear ();
594  selected_dofs.set_size(dof_handler.n_dofs());
595 
596  // let's see whether we have to check for certain boundary indicators
597  // or whether we can accept all
598  const bool check_boundary_id = (boundary_ids.size() != 0);
599 
600  // also see whether we have to check whether a certain vector component
601  // is selected, or all
602  const bool check_vector_component
603  = ((component_mask.represents_the_all_selected_mask() == false)
604  ||
605  (component_mask.n_selected_components(n_components(dof_handler)) !=
606  n_components(dof_handler)));
607 
608  std::vector<types::global_dof_index> face_dof_indices;
609  face_dof_indices.reserve (max_dofs_per_face(dof_handler));
610 
611  // now loop over all cells and check whether their faces are at the
612  // boundary. note that we need not take special care of single lines
613  // being at the boundary (using @p{cell->has_boundary_lines}), since we
614  // do not support boundaries of dimension dim-2, and so every isolated
615  // boundary line is also part of a boundary face which we will be
616  // visiting sooner or later
617  for (typename DoFHandlerType::active_cell_iterator cell=dof_handler.begin_active();
618  cell!=dof_handler.end(); ++cell)
619 
620  // only work on cells that are either locally owned or at least ghost
621  // cells
622  if (cell->is_artificial() == false)
623  for (unsigned int face=0;
624  face<GeometryInfo<DoFHandlerType::dimension>::faces_per_cell; ++face)
625  if (cell->at_boundary(face))
626  if (! check_boundary_id ||
627  (boundary_ids.find (cell->face(face)->boundary_id())
628  != boundary_ids.end()))
629  {
631  &fe = cell->get_fe();
632 
633  const unsigned int dofs_per_face = fe.dofs_per_face;
634  face_dof_indices.resize (dofs_per_face);
635  cell->face(face)->get_dof_indices (face_dof_indices,
636  cell->active_fe_index());
637 
638  for (unsigned int i=0; i<fe.dofs_per_face; ++i)
639  if (!check_vector_component)
640  selected_dofs.add_index (face_dof_indices[i]);
641  else
642  // check for component is required. somewhat tricky as
643  // usual for the case that the shape function is
644  // non-primitive, but use usual convention (see docs)
645  {
646  // first get at the cell-global number of a face dof,
647  // to ask the fe certain questions
648  const unsigned int cell_index
649  = (dim == 1 ?
650  i
651  :
652  (dim == 2 ?
653  (i<2*fe.dofs_per_vertex ? i : i+2*fe.dofs_per_vertex)
654  :
655  (dim == 3 ?
656  (i<4*fe.dofs_per_vertex ?
657  i
658  :
659  (i<4*fe.dofs_per_vertex+4*fe.dofs_per_line ?
660  i+4*fe.dofs_per_vertex
661  :
662  i+4*fe.dofs_per_vertex+8*fe.dofs_per_line))
663  :
665  if (fe.is_primitive (cell_index))
666  {
667  if (component_mask[fe.face_system_to_component_index(i).first]
668  == true)
669  selected_dofs.add_index (face_dof_indices[i]);
670  }
671  else // not primitive
672  {
673  const unsigned int first_nonzero_comp
675  Assert (first_nonzero_comp < fe.n_components(),
676  ExcInternalError());
677 
678  if (component_mask[first_nonzero_comp] == true)
679  selected_dofs.add_index (face_dof_indices[i]);
680  }
681  }
682  }
683  }
684 
685 
686 
687  template <typename DoFHandlerType>
688  void
689  extract_dofs_with_support_on_boundary (const DoFHandlerType &dof_handler,
690  const ComponentMask &component_mask,
691  std::vector<bool> &selected_dofs,
692  const std::set<types::boundary_id> &boundary_ids)
693  {
694  Assert (component_mask.represents_n_components (n_components(dof_handler)),
695  ExcMessage ("This component mask has the wrong size."));
696  Assert (boundary_ids.find (numbers::internal_face_boundary_id) == boundary_ids.end(),
698 
699  // let's see whether we have to check for certain boundary indicators
700  // or whether we can accept all
701  const bool check_boundary_id = (boundary_ids.size() != 0);
702 
703  // also see whether we have to check whether a certain vector component
704  // is selected, or all
705  const bool check_vector_component
706  = (component_mask.represents_the_all_selected_mask() == false);
707 
708  // clear and reset array by default values
709  selected_dofs.clear ();
710  selected_dofs.resize (dof_handler.n_dofs(), false);
711  std::vector<types::global_dof_index> cell_dof_indices;
712  cell_dof_indices.reserve (max_dofs_per_cell(dof_handler));
713 
714  // now loop over all cells and check whether their faces are at the
715  // boundary. note that we need not take special care of single lines
716  // being at the boundary (using @p{cell->has_boundary_lines}), since we
717  // do not support boundaries of dimension dim-2, and so every isolated
718  // boundary line is also part of a boundary face which we will be
719  // visiting sooner or later
720  for (typename DoFHandlerType::active_cell_iterator cell=dof_handler.begin_active();
721  cell!=dof_handler.end(); ++cell)
722  for (unsigned int face=0;
723  face<GeometryInfo<DoFHandlerType::dimension>::faces_per_cell; ++face)
724  if (cell->at_boundary(face))
725  if (! check_boundary_id ||
726  (boundary_ids.find (cell->face(face)->boundary_id())
727  != boundary_ids.end()))
728  {
730  = cell->get_fe();
731 
732  const unsigned int dofs_per_cell = fe.dofs_per_cell;
733  cell_dof_indices.resize (dofs_per_cell);
734  cell->get_dof_indices (cell_dof_indices);
735 
736  for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
737  if (fe.has_support_on_face(i,face))
738  {
739  if (!check_vector_component)
740  selected_dofs[cell_dof_indices[i]] = true;
741  else
742  // check for component is required. somewhat tricky
743  // as usual for the case that the shape function is
744  // non-primitive, but use usual convention (see docs)
745  {
746  if (fe.is_primitive (i))
747  selected_dofs[cell_dof_indices[i]]
748  = (component_mask[fe.system_to_component_index(i).first]
749  == true);
750  else // not primitive
751  {
752  const unsigned int first_nonzero_comp
754  Assert (first_nonzero_comp < fe.n_components(),
755  ExcInternalError());
756 
757  selected_dofs[cell_dof_indices[i]]
758  = (component_mask[first_nonzero_comp]
759  == true);
760  }
761  }
762  }
763  }
764  }
765 
766 
767 
768 
769  namespace internal
770  {
771  namespace
772  {
773  template <int spacedim>
774  void extract_hanging_node_dofs (const ::DoFHandler<1,spacedim> &dof_handler,
775  std::vector<bool> &selected_dofs)
776  {
777  Assert(selected_dofs.size() == dof_handler.n_dofs(),
778  ExcDimensionMismatch(selected_dofs.size(), dof_handler.n_dofs()));
779  // preset all values by false
780  std::fill_n (selected_dofs.begin(), dof_handler.n_dofs(), false);
781 
782  // there are no hanging nodes in 1d
783  }
784 
785 
786  template <int spacedim>
787  void extract_hanging_node_dofs (const ::DoFHandler<2,spacedim> &dof_handler,
788  std::vector<bool> &selected_dofs)
789  {
790  const unsigned int dim = 2;
791 
792  Assert(selected_dofs.size() == dof_handler.n_dofs(),
793  ExcDimensionMismatch(selected_dofs.size(), dof_handler.n_dofs()));
794  // preset all values by false
795  std::fill_n (selected_dofs.begin(), dof_handler.n_dofs(), false);
796 
797  const FiniteElement<dim,spacedim> &fe = dof_handler.get_fe();
798 
799  // this function is similar to the make_sparsity_pattern function,
800  // see there for more information
801  typename ::DoFHandler<dim,spacedim>::active_cell_iterator
802  cell = dof_handler.begin_active(),
803  endc = dof_handler.end();
804  for (; cell!=endc; ++cell)
805  for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
806  if (cell->face(face)->has_children())
807  {
808  const typename ::DoFHandler<dim,spacedim>::line_iterator
809  line = cell->face(face);
810 
811  for (unsigned int dof=0; dof!=fe.dofs_per_vertex; ++dof)
812  selected_dofs[line->child(0)->vertex_dof_index(1,dof)] = true;
813 
814  for (unsigned int child=0; child<2; ++child)
815  for (unsigned int dof=0; dof!=fe.dofs_per_line; ++dof)
816  selected_dofs[line->child(child)->dof_index(dof)] = true;
817  }
818  }
819 
820 
821  template <int spacedim>
822  void extract_hanging_node_dofs (const ::DoFHandler<3,spacedim> &dof_handler,
823  std::vector<bool> &selected_dofs)
824  {
825  const unsigned int dim = 3;
826 
827  Assert(selected_dofs.size() == dof_handler.n_dofs(),
828  ExcDimensionMismatch(selected_dofs.size(), dof_handler.n_dofs()));
829  // preset all values by false
830  std::fill_n (selected_dofs.begin(), dof_handler.n_dofs(), false);
831 
832  const FiniteElement<dim,spacedim> &fe = dof_handler.get_fe();
833 
834  // this function is similar to the make_sparsity_pattern function,
835  // see there for more information
836 
837  typename ::DoFHandler<dim,spacedim>::active_cell_iterator
838  cell = dof_handler.begin_active(),
839  endc = dof_handler.end();
840  for (; cell!=endc; ++cell)
841  for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
842  if (cell->face(f)->has_children())
843  {
844  const typename ::DoFHandler<dim,spacedim>::face_iterator
845  face = cell->face(f);
846 
847  for (unsigned int dof=0; dof!=fe.dofs_per_vertex; ++dof)
848  selected_dofs[face->child(0)->vertex_dof_index(2,dof)] = true;
849 
850  // dof numbers on the centers of the lines bounding this
851  // face
852  for (unsigned int line=0; line<4; ++line)
853  for (unsigned int dof=0; dof!=fe.dofs_per_vertex; ++dof)
854  selected_dofs[face->line(line)->child(0)->vertex_dof_index(1,dof)] = true;
855 
856  // next the dofs on the lines interior to the face; the
857  // order of these lines is laid down in the FiniteElement
858  // class documentation
859  for (unsigned int dof=0; dof<fe.dofs_per_line; ++dof)
860  selected_dofs[face->child(0)->line(1)->dof_index(dof)] = true;
861  for (unsigned int dof=0; dof<fe.dofs_per_line; ++dof)
862  selected_dofs[face->child(1)->line(2)->dof_index(dof)] = true;
863  for (unsigned int dof=0; dof<fe.dofs_per_line; ++dof)
864  selected_dofs[face->child(2)->line(3)->dof_index(dof)] = true;
865  for (unsigned int dof=0; dof<fe.dofs_per_line; ++dof)
866  selected_dofs[face->child(3)->line(0)->dof_index(dof)] = true;
867 
868  // dofs on the bordering lines
869  for (unsigned int line=0; line<4; ++line)
870  for (unsigned int child=0; child<2; ++child)
871  for (unsigned int dof=0; dof!=fe.dofs_per_line; ++dof)
872  selected_dofs[face->line(line)->child(child)->dof_index(dof)] = true;
873 
874  // finally, for the dofs interior to the four child faces
875  for (unsigned int child=0; child<4; ++child)
876  for (unsigned int dof=0; dof!=fe.dofs_per_quad; ++dof)
877  selected_dofs[face->child(child)->dof_index(dof)] = true;
878  }
879  }
880  }
881  }
882 
883 
884 
885  template <int dim, int spacedim>
886  void
887 
889  std::vector<bool> &selected_dofs)
890  {
891  internal::extract_hanging_node_dofs (dof_handler,
892  selected_dofs);
893  }
894 
895 
896 
897  template <typename DoFHandlerType>
898  void
899  extract_subdomain_dofs (const DoFHandlerType &dof_handler,
900  const types::subdomain_id subdomain_id,
901  std::vector<bool> &selected_dofs)
902  {
903  Assert(selected_dofs.size() == dof_handler.n_dofs(),
904  ExcDimensionMismatch(selected_dofs.size(), dof_handler.n_dofs()));
905 
906  // preset all values by false
907  std::fill_n (selected_dofs.begin(), dof_handler.n_dofs(), false);
908 
909  std::vector<types::global_dof_index> local_dof_indices;
910  local_dof_indices.reserve (max_dofs_per_cell(dof_handler));
911 
912  // this function is similar to the make_sparsity_pattern function, see
913  // there for more information
914  typename DoFHandlerType::active_cell_iterator
915  cell = dof_handler.begin_active(),
916  endc = dof_handler.end();
917  for (; cell!=endc; ++cell)
918  if (cell->subdomain_id() == subdomain_id)
919  {
920  const unsigned int dofs_per_cell = cell->get_fe().dofs_per_cell;
921  local_dof_indices.resize (dofs_per_cell);
922  cell->get_dof_indices (local_dof_indices);
923  for (unsigned int i=0; i<dofs_per_cell; ++i)
924  selected_dofs[local_dof_indices[i]] = true;
925  };
926  }
927 
928 
929 
930  template <typename DoFHandlerType>
931  void
932  extract_locally_owned_dofs (const DoFHandlerType &dof_handler,
933  IndexSet &dof_set)
934  {
935  // collect all the locally owned dofs
936  dof_set = dof_handler.locally_owned_dofs();
937  dof_set.compress ();
938  }
939 
940 
941 
942  template <typename DoFHandlerType>
943  void
944  extract_locally_active_dofs (const DoFHandlerType &dof_handler,
945  IndexSet &dof_set)
946  {
947  // collect all the locally owned dofs
948  dof_set = dof_handler.locally_owned_dofs();
949 
950  // add the DoF on the adjacent ghost cells to the IndexSet, cache them
951  // in a set. need to check each dof manually because we can't be sure
952  // that the dof range of locally_owned_dofs is really contiguous.
953  std::vector<types::global_dof_index> dof_indices;
954  std::set<types::global_dof_index> global_dof_indices;
955 
956  typename DoFHandlerType::active_cell_iterator cell = dof_handler.begin_active(),
957  endc = dof_handler.end();
958  for (; cell!=endc; ++cell)
959  if (cell->is_locally_owned())
960  {
961  dof_indices.resize(cell->get_fe().dofs_per_cell);
962  cell->get_dof_indices(dof_indices);
963 
964  for (std::vector<types::global_dof_index>::iterator it=dof_indices.begin();
965  it!=dof_indices.end();
966  ++it)
967  if (!dof_set.is_element(*it))
968  global_dof_indices.insert(*it);
969  }
970 
971  dof_set.add_indices(global_dof_indices.begin(), global_dof_indices.end());
972 
973  dof_set.compress();
974  }
975 
976 
977 
978  template <typename DoFHandlerType>
979  void
980  extract_locally_relevant_dofs (const DoFHandlerType &dof_handler,
981  IndexSet &dof_set)
982  {
983  // collect all the locally owned dofs
984  dof_set = dof_handler.locally_owned_dofs();
985 
986  // now add the DoF on the adjacent ghost cells to the IndexSet
987 
988  // Note: For certain meshes (in particular in 3D and with many
989  // processors), it is really necessary to cache intermediate data. After
990  // trying several objects such as std::set, a vector that is always kept
991  // sorted, and a vector that is initially unsorted and sorted once at the
992  // end, the latter has been identified to provide the best performance.
993  // Martin Kronbichler
994  std::vector<types::global_dof_index> dof_indices;
995  std::vector<types::global_dof_index> dofs_on_ghosts;
996 
997  typename DoFHandlerType::active_cell_iterator cell = dof_handler.begin_active(),
998  endc = dof_handler.end();
999  for (; cell!=endc; ++cell)
1000  if (cell->is_ghost())
1001  {
1002  dof_indices.resize(cell->get_fe().dofs_per_cell);
1003  cell->get_dof_indices(dof_indices);
1004  for (unsigned int i=0; i<dof_indices.size(); ++i)
1005  if (!dof_set.is_element(dof_indices[i]))
1006  dofs_on_ghosts.push_back(dof_indices[i]);
1007  }
1008 
1009  // sort, compress out duplicates, fill into index set
1010  std::sort(dofs_on_ghosts.begin(), dofs_on_ghosts.end());
1011  dof_set.add_indices(dofs_on_ghosts.begin(), std::unique(dofs_on_ghosts.begin(),
1012  dofs_on_ghosts.end()));
1013  dof_set.compress();
1014  }
1015 
1016 
1017  template <typename DoFHandlerType>
1018  void
1019  extract_locally_relevant_level_dofs (const DoFHandlerType &dof_handler,
1020  const unsigned int level,
1021  IndexSet &dof_set)
1022  {
1023  // collect all the locally owned dofs
1024  dof_set = dof_handler.locally_owned_mg_dofs(level);
1025 
1026  // add the DoF on the adjacent ghost cells to the IndexSet
1027 
1028  // Note: For certain meshes (in particular in 3D and with many
1029  // processors), it is really necessary to cache intermediate data. After
1030  // trying several objects such as std::set, a vector that is always kept
1031  // sorted, and a vector that is initially unsorted and sorted once at the
1032  // end, the latter has been identified to provide the best performance.
1033  // Martin Kronbichler
1034  std::vector<types::global_dof_index> dof_indices;
1035  std::vector<types::global_dof_index> dofs_on_ghosts;
1036 
1037  typename DoFHandlerType::cell_iterator cell = dof_handler.begin(level),
1038  endc = dof_handler.end(level);
1039  for (; cell!=endc; ++cell)
1040  {
1041  const types::subdomain_id id = cell->level_subdomain_id();
1042 
1043  // skip artificial and own cells (only look at ghost cells)
1044  if (id == dof_handler.get_triangulation().locally_owned_subdomain()
1046  continue;
1047 
1048  dof_indices.resize(cell->get_fe().dofs_per_cell);
1049  cell->get_mg_dof_indices(dof_indices);
1050  for (unsigned int i=0; i<dof_indices.size(); ++i)
1051  if (!dof_set.is_element(dof_indices[i]))
1052  dofs_on_ghosts.push_back(dof_indices[i]);
1053  }
1054 
1055  // sort, compress out duplicates, fill into index set
1056  std::sort(dofs_on_ghosts.begin(), dofs_on_ghosts.end());
1057  dof_set.add_indices(dofs_on_ghosts.begin(), std::unique(dofs_on_ghosts.begin(),
1058  dofs_on_ghosts.end()));
1059 
1060  dof_set.compress();
1061  }
1062 
1063  template <typename DoFHandlerType>
1064  void
1065  extract_constant_modes (const DoFHandlerType &dof_handler,
1066  const ComponentMask &component_mask,
1067  std::vector<std::vector<bool> > &constant_modes)
1068  {
1069  const unsigned int n_components = dof_handler.get_fe().n_components();
1070  Assert (component_mask.represents_n_components(n_components),
1071  ExcDimensionMismatch(n_components,
1072  component_mask.size()));
1073 
1074  std::vector<unsigned char> dofs_by_component (dof_handler.n_locally_owned_dofs());
1075  internal::get_component_association (dof_handler, component_mask,
1076  dofs_by_component);
1077  unsigned int n_selected_dofs = 0;
1078  for (unsigned int i=0; i<n_components; ++i)
1079  if (component_mask[i] == true)
1080  n_selected_dofs += std::count (dofs_by_component.begin(),
1081  dofs_by_component.end(), i);
1082 
1083  // Find local numbering within the selected components
1084  const IndexSet &locally_owned_dofs = dof_handler.locally_owned_dofs();
1085  std::vector<unsigned int> component_numbering(locally_owned_dofs.n_elements(),
1087  for (unsigned int i=0, count=0; i<locally_owned_dofs.n_elements(); ++i)
1088  if (component_mask[dofs_by_component[i]])
1089  component_numbering[i] = count++;
1090 
1091  // get the element constant modes and find a translation table between
1092  // index in the constant modes and the components.
1093  //
1094  // TODO: We might be able to extend this also for elements which do not
1095  // have the same constant modes, but that is messy...
1096  const ::hp::FECollection<DoFHandlerType::dimension,DoFHandlerType::space_dimension>
1097  fe_collection (dof_handler.get_fe());
1098  std::vector<Table<2,bool> > element_constant_modes;
1099  std::vector<std::vector<std::pair<unsigned int, unsigned int> > >
1100  constant_mode_to_component_translation(n_components);
1101  unsigned int n_constant_modes = 0;
1102  for (unsigned int f=0; f<fe_collection.size(); ++f)
1103  {
1104  std::pair<Table<2,bool>, std::vector<unsigned int> > data
1105  = fe_collection[f].get_constant_modes();
1106  element_constant_modes.push_back(data.first);
1107  if (f==0)
1108  for (unsigned int i=0; i<data.second.size(); ++i)
1109  if (component_mask[data.second[i]])
1110  constant_mode_to_component_translation[data.second[i]].
1111  push_back(std::make_pair(n_constant_modes++,i));
1112  AssertDimension(element_constant_modes.back().n_rows(),
1113  element_constant_modes[0].n_rows());
1114  }
1115 
1116  // First count the number of dofs in the current component.
1117  constant_modes.clear ();
1118  constant_modes.resize (n_constant_modes, std::vector<bool>(n_selected_dofs,
1119  false));
1120 
1121  // Loop over all owned cells and ask the element for the constant modes
1122 
1123  typename DoFHandlerType::active_cell_iterator cell = dof_handler.begin_active(),
1124  endc = dof_handler.end();
1125  std::vector<types::global_dof_index> dof_indices;
1126  for (; cell!=endc; ++cell)
1127  if (cell->is_locally_owned())
1128  {
1129  dof_indices.resize(cell->get_fe().dofs_per_cell);
1130  cell->get_dof_indices(dof_indices);
1131 
1132  for (unsigned int i=0; i<dof_indices.size(); ++i)
1133  if (locally_owned_dofs.is_element(dof_indices[i]))
1134  {
1135  const unsigned int loc_index =
1136  locally_owned_dofs.index_within_set(dof_indices[i]);
1137  const unsigned int comp = dofs_by_component[loc_index];
1138  if (component_mask[comp])
1139  for (unsigned int j=0; j<constant_mode_to_component_translation[comp].size(); ++j)
1140  constant_modes[constant_mode_to_component_translation[comp][j].first]
1141  [component_numbering[loc_index]] =
1142  element_constant_modes[cell->active_fe_index()]
1143  (constant_mode_to_component_translation[comp][j].second,i);
1144  }
1145  }
1146  }
1147 
1148 
1149 
1150  template <typename DoFHandlerType>
1151  void
1152  get_active_fe_indices (const DoFHandlerType &dof_handler,
1153  std::vector<unsigned int> &active_fe_indices)
1154  {
1155  AssertDimension (active_fe_indices.size(), dof_handler.get_triangulation().n_active_cells());
1156 
1157  typename DoFHandlerType::active_cell_iterator
1158  cell = dof_handler.begin_active(),
1159  endc = dof_handler.end();
1160  for (; cell!=endc; ++cell)
1161  active_fe_indices[cell->active_cell_index()] = cell->active_fe_index();
1162  }
1163 
1164  template <typename DoFHandlerType>
1165  std::vector<IndexSet>
1166  locally_owned_dofs_per_subdomain (const DoFHandlerType &dof_handler)
1167  {
1168  Assert(dof_handler.n_dofs() > 0,
1169  ExcMessage("The given DoFHandler has no DoFs."));
1170 
1171  // If the Triangulation is distributed, the only thing we can usefully
1172  // ask is for its locally owned subdomain
1173  Assert ((dynamic_cast<const parallel::distributed::
1174  Triangulation<DoFHandlerType::dimension,DoFHandlerType::space_dimension> *>
1175  (&dof_handler.get_triangulation()) == 0),
1176  ExcMessage ("For parallel::distributed::Triangulation objects and "
1177  "associated DoF handler objects, asking for any information "
1178  "related to a subdomain other than the locally owned one does "
1179  "not make sense."));
1180 
1181  // The following is a random process (flip of a coin), thus should be called once only.
1182  std::vector< ::types::subdomain_id > subdomain_association (dof_handler.n_dofs ());
1183  ::DoFTools::get_subdomain_association (dof_handler, subdomain_association);
1184 
1185  // We have no MPI communicator with a serial computation and the subdomains
1186  // can be set to arbitrary values. In case of a parallel Triangulation,
1187  // we can check that we don't have more subdomains than processors.
1188  // Note that max_element is well-defined because subdomain_association
1189  // is non-empty (n_dofs()>0).
1190  const unsigned int n_subdomains
1192  (&dof_handler.get_triangulation()) == 0
1193  ?
1194  (1+*std::max_element (subdomain_association.begin (),
1195  subdomain_association.end ()))
1196  :
1199  (&dof_handler.get_triangulation())->get_communicator()));
1200  Assert (n_subdomains >
1201  *std::max_element (subdomain_association.begin (),
1202  subdomain_association.end ()),
1203  ExcInternalError());
1204 
1205  std::vector<::IndexSet> index_sets (n_subdomains,
1206  ::IndexSet(dof_handler.n_dofs()));
1207 
1208  // loop over subdomain_association and populate IndexSet when a
1209  // change in subdomain ID is found
1210  ::types::global_dof_index i_min = 0;
1211  ::types::global_dof_index this_subdomain = subdomain_association[0];
1212 
1213  for (::types::global_dof_index index = 1;
1214  index < subdomain_association.size (); ++index)
1215  {
1216  //found index different from the current one
1217  if (subdomain_association[index] != this_subdomain)
1218  {
1219  index_sets[this_subdomain].add_range (i_min, index);
1220  i_min = index;
1221  this_subdomain = subdomain_association[index];
1222  }
1223  }
1224 
1225  // the very last element is of different index
1226  if (i_min == subdomain_association.size () - 1)
1227  {
1228  index_sets[this_subdomain].add_index (i_min);
1229  }
1230 
1231  // otherwise there are at least two different indices
1232  else
1233  {
1234  index_sets[this_subdomain].add_range (
1235  i_min, subdomain_association.size ());
1236  }
1237 
1238  for (unsigned int i = 0; i < n_subdomains; i++)
1239  index_sets[i].compress ();
1240 
1241  return index_sets;
1242  }
1243 
1244  template <typename DoFHandlerType>
1245  std::vector<IndexSet>
1246  locally_relevant_dofs_per_subdomain (const DoFHandlerType &dof_handler)
1247  {
1248  // If the Triangulation is distributed, the only thing we can usefully
1249  // ask is for its locally owned subdomain
1250  Assert ((dynamic_cast<const parallel::distributed::
1251  Triangulation<DoFHandlerType::dimension,DoFHandlerType::space_dimension> *>
1252  (&dof_handler.get_triangulation()) == 0),
1253  ExcMessage ("For parallel::distributed::Triangulation objects and "
1254  "associated DoF handler objects, asking for any information "
1255  "related to a subdomain other than the locally owned one does "
1256  "not make sense."));
1257 
1258  // Collect all the locally owned DoFs
1259  // Note: Even though the distribution of DoFs by the locally_owned_dofs_per_subdomain
1260  // function is pseudo-random, we will collect all the DoFs on the subdomain
1261  // and its layer cell. Therefore, the random nature of this function does
1262  // not play a role in the extraction of the locally relevant DoFs
1263  std::vector<IndexSet> dof_set = locally_owned_dofs_per_subdomain(dof_handler);
1264  const ::types::subdomain_id n_subdomains = dof_set.size();
1265 
1266  // Add the DoFs on the adjacent (equivalent ghost) cells to the IndexSet,
1267  // cache them in a set. Need to check each DoF manually because we can't
1268  // be sure that the DoF range of locally_owned_dofs is really contiguous.
1269  for (::types::subdomain_id subdomain_id = 0;
1270  subdomain_id < n_subdomains; ++subdomain_id)
1271  {
1272  // Extract the layer of cells around this subdomain
1273  std_cxx11::function<bool (const typename DoFHandlerType::active_cell_iterator &)> predicate
1274  = IteratorFilters::SubdomainEqualTo(subdomain_id);
1275  const std::vector<typename DoFHandlerType::active_cell_iterator>
1276  active_halo_layer = GridTools::compute_active_cell_halo_layer (dof_handler,
1277  predicate);
1278 
1279  // Extract DoFs associated with halo layer
1280  std::vector<types::global_dof_index> local_dof_indices;
1281  std::set<types::global_dof_index> subdomain_halo_global_dof_indices;
1282  for (typename std::vector<typename DoFHandlerType::active_cell_iterator>::const_iterator
1283  it_cell = active_halo_layer.begin(); it_cell!=active_halo_layer.end(); ++it_cell)
1284  {
1285  const typename DoFHandlerType::active_cell_iterator &cell = *it_cell;
1286  Assert(cell->subdomain_id() != subdomain_id,
1287  ExcMessage("The subdomain ID of the halo cell should not match that of the vector entry."));
1288 
1289  local_dof_indices.resize(cell->get_fe().dofs_per_cell);
1290  cell->get_dof_indices(local_dof_indices);
1291 
1292  for (std::vector<types::global_dof_index>::iterator it=local_dof_indices.begin();
1293  it!=local_dof_indices.end();
1294  ++it)
1295  subdomain_halo_global_dof_indices.insert(*it);
1296  }
1297 
1298  dof_set[subdomain_id].add_indices(subdomain_halo_global_dof_indices.begin(),
1299  subdomain_halo_global_dof_indices.end());
1300 
1301  dof_set[subdomain_id].compress();
1302  }
1303 
1304  return dof_set;
1305  }
1306 
1307  template <typename DoFHandlerType>
1308  void
1309  get_subdomain_association (const DoFHandlerType &dof_handler,
1310  std::vector<types::subdomain_id> &subdomain_association)
1311  {
1312  // if the Triangulation is distributed, the only thing we can usefully
1313  // ask is for its locally owned subdomain
1314  Assert ((dynamic_cast<const parallel::distributed::
1315  Triangulation<DoFHandlerType::dimension,DoFHandlerType::space_dimension> *>
1316  (&dof_handler.get_triangulation()) == 0),
1317  ExcMessage ("For parallel::distributed::Triangulation objects and "
1318  "associated DoF handler objects, asking for any subdomain other "
1319  "than the locally owned one does not make sense."));
1320 
1321  Assert(subdomain_association.size() == dof_handler.n_dofs(),
1322  ExcDimensionMismatch(subdomain_association.size(),
1323  dof_handler.n_dofs()));
1324 
1325  Assert(dof_handler.n_dofs() > 0,
1326  ExcMessage("Number of DoF is not positive. "
1327  "This could happen when the function is called before NumberCache is written."));
1328 
1329  // In case this function is executed with parallel::shared::Triangulation
1330  // with possibly artifical cells, we need to take "true" subdomain IDs (i.e. without
1331  // artificial cells). Otherwise we are good to use subdomain_id as stored
1332  // in cell->subdomain_id().
1333  std::vector<types::subdomain_id> cell_owners (dof_handler.get_triangulation().n_active_cells());
1335  *tr = (dynamic_cast<const parallel::shared::Triangulation<DoFHandlerType::dimension,
1336  DoFHandlerType::space_dimension>*> (&dof_handler.get_triangulation())))
1337  {
1338  cell_owners = tr->get_true_subdomain_ids_of_cells();
1339  Assert (tr->get_true_subdomain_ids_of_cells().size() == tr->n_active_cells(),
1340  ExcInternalError());
1341  }
1342  else
1343  {
1344  for (typename DoFHandlerType::active_cell_iterator cell = dof_handler.begin_active();
1345  cell!= dof_handler.end(); cell++)
1346  if (cell->is_locally_owned())
1347  cell_owners[cell->active_cell_index()] = cell->subdomain_id();
1348  }
1349 
1350  // preset all values by an invalid value
1351  std::fill_n (subdomain_association.begin(), dof_handler.n_dofs(),
1353 
1354  std::vector<types::global_dof_index> local_dof_indices;
1355  local_dof_indices.reserve (max_dofs_per_cell(dof_handler));
1356 
1357  // pseudo-randomly assign variables which lie on the interface between
1358  // subdomains to each of the two or more
1359  bool coin_flip = true;
1360 
1361  // loop over all cells and record which subdomain a DoF belongs to.
1362  // toss a coin in case it is on an interface
1363  typename DoFHandlerType::active_cell_iterator
1364  cell = dof_handler.begin_active(),
1365  endc = dof_handler.end();
1366  for (; cell!=endc; ++cell)
1367  {
1368  const types::subdomain_id subdomain_id = cell_owners[cell->active_cell_index()];
1369  const unsigned int dofs_per_cell = cell->get_fe().dofs_per_cell;
1370  local_dof_indices.resize (dofs_per_cell);
1371  cell->get_dof_indices (local_dof_indices);
1372 
1373  // set subdomain ids. if dofs already have their values set then
1374  // they must be on partition interfaces. in that case randomly
1375  // assign them to either the previous association or the current
1376  // one, where we take "random" to be "once this way once that way"
1377  for (unsigned int i=0; i<dofs_per_cell; ++i)
1378  if (subdomain_association[local_dof_indices[i]] ==
1380  subdomain_association[local_dof_indices[i]] = subdomain_id;
1381  else
1382  {
1383  if (coin_flip == true)
1384  subdomain_association[local_dof_indices[i]] = subdomain_id;
1385  coin_flip = !coin_flip;
1386  }
1387  }
1388 
1389  Assert (std::find (subdomain_association.begin(),
1390  subdomain_association.end(),
1392  == subdomain_association.end(),
1393  ExcInternalError());
1394  }
1395 
1396 
1397 
1398  template <typename DoFHandlerType>
1399  unsigned int
1400  count_dofs_with_subdomain_association (const DoFHandlerType &dof_handler,
1401  const types::subdomain_id subdomain)
1402  {
1403  std::vector<types::subdomain_id> subdomain_association (dof_handler.n_dofs());
1404  get_subdomain_association (dof_handler, subdomain_association);
1405 
1406  return std::count (subdomain_association.begin(),
1407  subdomain_association.end(),
1408  subdomain);
1409  }
1410 
1411 
1412 
1413  template <typename DoFHandlerType>
1414  IndexSet
1415  dof_indices_with_subdomain_association (const DoFHandlerType &dof_handler,
1416  const types::subdomain_id subdomain)
1417  {
1418 
1419  // If we have a distributed::Triangulation only allow locally_owned
1420  // subdomain.
1421  Assert (
1422  (dof_handler.get_triangulation().locally_owned_subdomain() == numbers::invalid_subdomain_id)
1423  ||
1424  (subdomain == dof_handler.get_triangulation().locally_owned_subdomain()),
1425  ExcMessage ("For parallel::distributed::Triangulation objects and "
1426  "associated DoF handler objects, asking for any subdomain other "
1427  "than the locally owned one does not make sense."));
1428 
1429  IndexSet index_set (dof_handler.n_dofs());
1430 
1431  std::vector<types::global_dof_index> local_dof_indices;
1432  local_dof_indices.reserve (max_dofs_per_cell(dof_handler));
1433 
1434  // first generate an unsorted list of all indices which we fill from
1435  // the back. could also insert them directly into the IndexSet, but
1436  // that inserts indices in the middle, which is an O(n^2) algorithm and
1437  // hence too expensive. Could also use std::set, but that is in general
1438  // more expensive than a vector
1439  std::vector<types::global_dof_index> subdomain_indices;
1440 
1441  typename DoFHandlerType::active_cell_iterator
1442  cell = dof_handler.begin_active(),
1443  endc = dof_handler.end();
1444  for (; cell!=endc; ++cell)
1445  if ((cell->is_artificial() == false)
1446  &&
1447  (cell->subdomain_id() == subdomain))
1448  {
1449  const unsigned int dofs_per_cell = cell->get_fe().dofs_per_cell;
1450  local_dof_indices.resize (dofs_per_cell);
1451  cell->get_dof_indices (local_dof_indices);
1452  subdomain_indices.insert(subdomain_indices.end(),
1453  local_dof_indices.begin(),
1454  local_dof_indices.end());
1455  }
1456  // sort indices and remove duplicates
1457  std::sort (subdomain_indices.begin(), subdomain_indices.end());
1458  subdomain_indices.erase (std::unique(subdomain_indices.begin(),
1459  subdomain_indices.end()),
1460  subdomain_indices.end());
1461 
1462  // insert into IndexSet
1463  index_set.add_indices (subdomain_indices.begin(), subdomain_indices.end());
1464  index_set.compress ();
1465 
1466  return index_set;
1467  }
1468 
1469 
1470 
1471  template <typename DoFHandlerType>
1472  void
1473  count_dofs_with_subdomain_association (const DoFHandlerType &dof_handler,
1474  const types::subdomain_id subdomain,
1475  std::vector<unsigned int> &n_dofs_on_subdomain)
1476  {
1477  Assert (n_dofs_on_subdomain.size() == dof_handler.get_fe().n_components(),
1478  ExcDimensionMismatch (n_dofs_on_subdomain.size(),
1479  dof_handler.get_fe().n_components()));
1480  std::fill (n_dofs_on_subdomain.begin(), n_dofs_on_subdomain.end(), 0);
1481 
1482  // in debug mode, make sure that there are some cells at least with
1483  // this subdomain id
1484 #ifdef DEBUG
1485  {
1486  bool found = false;
1487  for (typename Triangulation<DoFHandlerType::dimension,
1488  DoFHandlerType::space_dimension>::active_cell_iterator
1489  cell=dof_handler.get_triangulation().begin_active();
1490  cell!=dof_handler.get_triangulation().end(); ++cell)
1491  if (cell->subdomain_id() == subdomain)
1492  {
1493  found = true;
1494  break;
1495  }
1496  Assert (found == true,
1497  ExcMessage ("There are no cells for the given subdomain!"));
1498  }
1499 #endif
1500 
1501  std::vector<types::subdomain_id> subdomain_association (dof_handler.n_dofs());
1502  get_subdomain_association (dof_handler, subdomain_association);
1503 
1504  std::vector<unsigned char> component_association (dof_handler.n_dofs());
1505  internal::get_component_association (dof_handler, std::vector<bool>(),
1506  component_association);
1507 
1508  for (unsigned int c=0; c<dof_handler.get_fe().n_components(); ++c)
1509  {
1510  for (types::global_dof_index i=0; i<dof_handler.n_dofs(); ++i)
1511  if ((subdomain_association[i] == subdomain) &&
1512  (component_association[i] == static_cast<unsigned char>(c)))
1513  ++n_dofs_on_subdomain[c];
1514  }
1515  }
1516 
1517 
1518 
1519  namespace internal
1520  {
1521  // TODO: why is this function so complicated? It would be nice to have
1522  // comments that explain why we can't just loop over all components and
1523  // count the entries in dofs_by_component that have this component's
1524  // index
1525  template <int dim, int spacedim>
1526  void
1527  resolve_components (const FiniteElement<dim,spacedim> &fe,
1528  const std::vector<unsigned char> &dofs_by_component,
1529  const std::vector<unsigned int> &target_component,
1530  const bool only_once,
1531  std::vector<types::global_dof_index> &dofs_per_component,
1532  unsigned int &component)
1533  {
1534  for (unsigned int b=0; b<fe.n_base_elements(); ++b)
1535  {
1536  const FiniteElement<dim,spacedim> &base = fe.base_element(b);
1537  // Dimension of base element
1538  unsigned int d = base.n_components();
1539 
1540  for (unsigned int m=0; m<fe.element_multiplicity(b); ++m)
1541  {
1542  if (base.n_base_elements() > 1)
1543  resolve_components(base, dofs_by_component, target_component,
1544  only_once, dofs_per_component, component);
1545  else
1546  {
1547  for (unsigned int dd=0; dd<d; ++dd,++component)
1548  dofs_per_component[target_component[component]]
1549  += std::count(dofs_by_component.begin(),
1550  dofs_by_component.end(),
1551  component);
1552 
1553  // if we have non-primitive FEs and want all components
1554  // to show the number of dofs, need to copy the result to
1555  // those components
1556  if (!base.is_primitive() && !only_once)
1557  for (unsigned int dd=1; dd<d; ++dd)
1558  dofs_per_component[target_component[component-d+dd]] =
1559  dofs_per_component[target_component[component-d]];
1560  }
1561  }
1562  }
1563  }
1564 
1565 
1566  template <int dim, int spacedim>
1567  void
1568  resolve_components (const hp::FECollection<dim,spacedim> &fe_collection,
1569  const std::vector<unsigned char> &dofs_by_component,
1570  const std::vector<unsigned int> &target_component,
1571  const bool only_once,
1572  std::vector<types::global_dof_index> &dofs_per_component,
1573  unsigned int &component)
1574  {
1575  // assert that all elements in the collection have the same structure
1576  // (base elements and multiplicity, components per base element) and
1577  // then simply call the function above
1578  for (unsigned int fe=1; fe<fe_collection.size(); ++fe)
1579  {
1580  Assert (fe_collection[fe].n_components() == fe_collection[0].n_components(),
1581  ExcNotImplemented());
1582  Assert (fe_collection[fe].n_base_elements() == fe_collection[0].n_base_elements(),
1583  ExcNotImplemented());
1584  for (unsigned int b=0; b<fe_collection[0].n_base_elements(); ++b)
1585  {
1586  Assert (fe_collection[fe].base_element(b).n_components() == fe_collection[0].base_element(b).n_components(),
1587  ExcNotImplemented());
1588  Assert (fe_collection[fe].base_element(b).n_base_elements() == fe_collection[0].base_element(b).n_base_elements(),
1589  ExcNotImplemented());
1590  }
1591  }
1592 
1593  resolve_components (fe_collection[0], dofs_by_component,
1594  target_component, only_once, dofs_per_component,
1595  component);
1596  }
1597  }
1598 
1599 
1600 
1601  namespace internal
1602  {
1603  namespace
1604  {
1608  template <int dim, int spacedim>
1609  bool all_elements_are_primitive (const FiniteElement<dim,spacedim> &fe)
1610  {
1611  return fe.is_primitive();
1612  }
1613 
1614 
1618  template <int dim, int spacedim>
1619  bool all_elements_are_primitive (const ::hp::FECollection<dim,spacedim> &fe_collection)
1620  {
1621  for (unsigned int i=0; i<fe_collection.size(); ++i)
1622  if (fe_collection[i].is_primitive() == false)
1623  return false;
1624 
1625  return true;
1626  }
1627  }
1628  }
1629 
1630  template <typename DoFHandlerType>
1631  void
1632  count_dofs_per_component (const DoFHandlerType &dof_handler,
1633  std::vector<types::global_dof_index> &dofs_per_component,
1634  bool only_once,
1635  std::vector<unsigned int> target_component)
1636  {
1637  const unsigned int n_components = dof_handler.get_fe().n_components();
1638 
1639  std::fill (dofs_per_component.begin(), dofs_per_component.end(),
1641 
1642  // If the empty vector was given as default argument, set up this
1643  // vector as identity.
1644  if (target_component.size()==0)
1645  {
1646  target_component.resize(n_components);
1647  for (unsigned int i=0; i<n_components; ++i)
1648  target_component[i] = i;
1649  }
1650  else
1651  Assert (target_component.size()==n_components,
1652  ExcDimensionMismatch(target_component.size(),
1653  n_components));
1654 
1655 
1656  const unsigned int max_component
1657  = *std::max_element (target_component.begin(),
1658  target_component.end());
1659  const unsigned int n_target_components = max_component + 1;
1660  (void)n_target_components; // silence possible warning about unused variable
1661 
1662  AssertDimension (dofs_per_component.size(), n_target_components);
1663 
1664  // special case for only one component. treat this first since it does
1665  // not require any computations
1666  if (n_components == 1)
1667  {
1668  dofs_per_component[0] = dof_handler.n_locally_owned_dofs();
1669  return;
1670  }
1671 
1672 
1673  // otherwise determine the number of dofs in each component separately.
1674  // do so in parallel
1675  std::vector<unsigned char> dofs_by_component (dof_handler.n_locally_owned_dofs());
1676  internal::get_component_association (dof_handler, ComponentMask(),
1677  dofs_by_component);
1678 
1679  // next count what we got
1680  unsigned int component = 0;
1681  internal::resolve_components(dof_handler.get_fe(),
1682  dofs_by_component, target_component,
1683  only_once, dofs_per_component, component);
1684  Assert (n_components == component, ExcInternalError());
1685 
1686  // finally sanity check. this is only valid if the finite element is
1687  // actually primitive, so exclude other elements from this
1688  Assert ((internal::all_elements_are_primitive(dof_handler.get_fe()) == false)
1689  ||
1690  (std::accumulate (dofs_per_component.begin(),
1691  dofs_per_component.end(),
1693  == dof_handler.n_locally_owned_dofs()),
1694  ExcInternalError());
1695 
1696  // reduce information from all CPUs
1697 #ifdef DEAL_II_WITH_MPI
1698  const unsigned int dim = DoFHandlerType::dimension;
1699  const unsigned int spacedim = DoFHandlerType::space_dimension;
1700 
1702  = (dynamic_cast<const parallel::Triangulation<dim,spacedim>*>
1703  (&dof_handler.get_triangulation())))
1704  {
1705  std::vector<types::global_dof_index> local_dof_count = dofs_per_component;
1706 
1707  const int ierr = MPI_Allreduce (&local_dof_count[0], &dofs_per_component[0], n_target_components,
1708  DEAL_II_DOF_INDEX_MPI_TYPE,
1709  MPI_SUM, tria->get_communicator());
1710  AssertThrowMPI (ierr);
1711  }
1712 #endif
1713  }
1714 
1715 
1716 
1717  template <typename DoFHandlerType>
1718  void
1719  count_dofs_per_block (const DoFHandlerType &dof_handler,
1720  std::vector<types::global_dof_index> &dofs_per_block,
1721  const std::vector<unsigned int> &target_block_)
1722  {
1723  std::vector<unsigned int> target_block = target_block_;
1724 
1725  const ::hp::FECollection<DoFHandlerType::dimension,DoFHandlerType::space_dimension>
1726  fe_collection (dof_handler.get_fe());
1727  Assert (fe_collection.size() < 256, ExcNotImplemented());
1728 
1729  for (unsigned int this_fe=0; this_fe<fe_collection.size(); ++this_fe)
1730  {
1732  std::fill (dofs_per_block.begin(), dofs_per_block.end(),
1734 
1735  // If the empty vector was given as default argument, set up this
1736  // vector as identity.
1737  if (target_block.size()==0)
1738  {
1739  target_block.resize(fe.n_blocks());
1740  for (unsigned int i=0; i<fe.n_blocks(); ++i)
1741  target_block[i] = i;
1742  }
1743  else
1744  Assert (target_block.size()==fe.n_blocks(),
1745  ExcDimensionMismatch(target_block.size(),
1746  fe.n_blocks()));
1747 
1748 
1749 
1750  const unsigned int max_block
1751  = *std::max_element (target_block.begin(),
1752  target_block.end());
1753  const unsigned int n_target_blocks = max_block + 1;
1754  (void)n_target_blocks; // silence possible warning about unused variable
1755 
1756  const unsigned int n_blocks = fe.n_blocks();
1757 
1758  AssertDimension (dofs_per_block.size(), n_target_blocks);
1759 
1760  // special case for only one block. treat this first since it does
1761  // not require any computations
1762  if (n_blocks == 1)
1763  {
1764  dofs_per_block[0] = dof_handler.n_dofs();
1765  return;
1766  }
1767  // otherwise determine the number of dofs in each block separately.
1768  std::vector<unsigned char> dofs_by_block (dof_handler.n_locally_owned_dofs());
1769  internal::get_block_association (dof_handler, dofs_by_block);
1770 
1771  // next count what we got
1772  for (unsigned int block=0; block<fe.n_blocks(); ++block)
1773  dofs_per_block[target_block[block]]
1774  += std::count(dofs_by_block.begin(), dofs_by_block.end(),
1775  block);
1776 
1777 #ifdef DEAL_II_WITH_MPI
1778  // if we are working on a parallel mesh, we now need to collect
1779  // this information from all processors
1782  (&dof_handler.get_triangulation())))
1783  {
1784  std::vector<types::global_dof_index> local_dof_count = dofs_per_block;
1785  const int ierr = MPI_Allreduce (&local_dof_count[0], &dofs_per_block[0],
1786  n_target_blocks,
1787  DEAL_II_DOF_INDEX_MPI_TYPE,
1788  MPI_SUM, tria->get_communicator());
1789  AssertThrowMPI (ierr);
1790  }
1791 #endif
1792  }
1793  }
1794 
1795 
1796 
1797  template <typename DoFHandlerType>
1798  void
1799  map_dof_to_boundary_indices (const DoFHandlerType &dof_handler,
1800  std::vector<types::global_dof_index> &mapping)
1801  {
1802  mapping.clear ();
1803  mapping.insert (mapping.end(), dof_handler.n_dofs(),
1804  DoFHandlerType::invalid_dof_index);
1805 
1806  std::vector<types::global_dof_index> dofs_on_face;
1807  dofs_on_face.reserve (max_dofs_per_face(dof_handler));
1808  types::global_dof_index next_boundary_index = 0;
1809 
1810  // now loop over all cells and check whether their faces are at the
1811  // boundary. note that we need not take special care of single lines
1812  // being at the boundary (using @p{cell->has_boundary_lines}), since we
1813  // do not support boundaries of dimension dim-2, and so every isolated
1814  // boundary line is also part of a boundary face which we will be
1815  // visiting sooner or later
1816  typename DoFHandlerType::active_cell_iterator cell = dof_handler.begin_active(),
1817  endc = dof_handler.end();
1818  for (; cell!=endc; ++cell)
1819  for (unsigned int f=0; f<GeometryInfo<DoFHandlerType::dimension>::faces_per_cell; ++f)
1820  if (cell->at_boundary(f))
1821  {
1822  const unsigned int dofs_per_face = cell->get_fe().dofs_per_face;
1823  dofs_on_face.resize (dofs_per_face);
1824  cell->face(f)->get_dof_indices (dofs_on_face,
1825  cell->active_fe_index());
1826  for (unsigned int i=0; i<dofs_per_face; ++i)
1827  if (mapping[dofs_on_face[i]] == DoFHandlerType::invalid_dof_index)
1828  mapping[dofs_on_face[i]] = next_boundary_index++;
1829  }
1830 
1831  AssertDimension (next_boundary_index, dof_handler.n_boundary_dofs());
1832  }
1833 
1834 
1835 
1836  template <typename DoFHandlerType>
1838  (const DoFHandlerType &dof_handler,
1839  const std::set<types::boundary_id> &boundary_ids,
1840  std::vector<types::global_dof_index> &mapping)
1841  {
1842  Assert (boundary_ids.find (numbers::internal_face_boundary_id) == boundary_ids.end(),
1844 
1845  mapping.clear ();
1846  mapping.insert (mapping.end(), dof_handler.n_dofs(),
1847  DoFHandlerType::invalid_dof_index);
1848 
1849  // return if there is nothing to do
1850  if (boundary_ids.size() == 0)
1851  return;
1852 
1853  std::vector<types::global_dof_index> dofs_on_face;
1854  dofs_on_face.reserve (max_dofs_per_face(dof_handler));
1855  types::global_dof_index next_boundary_index = 0;
1856 
1857  typename DoFHandlerType::active_cell_iterator cell = dof_handler.begin_active(),
1858  endc = dof_handler.end();
1859  for (; cell!=endc; ++cell)
1860  for (unsigned int f=0; f<GeometryInfo<DoFHandlerType::dimension>::faces_per_cell; ++f)
1861  if (boundary_ids.find (cell->face(f)->boundary_id()) !=
1862  boundary_ids.end())
1863  {
1864  const unsigned int dofs_per_face = cell->get_fe().dofs_per_face;
1865  dofs_on_face.resize (dofs_per_face);
1866  cell->face(f)->get_dof_indices (dofs_on_face, cell->active_fe_index());
1867  for (unsigned int i=0; i<dofs_per_face; ++i)
1868  if (mapping[dofs_on_face[i]] == DoFHandlerType::invalid_dof_index)
1869  mapping[dofs_on_face[i]] = next_boundary_index++;
1870  }
1871 
1872  AssertDimension (next_boundary_index,
1873  dof_handler.n_boundary_dofs (boundary_ids));
1874  }
1875 
1876  namespace internal
1877  {
1878  namespace
1879  {
1880  template <typename DoFHandlerType>
1881  void
1884  const DoFHandlerType &dof_handler,
1886  {
1887  const unsigned int dim = DoFHandlerType::dimension;
1888  const unsigned int spacedim = DoFHandlerType::space_dimension;
1889 
1890  hp::FECollection<dim, spacedim> fe_collection(dof_handler.get_fe());
1891  hp::QCollection<dim> q_coll_dummy;
1892 
1893  for (unsigned int fe_index = 0; fe_index < fe_collection.size(); ++fe_index)
1894  {
1895  // check whether every fe in the collection has support points
1896  Assert(fe_collection[fe_index].has_support_points(),
1898  q_coll_dummy.push_back(
1899  Quadrature<dim> (
1900  fe_collection[fe_index].get_unit_support_points()));
1901  }
1902 
1903  // Now loop over all cells and enquire the support points on each
1904  // of these. we use dummy quadrature formulas where the quadrature
1905  // points are located at the unit support points to enquire the
1906  // location of the support points in real space.
1907  //
1908  // The weights of the quadrature rule have been set to invalid
1909  // values by the used constructor.
1910  hp::FEValues<dim, spacedim> hp_fe_values(mapping, fe_collection,
1911  q_coll_dummy, update_quadrature_points);
1912  typename DoFHandlerType::active_cell_iterator cell =
1913  dof_handler.begin_active(), endc = dof_handler.end();
1914 
1915  std::vector<types::global_dof_index> local_dof_indices;
1916  for (; cell != endc; ++cell)
1917  // only work on locally relevant cells
1918  if (cell->is_artificial() == false)
1919  {
1920  hp_fe_values.reinit(cell);
1921  const FEValues<dim, spacedim> &fe_values = hp_fe_values.get_present_fe_values();
1922 
1923  local_dof_indices.resize(cell->get_fe().dofs_per_cell);
1924  cell->get_dof_indices(local_dof_indices);
1925 
1926  const std::vector<Point<spacedim> > &points =
1927  fe_values.get_quadrature_points();
1928  for (unsigned int i = 0; i < cell->get_fe().dofs_per_cell; ++i)
1929  // insert the values into the map
1930  support_points[local_dof_indices[i]] = points[i];
1931  }
1932  }
1933 
1934 
1935  template <typename DoFHandlerType>
1936  void
1939  const DoFHandlerType &dof_handler,
1940  std::vector<Point<DoFHandlerType::space_dimension> > &support_points)
1941  {
1942  // get the data in the form of the map as above
1943  std::map<types::global_dof_index,Point<DoFHandlerType::space_dimension> > x_support_points;
1944  map_dofs_to_support_points(mapping, dof_handler, x_support_points);
1945 
1946  // now convert from the map to the linear vector. make sure every
1947  // entry really appeared in the map
1948  for (types::global_dof_index i=0; i<dof_handler.n_dofs(); ++i)
1949  {
1950  Assert (x_support_points.find(i) != x_support_points.end(),
1951  ExcInternalError());
1952  support_points[i] = x_support_points[i];
1953  }
1954  }
1955  }
1956  }
1957 
1958  template <int dim, int spacedim>
1959  void
1961  const DoFHandler<dim,spacedim> &dof_handler,
1962  std::vector<Point<spacedim> > &support_points)
1963  {
1964  AssertDimension(support_points.size(), dof_handler.n_dofs());
1966  (&dof_handler.get_triangulation())
1967  ==
1968  0),
1969  ExcMessage ("This function can not be used with distributed triangulations."
1970  "See the documentation for more information."));
1971 
1972  // Let the internal function do all the work, just make sure that it
1973  // gets a MappingCollection
1974  const hp::MappingCollection<dim, spacedim> mapping_collection(mapping);
1975 
1976  internal::map_dofs_to_support_points (mapping_collection,
1977  dof_handler,
1978  support_points);
1979  }
1980 
1981 
1982  template<int dim, int spacedim>
1983  void
1985  const hp::DoFHandler<dim, spacedim> &dof_handler,
1986  std::vector<Point<spacedim> > &support_points)
1987  {
1988  AssertDimension(support_points.size(), dof_handler.n_dofs());
1990  (&dof_handler.get_triangulation())
1991  ==
1992  0),
1993  ExcMessage ("This function can not be used with distributed triangulations."
1994  "See the documentation for more information."));
1995 
1996  // Let the internal function do all the work, just make sure that it
1997  // gets a MappingCollection
1998  internal::map_dofs_to_support_points (mapping,
1999  dof_handler,
2000  support_points);
2001  }
2002 
2003 
2004  template <int dim, int spacedim>
2005  void
2007  const DoFHandler<dim,spacedim> &dof_handler,
2008  std::map<types::global_dof_index, Point<spacedim> > &support_points)
2009  {
2010  support_points.clear();
2011 
2012  // Let the internal function do all the work, just make sure that it
2013  // gets a MappingCollection
2014  const hp::MappingCollection<dim, spacedim> mapping_collection(mapping);
2015 
2016  internal::map_dofs_to_support_points (mapping_collection,
2017  dof_handler,
2018  support_points);
2019  }
2020 
2021 
2022  template<int dim, int spacedim>
2023  void
2025  const hp::DoFHandler<dim, spacedim> &dof_handler,
2026  std::map<types::global_dof_index, Point<spacedim> > &support_points)
2027  {
2028  support_points.clear();
2029 
2030  // Let the internal function do all the work, just make sure that it
2031  // gets a MappingCollection
2032  internal::map_dofs_to_support_points (mapping,
2033  dof_handler,
2034  support_points);
2035  }
2036 
2037  template <int spacedim>
2038  void
2040  const std::map<types::global_dof_index, Point<spacedim> > &support_points)
2041  {
2042  AssertThrow (out, ExcIO());
2043 
2044  typedef std::map< types::global_dof_index, Point<spacedim> >
2045  dof_map_t;
2046 
2047  typedef std::map<Point<spacedim>, std::vector<types::global_dof_index>, typename internal::ComparisonHelper<spacedim> >
2048  point_map_t;
2049 
2050  point_map_t point_map;
2051 
2052  // convert to map point -> list of DoFs
2053  for (typename dof_map_t::const_iterator it = support_points.begin();
2054  it!=support_points.end();
2055  ++it)
2056  {
2057  std::vector<types::global_dof_index> &v = point_map[it->second];
2058  v.push_back(it->first);
2059  }
2060 
2061  // print the newly created map:
2062  for (typename point_map_t::iterator it = point_map.begin();
2063  it!=point_map.end();
2064  ++it)
2065  {
2066  out << it->first << " \"";
2067  const std::vector<types::global_dof_index> &v = it->second;
2068  for (unsigned int i=0; i < v.size(); ++i)
2069  {
2070  if (i>0)
2071  out << ", ";
2072  out << v[i];
2073  }
2074 
2075  out << "\"\n";
2076  }
2077 
2078  out << std::flush;
2079  }
2080 
2081 
2082  template<int dim, int spacedim>
2083  void
2085  (const DoFHandler<dim,spacedim> &dof_handler,
2086  const Table<2, Coupling> &table,
2087  std::vector<Table<2,Coupling> > &tables_by_block)
2088  {
2089  const FiniteElement<dim,spacedim> &fe = dof_handler.get_fe();
2090  const unsigned int nb = fe.n_blocks();
2091 
2092  tables_by_block.resize(1);
2093  tables_by_block[0].reinit(nb, nb);
2094  tables_by_block[0].fill(none);
2095 
2096  for (unsigned int i=0; i<fe.n_components(); ++i)
2097  {
2098  const unsigned int ib = fe.component_to_block_index(i);
2099  for (unsigned int j=0; j<fe.n_components(); ++j)
2100  {
2101  const unsigned int jb = fe.component_to_block_index(j);
2102  tables_by_block[0](ib,jb) |= table(i,j);
2103  }
2104  }
2105  }
2106 
2107 
2108  template<int dim, int spacedim>
2109  void
2111  const Table<2, Coupling> &table,
2112  std::vector<Table<2,Coupling> > &tables_by_block)
2113  {
2114  const hp::FECollection<dim> &fe_collection = dof_handler.get_fe();
2115  tables_by_block.resize(fe_collection.size());
2116 
2117  for (unsigned int f=0; f<fe_collection.size(); ++f)
2118  {
2119  const FiniteElement<dim,spacedim> &fe = fe_collection[f];
2120 
2121  const unsigned int nb = fe.n_blocks();
2122  tables_by_block[f].reinit(nb, nb);
2123  tables_by_block[f].fill(none);
2124  for (unsigned int i=0; i<fe.n_components(); ++i)
2125  {
2126  const unsigned int ib = fe.component_to_block_index(i);
2127  for (unsigned int j=0; j<fe.n_components(); ++j)
2128  {
2129  const unsigned int jb = fe.component_to_block_index(j);
2130  tables_by_block[f](ib,jb) |= table(i,j);
2131  }
2132  }
2133  }
2134  }
2135 
2136 
2137 
2138  template <int dim, int spacedim>
2140  const DoFHandler<dim,spacedim> &dof_handler,
2141  const unsigned int level,
2142  const std::vector<bool> &selected_dofs,
2143  const types::global_dof_index offset)
2144  {
2145  typename DoFHandler<dim,spacedim>::level_cell_iterator cell;
2146  typename DoFHandler<dim,spacedim>::level_cell_iterator endc = dof_handler.end(level);
2147  std::vector<types::global_dof_index> indices;
2148 
2149  unsigned int i=0;
2150 
2151  for (cell=dof_handler.begin(level); cell != endc; ++cell)
2152  if (cell->is_locally_owned_on_level())
2153  ++i;
2154  block_list.reinit(i, dof_handler.n_dofs(), dof_handler.get_fe().dofs_per_cell);
2155  i=0;
2156  for (cell=dof_handler.begin(level); cell != endc; ++cell)
2157  if (cell->is_locally_owned_on_level())
2158  {
2159  indices.resize(cell->get_fe().dofs_per_cell);
2160  cell->get_mg_dof_indices(indices);
2161 
2162  if (selected_dofs.size()!=0)
2163  AssertDimension(indices.size(), selected_dofs.size());
2164 
2165  for (types::global_dof_index j=0; j<indices.size(); ++j)
2166  {
2167  if (selected_dofs.size() == 0)
2168  block_list.add(i,indices[j]-offset);
2169  else
2170  {
2171  if (selected_dofs[j])
2172  block_list.add(i,indices[j]-offset);
2173  }
2174  }
2175  ++i;
2176  }
2177  }
2178 
2179 
2180  template <typename DoFHandlerType>
2182  const DoFHandlerType &dof_handler,
2183  const unsigned int level,
2184  const bool interior_only)
2185  {
2186  const FiniteElement<DoFHandlerType::dimension> &fe = dof_handler.get_fe();
2187  block_list.reinit(1, dof_handler.n_dofs(level), dof_handler.n_dofs(level));
2188  typename DoFHandlerType::level_cell_iterator cell;
2189  typename DoFHandlerType::level_cell_iterator endc = dof_handler.end(level);
2190 
2191  std::vector<types::global_dof_index> indices;
2192  std::vector<bool> exclude;
2193 
2194  for (cell=dof_handler.begin(level); cell != endc; ++cell)
2195  {
2196  indices.resize(cell->get_fe().dofs_per_cell);
2197  cell->get_mg_dof_indices(indices);
2198 
2199  if (interior_only)
2200  {
2201  // Exclude degrees of freedom on faces opposite to the vertex
2202  exclude.resize(fe.dofs_per_cell);
2203  std::fill(exclude.begin(), exclude.end(), false);
2204  const unsigned int dpf = fe.dofs_per_face;
2205 
2206  for (unsigned int face=0; face<GeometryInfo<DoFHandlerType::dimension>::faces_per_cell; ++face)
2207  if (cell->at_boundary(face) || cell->neighbor(face)->level() != cell->level())
2208  for (unsigned int i=0; i<dpf; ++i)
2209  exclude[fe.face_to_cell_index(i,face)] = true;
2210  for (types::global_dof_index j=0; j<indices.size(); ++j)
2211  if (!exclude[j])
2212  block_list.add(0, indices[j]);
2213  }
2214  else
2215  {
2216  for (types::global_dof_index j=0; j<indices.size(); ++j)
2217  block_list.add(0, indices[j]);
2218  }
2219  }
2220  }
2221 
2222 
2223  template <typename DoFHandlerType>
2225  const DoFHandlerType &dof_handler,
2226  const unsigned int level,
2227  const bool interior_dofs_only,
2228  const bool boundary_dofs)
2229  {
2230  Assert(level > 0 && level < dof_handler.get_triangulation().n_levels(),
2231  ExcIndexRange(level, 1, dof_handler.get_triangulation().n_levels()));
2232 
2233  typename DoFHandlerType::level_cell_iterator pcell = dof_handler.begin(level-1);
2234  typename DoFHandlerType::level_cell_iterator endc = dof_handler.end(level-1);
2235 
2236  std::vector<types::global_dof_index> indices;
2237  std::vector<bool> exclude;
2238 
2239  for (unsigned int block = 0; pcell != endc; ++pcell)
2240  {
2241  if (!pcell->has_children())
2242  continue;
2243 
2244  for (unsigned int child=0; child<pcell->n_children(); ++child)
2245  {
2246  const typename DoFHandlerType::level_cell_iterator cell = pcell->child(child);
2247 
2248  // For hp, only this line here would have to be replaced.
2249  const FiniteElement<DoFHandlerType::dimension> &fe = dof_handler.get_fe();
2250  const unsigned int n_dofs = fe.dofs_per_cell;
2251  indices.resize(n_dofs);
2252  exclude.resize(n_dofs);
2253  std::fill(exclude.begin(), exclude.end(), false);
2254  cell->get_mg_dof_indices(indices);
2255 
2256  if (interior_dofs_only)
2257  {
2258  // Eliminate dofs on faces of the child which are on faces
2259  // of the parent
2260  const unsigned int dpf = fe.dofs_per_face;
2261 
2262  for (unsigned int d=0; d<DoFHandlerType::dimension; ++d)
2263  {
2264  const unsigned int face = GeometryInfo<DoFHandlerType::dimension>::vertex_to_face[child][d];
2265  for (unsigned int i=0; i<dpf; ++i)
2266  exclude[fe.face_to_cell_index(i,face)] = true;
2267  }
2268 
2269  // Now remove all degrees of freedom on the domain boundary
2270  // from the exclusion list
2271  if (boundary_dofs)
2272  for (unsigned int face=0; face< GeometryInfo<DoFHandlerType::dimension>::faces_per_cell; ++face)
2273  if (cell->at_boundary(face))
2274  for (unsigned int i=0; i<dpf; ++i)
2275  exclude[fe.face_to_cell_index(i,face)] = false;
2276  }
2277 
2278  for (unsigned int i=0; i<n_dofs; ++i)
2279  if (!exclude[i])
2280  block_list.add(block, indices[i]);
2281  }
2282  ++block;
2283  }
2284  }
2285 
2286  template <typename DoFHandlerType>
2287  std::vector<unsigned int>
2289  const DoFHandlerType &dof_handler,
2290  const unsigned int level,
2291  const bool interior_only,
2292  const bool boundary_patches,
2293  const bool level_boundary_patches,
2294  const bool single_cell_patches,
2295  const bool invert_vertex_mapping)
2296  {
2297  const unsigned int n_blocks = dof_handler.get_fe().n_blocks();
2298  BlockMask exclude_boundary_dofs = BlockMask(n_blocks,interior_only);
2299  return make_vertex_patches(block_list,
2300  dof_handler,
2301  level,
2302  exclude_boundary_dofs,
2303  boundary_patches,
2304  level_boundary_patches,
2305  single_cell_patches,
2306  invert_vertex_mapping);
2307  }
2308 
2309  template <typename DoFHandlerType>
2310  std::vector<unsigned int>
2312  const DoFHandlerType &dof_handler,
2313  const unsigned int level,
2314  const BlockMask &exclude_boundary_dofs,
2315  const bool boundary_patches,
2316  const bool level_boundary_patches,
2317  const bool single_cell_patches,
2318  const bool invert_vertex_mapping)
2319  {
2320  typename DoFHandlerType::level_cell_iterator cell;
2321  typename DoFHandlerType::level_cell_iterator endc = dof_handler.end(level);
2322 
2323  // Vector mapping from vertex index in the triangulation to consecutive
2324  // block indices on this level The number of cells at a vertex
2325  std::vector<unsigned int> vertex_cell_count(dof_handler.get_triangulation().n_vertices(), 0);
2326 
2327  // Is a vertex at the boundary?
2328  std::vector<bool> vertex_boundary(dof_handler.get_triangulation().n_vertices(), false);
2329 
2330  std::vector<unsigned int> vertex_mapping(dof_handler.get_triangulation().n_vertices(),
2332 
2333  // Estimate for the number of dofs at this point
2334  std::vector<unsigned int> vertex_dof_count(dof_handler.get_triangulation().n_vertices(), 0);
2335 
2336  // Identify all vertices active on this level and remember some data
2337  // about them
2338  for (cell=dof_handler.begin(level); cell != endc; ++cell)
2339  for (unsigned int v=0; v<GeometryInfo<DoFHandlerType::dimension>::vertices_per_cell; ++v)
2340  {
2341  const unsigned int vg = cell->vertex_index(v);
2342  vertex_dof_count[vg] += cell->get_fe().dofs_per_cell;
2343  ++vertex_cell_count[vg];
2344  for (unsigned int d=0; d<DoFHandlerType::dimension; ++d)
2345  {
2346  const unsigned int face = GeometryInfo<DoFHandlerType::dimension>::vertex_to_face[v][d];
2347  if (cell->at_boundary(face))
2348  vertex_boundary[vg] = true;
2349  else if ((!level_boundary_patches)
2350  && (cell->neighbor(face)->level() != (int) level))
2351  vertex_boundary[vg] = true;
2352  }
2353  }
2354  // From now on, only vertices with positive dof count are "in".
2355 
2356  // Remove vertices at boundaries or in corners
2357  for (unsigned int vg=0; vg<vertex_dof_count.size(); ++vg)
2358  if ((!single_cell_patches && vertex_cell_count[vg] < 2)
2359  ||
2360  (!boundary_patches && vertex_boundary[vg]))
2361  vertex_dof_count[vg] = 0;
2362 
2363  // Create a mapping from all vertices to the ones used here
2364  unsigned int n_vertex_count=0;
2365  for (unsigned int vg=0; vg<vertex_mapping.size(); ++vg)
2366  if (vertex_dof_count[vg] != 0)
2367  vertex_mapping[vg] = n_vertex_count++;
2368 
2369  // Compactify dof count
2370  for (unsigned int vg=0; vg<vertex_mapping.size(); ++vg)
2371  if (vertex_dof_count[vg] != 0)
2372  vertex_dof_count[vertex_mapping[vg]] = vertex_dof_count[vg];
2373 
2374  // Now that we have all the data, we reduce it to the part we actually
2375  // want
2376  vertex_dof_count.resize(n_vertex_count);
2377 
2378  // At this point, the list of patches is ready. Now we enter the dofs
2379  // into the sparsity pattern.
2380  block_list.reinit(vertex_dof_count.size(), dof_handler.n_dofs(level), vertex_dof_count);
2381 
2382  std::vector<types::global_dof_index> indices;
2383  std::vector<bool> exclude;
2384 
2385  for (cell=dof_handler.begin(level); cell != endc; ++cell)
2386  {
2387  const FiniteElement<DoFHandlerType::dimension> &fe = cell->get_fe();
2388  indices.resize(fe.dofs_per_cell);
2389  cell->get_mg_dof_indices(indices);
2390 
2391  for (unsigned int v=0; v<GeometryInfo<DoFHandlerType::dimension>::vertices_per_cell; ++v)
2392  {
2393  const unsigned int vg = cell->vertex_index(v);
2394  const unsigned int block = vertex_mapping[vg];
2395  if (block == numbers::invalid_unsigned_int)
2396  continue;
2397 
2398  // Collect excluded dofs for some block(s) if boundary dofs
2399  // for a block are decided to be excluded
2400  if (exclude_boundary_dofs.size()==0 || exclude_boundary_dofs.n_selected_blocks() != 0)
2401  {
2402  // Exclude degrees of freedom on faces opposite to the
2403  // vertex
2404  exclude.resize(fe.dofs_per_cell);
2405  std::fill(exclude.begin(), exclude.end(), false);
2406  const unsigned int dpf = fe.dofs_per_face;
2407 
2408  for (unsigned int d=0; d<DoFHandlerType::dimension; ++d)
2409  {
2410  const unsigned int a_face = GeometryInfo<DoFHandlerType::dimension>::vertex_to_face[v][d];
2411  const unsigned int face = GeometryInfo<DoFHandlerType::dimension>::opposite_face[a_face];
2412  for (unsigned int i=0; i<dpf; ++i)
2413  {
2414  // For each dof, get the block it is in and decide to exclude it or not
2415  if (exclude_boundary_dofs[fe.system_to_block_index(fe.face_to_cell_index(i,face)).first]==true)
2416  exclude[fe.face_to_cell_index(i,face)] = true;
2417  }
2418  }
2419  for (unsigned int j=0; j<indices.size(); ++j)
2420  if (!exclude[j])
2421  block_list.add(block, indices[j]);
2422  }
2423  else
2424  {
2425  for (unsigned int j=0; j<indices.size(); ++j)
2426  block_list.add(block, indices[j]);
2427  }
2428  }
2429  }
2430 
2431  if (invert_vertex_mapping)
2432  {
2433  // Compress vertex mapping
2434  unsigned int n_vertex_count = 0;
2435  for (unsigned int vg = 0; vg < vertex_mapping.size(); ++vg)
2436  if (vertex_mapping[vg] != numbers::invalid_unsigned_int)
2437  vertex_mapping[n_vertex_count++] = vg;
2438 
2439  // Now we reduce it to the part we actually want
2440  vertex_mapping.resize(n_vertex_count);
2441  }
2442 
2443  return vertex_mapping;
2444  }
2445 
2446 
2447  template <typename DoFHandlerType>
2448  unsigned int
2449  count_dofs_on_patch (const std::vector<typename DoFHandlerType::active_cell_iterator> &patch)
2450  {
2451  std::set<types::global_dof_index> dofs_on_patch;
2452  std::vector<types::global_dof_index> local_dof_indices;
2453 
2454  // loop over the cells in the patch and get the DoFs on each.
2455  // add all of them to a std::set which automatically makes sure
2456  // all duplicates are ignored
2457  for (unsigned int i=0; i<patch.size(); ++i)
2458  {
2459  const typename DoFHandlerType::active_cell_iterator cell = patch[i];
2460  Assert (cell->is_artificial() == false,
2461  ExcMessage("This function can not be called with cells that are "
2462  "not either locally owned or ghost cells."));
2463  local_dof_indices.resize (cell->get_fe().dofs_per_cell);
2464  cell->get_dof_indices (local_dof_indices);
2465  dofs_on_patch.insert (local_dof_indices.begin(),
2466  local_dof_indices.end());
2467  }
2468 
2469  // now return the number of DoFs (duplicates were ignored)
2470  return dofs_on_patch.size();
2471  }
2472 
2473 
2474 
2475  template <typename DoFHandlerType>
2476  std::vector<types::global_dof_index>
2477  get_dofs_on_patch (const std::vector<typename DoFHandlerType::active_cell_iterator> &patch)
2478  {
2479  std::set<types::global_dof_index> dofs_on_patch;
2480  std::vector<types::global_dof_index> local_dof_indices;
2481 
2482  // loop over the cells in the patch and get the DoFs on each.
2483  // add all of them to a std::set which automatically makes sure
2484  // all duplicates are ignored
2485  for (unsigned int i=0; i<patch.size(); ++i)
2486  {
2487  const typename DoFHandlerType::active_cell_iterator cell = patch[i];
2488  Assert (cell->is_artificial() == false,
2489  ExcMessage("This function can not be called with cells that are "
2490  "not either locally owned or ghost cells."));
2491  local_dof_indices.resize (cell->get_fe().dofs_per_cell);
2492  cell->get_dof_indices (local_dof_indices);
2493  dofs_on_patch.insert (local_dof_indices.begin(),
2494  local_dof_indices.end());
2495  }
2496 
2497  Assert (dofs_on_patch.size() == count_dofs_on_patch<DoFHandlerType>(patch),
2498  ExcInternalError());
2499 
2500  // return a vector with the content of the set above. copying
2501  // also ensures that we retain sortedness as promised in the
2502  // documentation and as necessary to retain the block structure
2503  // also on the local system
2504  return std::vector<types::global_dof_index> (dofs_on_patch.begin(),
2505  dofs_on_patch.end());
2506  }
2507 
2508 
2509 } // end of namespace DoFTools
2510 
2511 
2512 
2513 // explicit instantiations
2514 
2515 #include "dof_tools.inst"
2516 
2517 
2518 
2519 DEAL_II_NAMESPACE_CLOSE
unsigned int n_active_cells() const
Definition: tria.cc:11244
static const unsigned int invalid_unsigned_int
Definition: types.h:170
void make_child_patches(SparsityPattern &block_list, const DoFHandlerType &dof_handler, const unsigned int level, const bool interior_dofs_only, const bool boundary_dofs=false)
Definition: dof_tools.cc:2224
std::vector< IndexSet > locally_owned_dofs_per_subdomain(const DoFHandlerType &dof_handler)
Definition: dof_tools.cc:1166
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1146
ElementIterator end() const
Definition: index_set.h:1305
const types::subdomain_id invalid_subdomain_id
Definition: types.h:245
void add_index(const size_type index)
Definition: index_set.h:1440
cell_iterator begin(const unsigned int level=0) const
Definition: dof_handler.cc:728
const FEValues< dim, spacedim > & get_present_fe_values() const
static ::ExceptionBase & ExcIO()
void count_dofs_per_component(const DoFHandlerType &dof_handler, std::vector< types::global_dof_index > &dofs_per_component, const bool vector_valued_once=false, std::vector< unsigned int > target_component=std::vector< unsigned int >())
Definition: dof_tools.cc:1632
void map_dofs_to_support_points(const Mapping< dim, spacedim > &mapping, const DoFHandler< dim, spacedim > &dof_handler, std::vector< Point< spacedim > > &support_points)
Definition: dof_tools.cc:1960
void get_subdomain_association(const DoFHandlerType &dof_handler, std::vector< types::subdomain_id > &subdomain)
Definition: dof_tools.cc:1309
bool operator()(const Point< dim, Number > &lhs, const Point< dim, Number > &rhs) const
Definition: dof_tools.cc:75
std::vector< types::global_dof_index > get_dofs_on_patch(const std::vector< typename DoFHandlerType::active_cell_iterator > &patch)
Definition: dof_tools.cc:2477
cell_iterator end() const
Definition: dof_handler.cc:756
#define AssertIndexRange(index, range)
Definition: exceptions.h:1170
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
Definition: index_set.h:1463
active_cell_iterator begin_active(const unsigned int level=0) const
bool represents_n_components(const unsigned int n) const
bool represents_the_all_selected_mask() const
unsigned int size() const
Transformed quadrature points.
#define AssertThrow(cond, exc)
Definition: exceptions.h:369
bool is_primitive() const
Definition: fe.h:3034
void write_gnuplot_dof_support_point_info(std::ostream &out, const std::map< types::global_dof_index, Point< spacedim > > &support_points)
Definition: dof_tools.cc:2039
unsigned int count_dofs_with_subdomain_association(const DoFHandlerType &dof_handler, const types::subdomain_id subdomain)
Definition: dof_tools.cc:1400
const FiniteElement< dim, spacedim > & get_fe() const
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
const unsigned int dofs_per_line
Definition: fe_base.h:244
void map_dof_to_boundary_indices(const DoFHandlerType &dof_handler, std::vector< types::global_dof_index > &mapping)
Definition: dof_tools.cc:1799
iterator end()
void extract_locally_relevant_level_dofs(const DoFHandlerType &dof_handler, const unsigned int level, IndexSet &dof_set)
Definition: dof_tools.cc:1019
Definition: point.h:89
unsigned int n_blocks() const
IndexSet dof_indices_with_subdomain_association(const DoFHandlerType &dof_handler, const types::subdomain_id subdomain)
Definition: dof_tools.cc:1415
const std::vector< Point< spacedim > > & get_quadrature_points() const
const hp::FECollection< dim, spacedim > & get_fe() const
unsigned int component_to_block_index(const unsigned int component) const
Definition: fe.cc:347
unsigned int n_locally_owned_dofs() const
void clear()
Definition: index_set.h:1393
static ::ExceptionBase & ExcMessage(std::string arg1)
void push_back(const FiniteElement< dim, spacedim > &new_fe)
void add(const size_type i, const size_type j)
unsigned int global_dof_index
Definition: types.h:88
#define Assert(cond, exc)
Definition: exceptions.h:313
unsigned int element_multiplicity(const unsigned int index) const
Definition: fe.h:2863
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
void extract_locally_owned_dofs(const DoFHandlerType &dof_handler, IndexSet &dof_set)
Definition: dof_tools.cc:932
Abstract base class for mapping classes.
Definition: dof_tools.h:46
void make_cell_patches(SparsityPattern &block_list, const DoFHandler< dim, spacedim > &dof_handler, const unsigned int level, const std::vector< bool > &selected_dofs=std::vector< bool >(), const types::global_dof_index offset=0)
Definition: dof_tools.cc:2139
const ComponentMask & get_nonzero_components(const unsigned int i) const
Definition: fe.h:3012
std::size_t size() const
std::pair< unsigned int, unsigned int > face_system_to_component_index(const unsigned int index) const
Definition: fe.h:2895
types::global_dof_index n_dofs() const
unsigned int size() const
virtual const FiniteElement< dim, spacedim > & base_element(const unsigned int index) const
Definition: fe.cc:1251
void extract_locally_relevant_dofs(const DoFHandlerType &dof_handler, IndexSet &dof_set)
Definition: dof_tools.cc:980
void extract_boundary_dofs(const DoFHandlerType &dof_handler, const ComponentMask &component_mask, std::vector< bool > &selected_dofs, const std::set< types::boundary_id > &boundary_ids=std::set< types::boundary_id >())
Definition: dof_tools.cc:555
void extract_hanging_node_dofs(const DoFHandler< dim, spacedim > &dof_handler, std::vector< bool > &selected_dofs)
Definition: dof_tools.cc:888
void extract_dofs_with_support_on_boundary(const DoFHandlerType &dof_handler, const ComponentMask &component_mask, std::vector< bool > &selected_dofs, const std::set< types::boundary_id > &boundary_ids=std::set< types::boundary_id >())
Definition: dof_tools.cc:689
virtual unsigned int face_to_cell_index(const unsigned int face_dof_index, const unsigned int face, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false) const
Definition: fe.cc:528
unsigned int subdomain_id
Definition: types.h:42
std::vector< unsigned int > make_vertex_patches(SparsityPattern &block_list, const DoFHandlerType &dof_handler, const unsigned int level, const bool interior_dofs_only, const bool boundary_patches=false, const bool level_boundary_patches=false, const bool single_cell_patches=false, const bool invert_vertex_mapping=false)
Definition: dof_tools.cc:2288
unsigned int n_mpi_processes(const MPI_Comm &mpi_communicator)
Definition: mpi.cc:63
const unsigned int dofs_per_cell
Definition: fe_base.h:295
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
void reinit(const size_type m, const size_type n, const unsigned int max_per_row)
void convert_couplings_to_blocks(const hp::DoFHandler< dim, spacedim > &dof_handler, const Table< 2, Coupling > &table_by_component, std::vector< Table< 2, Coupling > > &tables_by_block)
Definition: dof_tools.cc:2110
void set_size(const size_type size)
Definition: index_set.h:1406
const types::subdomain_id artificial_subdomain_id
Definition: types.h:261
std::vector< IndexSet > locally_relevant_dofs_per_subdomain(const DoFHandlerType &dof_handler)
Definition: dof_tools.cc:1246
void extract_locally_active_dofs(const DoFHandlerType &dof_handler, IndexSet &dof_set)
Definition: dof_tools.cc:944
void extract_dofs(const DoFHandler< dim, spacedim > &dof_handler, const ComponentMask &component_mask, std::vector< bool > &selected_dofs)
Definition: dof_tools.cc:372
void compress() const
Definition: index_set.h:1428
void extract_subdomain_dofs(const DoFHandlerType &dof_handler, const types::subdomain_id subdomain_id, std::vector< bool > &selected_dofs)
Definition: dof_tools.cc:899
std::pair< unsigned int, unsigned int > system_to_component_index(const unsigned int index) const
Definition: fe.h:2839
void count_dofs_per_block(const DoFHandlerType &dof, std::vector< types::global_dof_index > &dofs_per_block, const std::vector< unsigned int > &target_block=std::vector< unsigned int >())
Definition: dof_tools.cc:1719
#define AssertThrowMPI(error_code)
Definition: exceptions.h:1211
const Triangulation< dim, spacedim > & get_triangulation() const
unsigned int n_components() const
std::pair< unsigned int, types::global_dof_index > system_to_block_index(const unsigned int component) const
Definition: fe.h:2982
unsigned int n_selected_blocks(const unsigned int overall_number_of_blocks=numbers::invalid_unsigned_int) const
Definition: block_mask.h:292
unsigned int first_selected_component(const unsigned int overall_number_of_components=numbers::invalid_unsigned_int) const
unsigned int n_selected_components(const unsigned int overall_number_of_components=numbers::invalid_unsigned_int) const
unsigned int count_dofs_on_patch(const std::vector< typename DoFHandlerType::active_cell_iterator > &patch)
Definition: dof_tools.cc:2449
const unsigned int dofs_per_face
Definition: fe_base.h:288
Definition: fe.h:30
types::global_dof_index n_dofs() const
static ::ExceptionBase & ExcInvalidBoundaryIndicator()
static ::ExceptionBase & ExcNotImplemented()
const Triangulation< dim, spacedim > & get_triangulation() const
const unsigned int dofs_per_vertex
Definition: fe_base.h:238
Definition: table.h:33
bool is_element(const size_type index) const
Definition: index_set.h:1489
const types::boundary_id internal_face_boundary_id
Definition: types.h:216
void extract_level_dofs(const unsigned int level, const DoFHandlerType &dof, const ComponentMask &component_mask, std::vector< bool > &selected_dofs)
Definition: dof_tools.cc:489
std::vector< typename MeshType::active_cell_iterator > compute_active_cell_halo_layer(const MeshType &mesh, const std_cxx11::function< bool(const typename MeshType::active_cell_iterator &)> &predicate)
Definition: grid_tools.cc:1583
unsigned int size() const
Definition: block_mask.h:255
unsigned int n_base_elements() const
Definition: fe.h:2853
ElementIterator begin() const
Definition: index_set.h:1246
void get_active_fe_indices(const DoFHandlerType &dof_handler, std::vector< unsigned int > &active_fe_indices)
Definition: dof_tools.cc:1152
void distribute_cell_to_dof_vector(const DoFHandlerType &dof_handler, const Vector< Number > &cell_data, Vector< double > &dof_data, const unsigned int component=0)
Definition: dof_tools.cc:290
void extract_constant_modes(const DoFHandlerType &dof_handler, const ComponentMask &component_mask, std::vector< std::vector< bool > > &constant_modes)
Definition: dof_tools.cc:1065
virtual bool has_support_on_face(const unsigned int shape_index, const unsigned int face_index) const
Definition: fe.cc:1079
void make_single_patch(SparsityPattern &block_list, const DoFHandlerType &dof_handler, const unsigned int level, const bool interior_dofs_only=false)
Definition: dof_tools.cc:2181
static ::ExceptionBase & ExcInternalError()
Triangulation< dim, spacedim > & get_triangulation()
Definition: tria.cc:11855