Reference documentation for deal.II version 9.1.0-pre
mg_transfer_matrix_free.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2016 - 2017 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_mg_transfer_matrix_free_h
17 #define dealii_mg_transfer_matrix_free_h
18 
19 #include <deal.II/base/config.h>
20 
21 #include <deal.II/base/mg_level_object.h>
22 #include <deal.II/base/vectorization.h>
23 
24 #include <deal.II/dofs/dof_handler.h>
25 
26 #include <deal.II/lac/la_parallel_block_vector.h>
27 #include <deal.II/lac/la_parallel_vector.h>
28 
29 #include <deal.II/multigrid/mg_base.h>
30 #include <deal.II/multigrid/mg_constrained_dofs.h>
31 #include <deal.II/multigrid/mg_transfer.h>
32 #include <deal.II/multigrid/mg_transfer_internal.h>
33 
34 
35 DEAL_II_NAMESPACE_OPEN
36 
37 
40 
56 template <int dim, typename Number>
58  : public MGLevelGlobalTransfer<LinearAlgebra::distributed::Vector<Number>>
59 {
60 public:
66 
72 
76  virtual ~MGTransferMatrixFree() override = default;
77 
81  void
82  initialize_constraints(const MGConstrainedDoFs &mg_constrained_dofs);
83 
87  void
88  clear();
89 
93  void
94  build(const DoFHandler<dim, dim> &mg_dof);
95 
110  virtual void
111  prolongate(
112  const unsigned int to_level,
114  const LinearAlgebra::distributed::Vector<Number> &src) const override;
115 
134  virtual void
136  const unsigned int from_level,
138  const LinearAlgebra::distributed::Vector<Number> &src) const override;
139 
147  template <typename Number2, int spacedim>
148  void
150  const DoFHandler<dim, spacedim> & mg_dof,
153 
158 
162  std::size_t
163  memory_consumption() const;
164 
165 private:
171  unsigned int fe_degree;
172 
178 
183  unsigned int n_components;
184 
190  unsigned int n_child_cell_dofs;
191 
202  std::vector<std::vector<unsigned int>> level_dof_indices;
203 
208  std::vector<std::vector<std::pair<unsigned int, unsigned int>>>
210 
215  std::vector<unsigned int> n_owned_level_cells;
216 
222 
227 
239  std::vector<AlignedVector<VectorizedArray<Number>>> weights_on_refined;
240 
246  std::vector<std::vector<std::vector<unsigned short>>> dirichlet_indices;
247 
251  template <int degree>
252  void
254  const unsigned int to_level,
257 
261  template <int degree>
262  void
263  do_restrict_add(const unsigned int from_level,
266 };
267 
268 
285 template <int dim, typename Number>
287  : public MGTransferBase<LinearAlgebra::distributed::BlockVector<Number>>
288 {
289 public:
294  MGTransferBlockMatrixFree() = default;
295 
301 
306  const std::vector<MGConstrainedDoFs> &mg_constrained_dofs);
307 
311  virtual ~MGTransferBlockMatrixFree() override = default;
312 
316  void
317  initialize_constraints(const MGConstrainedDoFs &mg_constrained_dofs);
318 
322  void
324  const std::vector<MGConstrainedDoFs> &mg_constrained_dofs);
325 
329  void
330  clear();
331 
335  void
336  build(const DoFHandler<dim, dim> &mg_dof);
337 
341  void
342  build(const std::vector<const DoFHandler<dim, dim> *> &mg_dof);
343 
358  virtual void
359  prolongate(
360  const unsigned int to_level,
362  const LinearAlgebra::distributed::BlockVector<Number> &src) const override;
363 
382  virtual void
384  const unsigned int from_level,
386  const LinearAlgebra::distributed::BlockVector<Number> &src) const override;
387 
398  template <typename Number2, int spacedim>
399  void
400  copy_to_mg(
401  const DoFHandler<dim, spacedim> & mg_dof,
404 
408  template <typename Number2, int spacedim>
409  void
410  copy_to_mg(
411  const std::vector<const DoFHandler<dim, spacedim> *> & mg_dof,
414 
418  template <typename Number2, int spacedim>
419  void
420  copy_from_mg(
421  const DoFHandler<dim, spacedim> & mg_dof,
424  const;
425 
429  template <typename Number2, int spacedim>
430  void
431  copy_from_mg(
432  const std::vector<const DoFHandler<dim, spacedim> *> &mg_dof,
435  const;
436 
440  std::size_t
441  memory_consumption() const;
442 
447  static const bool supports_dof_handler_vector = true;
448 
449 private:
453  std::vector<MGTransferMatrixFree<dim, Number>> matrix_free_transfer_vector;
454 
459  const bool same_for_all;
460 };
461 
462 
466 //------------------------ templated functions -------------------------
467 #ifndef DOXYGEN
468 
469 
470 template <int dim, typename Number>
471 template <typename Number2, int spacedim>
472 void
474  const DoFHandler<dim, spacedim> & dof_handler,
477 {
478  const unsigned int min_level = dst.min_level();
479  const unsigned int max_level = dst.max_level();
480 
481  Assert(max_level == dof_handler.get_triangulation().n_global_levels() - 1,
483  max_level, dof_handler.get_triangulation().n_global_levels() - 1));
484 
486  (dynamic_cast<const parallel::Triangulation<dim, spacedim> *>(
487  &dof_handler.get_triangulation()));
488  MPI_Comm mpi_communicator =
489  p_tria != nullptr ? p_tria->get_communicator() : MPI_COMM_SELF;
490 
491  // resize the dst vector if it's empty or has incorrect size
492  MGLevelObject<IndexSet> relevant_dofs(min_level, max_level);
493  for (unsigned int level = min_level; level <= max_level; ++level)
494  {
496  level,
497  relevant_dofs[level]);
498  if (dst[level].size() !=
499  dof_handler.locally_owned_mg_dofs(level).size() ||
500  dst[level].local_size() !=
501  dof_handler.locally_owned_mg_dofs(level).n_elements())
502  dst[level].reinit(dof_handler.locally_owned_mg_dofs(level),
503  relevant_dofs[level],
504  mpi_communicator);
505  }
506 
507  const FiniteElement<dim, spacedim> &fe = dof_handler.get_fe();
508 
509  // copy fine level vector to active cells in MG hierarchy
510  this->copy_to_mg(dof_handler, dst, src, true);
511 
512  // FIXME: maybe need to store hanging nodes constraints per level?
513  // MGConstrainedDoFs does NOT keep this info right now, only periodicity
514  // constraints...
515  dst[max_level].update_ghost_values();
516  // do the transfer from level to level-1:
517  for (unsigned int level = max_level; level > min_level; --level)
518  {
519  // auxiliary vector which always has ghost elements
521  dof_handler.locally_owned_mg_dofs(level),
522  relevant_dofs[level],
523  mpi_communicator);
524  ghosted_vector = dst[level];
525  ghosted_vector.update_ghost_values();
526 
527  std::vector<Number> dof_values_coarse(fe.dofs_per_cell);
528  Vector<Number> dof_values_fine(fe.dofs_per_cell);
529  Vector<Number> tmp(fe.dofs_per_cell);
530  std::vector<types::global_dof_index> dof_indices(fe.dofs_per_cell);
531  typename DoFHandler<dim>::cell_iterator cell =
532  dof_handler.begin(level - 1);
533  typename DoFHandler<dim>::cell_iterator endc = dof_handler.end(level - 1);
534  for (; cell != endc; ++cell)
535  if (cell->is_locally_owned_on_level())
536  {
537  // if we get to a cell without children (== active), we can
538  // skip it as there values should be already set by the
539  // equivalent of copy_to_mg()
540  if (!cell->has_children())
541  continue;
542 
543  std::fill(dof_values_coarse.begin(), dof_values_coarse.end(), 0.);
544  for (unsigned int child = 0; child < cell->n_children(); ++child)
545  {
546  cell->child(child)->get_mg_dof_indices(dof_indices);
547  for (unsigned int i = 0; i < fe.dofs_per_cell; ++i)
548  dof_values_fine(i) = ghosted_vector(dof_indices[i]);
549  fe.get_restriction_matrix(child, cell->refinement_case())
550  .vmult(tmp, dof_values_fine);
551  for (unsigned int i = 0; i < fe.dofs_per_cell; ++i)
552  if (fe.restriction_is_additive(i))
553  dof_values_coarse[i] += tmp[i];
554  else if (tmp(i) != 0.)
555  dof_values_coarse[i] = tmp[i];
556  }
557  cell->get_mg_dof_indices(dof_indices);
558  for (unsigned int i = 0; i < fe.dofs_per_cell; ++i)
559  dst[level - 1](dof_indices[i]) = dof_values_coarse[i];
560  }
561 
562  dst[level - 1].compress(VectorOperation::insert);
563  dst[level - 1].update_ghost_values();
564  }
565 }
566 
567 
568 
569 template <int dim, typename Number>
570 template <typename Number2, int spacedim>
571 void
573  const DoFHandler<dim, spacedim> & mg_dof,
576 {
577  AssertDimension(matrix_free_transfer_vector.size(), 1);
578  Assert(same_for_all,
579  ExcMessage(
580  "This object was initialized with support for usage with one "
581  "DoFHandler for each block, but this method assumes that "
582  "the same DoFHandler is used for all the blocks!"));
583  const std::vector<const DoFHandler<dim, spacedim> *> mg_dofs(src.n_blocks(),
584  &mg_dof);
585 
586  copy_to_mg(mg_dofs, dst, src);
587 }
588 
589 template <int dim, typename Number>
590 template <typename Number2, int spacedim>
591 void
593  const std::vector<const DoFHandler<dim, spacedim> *> & mg_dof,
596 {
597  const unsigned int n_blocks = src.n_blocks();
598  AssertDimension(mg_dof.size(), n_blocks);
599 
600  if (n_blocks == 0)
601  return;
602 
603  const unsigned int min_level = dst.min_level();
604  const unsigned int max_level = dst.max_level();
605 
606  // this function is normally called within the Multigrid class with
607  // dst == defect level block vector. At first run this vector is not
608  // initialized. Do this below:
609  {
611  (dynamic_cast<const parallel::Triangulation<dim, spacedim> *>(
612  &(mg_dof[0]->get_triangulation())));
613  for (unsigned int i = 1; i < n_blocks; ++i)
615  &(mg_dof[0]->get_triangulation())) == tria),
616  ExcMessage("The DoFHandler use different Triangulations!"));
617 
618  for (unsigned int level = min_level; level <= max_level; ++level)
619  {
620  dst[level].reinit(n_blocks);
621  bool collect_size = false;
622  for (unsigned int b = 0; b < n_blocks; ++b)
623  {
624  LinearAlgebra::distributed::Vector<Number> &v = dst[level].block(b);
625  if (v.size() != mg_dof[b]->locally_owned_mg_dofs(level).size() ||
626  v.local_size() !=
627  mg_dof[b]->locally_owned_mg_dofs(level).n_elements())
628  {
629  v.reinit(mg_dof[b]->locally_owned_mg_dofs(level),
630  tria != nullptr ? tria->get_communicator() :
631  MPI_COMM_SELF);
632  collect_size = true;
633  }
634  else
635  v = 0.;
636  }
637  if (collect_size)
638  dst[level].collect_sizes();
639  }
640  }
641 
642  // FIXME: this a quite ugly as we need a temporary object:
644  min_level, max_level);
645 
646  for (unsigned int b = 0; b < n_blocks; ++b)
647  {
648  for (unsigned int l = min_level; l <= max_level; ++l)
649  dst_non_block[l].reinit(dst[l].block(b));
650  const unsigned int data_block = same_for_all ? 0 : b;
651  matrix_free_transfer_vector[data_block].copy_to_mg(*mg_dof[b],
652  dst_non_block,
653  src.block(b));
654 
655  for (unsigned int l = min_level; l <= max_level; ++l)
656  dst[l].block(b) = dst_non_block[l];
657  }
658 }
659 
660 template <int dim, typename Number>
661 template <typename Number2, int spacedim>
662 void
664  const DoFHandler<dim, spacedim> & mg_dof,
667  const
668 {
669  AssertDimension(matrix_free_transfer_vector.size(), 1);
670  const std::vector<const DoFHandler<dim, spacedim> *> mg_dofs(dst.n_blocks(),
671  &mg_dof);
672 
673  copy_from_mg(mg_dofs, dst, src);
674 }
675 
676 template <int dim, typename Number>
677 template <typename Number2, int spacedim>
678 void
680  const std::vector<const DoFHandler<dim, spacedim> *> & mg_dof,
683  const
684 {
685  const unsigned int n_blocks = dst.n_blocks();
686  AssertDimension(mg_dof.size(), n_blocks);
687 
688  if (n_blocks == 0)
689  return;
690 
691  const unsigned int min_level = src.min_level();
692  const unsigned int max_level = src.max_level();
693 
694  for (unsigned int l = min_level; l <= max_level; ++l)
695  AssertDimension(src[l].n_blocks(), dst.n_blocks());
696 
697  // FIXME: this a quite ugly as we need a temporary object:
699  min_level, max_level);
700 
701  for (unsigned int b = 0; b < n_blocks; ++b)
702  {
703  for (unsigned int l = min_level; l <= max_level; ++l)
704  {
705  src_non_block[l].reinit(src[l].block(b));
706  src_non_block[l] = src[l].block(b);
707  }
708  const unsigned int data_block = same_for_all ? 0 : b;
709  matrix_free_transfer_vector[data_block].copy_from_mg(*mg_dof[b],
710  dst.block(b),
711  src_non_block);
712  }
713 }
714 
715 
716 
717 #endif // DOXYGEN
718 
719 
720 DEAL_II_NAMESPACE_CLOSE
721 
722 #endif
void reinit(const size_type size, const bool omit_zeroing_entries=false)
void do_prolongate_add(const unsigned int to_level, LinearAlgebra::distributed::Vector< Number > &dst, const LinearAlgebra::distributed::Vector< Number > &src) const
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1366
void copy_from_mg(const DoFHandler< dim, spacedim > &mg_dof, LinearAlgebra::distributed::BlockVector< Number2 > &dst, const MGLevelObject< LinearAlgebra::distributed::BlockVector< Number >> &src) const
std::vector< unsigned int > n_owned_level_cells
AlignedVector< VectorizedArray< Number > > evaluation_data
static::ExceptionBase & ExcNoProlongation()
std::vector< std::vector< std::vector< unsigned short > > > dirichlet_indices
size_type n_elements() const
Definition: index_set.h:1743
#define AssertThrow(cond, exc)
Definition: exceptions.h:1329
const Triangulation< dim, spacedim > & get_triangulation() const
size_type size() const
Definition: index_set.h:1611
void extract_locally_relevant_level_dofs(const DoFHandlerType &dof_handler, const unsigned int level, IndexSet &dof_set)
Definition: dof_tools.cc:1185
void interpolate_to_mg(const DoFHandler< dim, spacedim > &mg_dof, MGLevelObject< LinearAlgebra::distributed::Vector< Number >> &dst, const LinearAlgebra::distributed::Vector< Number2 > &src) const
virtual MPI_Comm get_communicator() const
Definition: tria_base.cc:155
static::ExceptionBase & ExcMessage(std::string arg1)
AlignedVector< VectorizedArray< Number > > prolongation_matrix_1d
void copy_to_mg(const DoFHandler< dim, spacedim > &mg_dof, MGLevelObject< LinearAlgebra::distributed::Vector< Number >> &dst, const LinearAlgebra::distributed::Vector< Number2 > &src) const
virtual size_type size() const override
#define Assert(cond, exc)
Definition: exceptions.h:1227
void copy_from_mg(const DoFHandler< dim, spacedim > &mg_dof, LinearAlgebra::distributed::Vector< Number2 > &dst, const MGLevelObject< LinearAlgebra::distributed::Vector< Number >> &src) const
static::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
virtual void restrict_and_add(const unsigned int from_level, LinearAlgebra::distributed::Vector< Number > &dst, const LinearAlgebra::distributed::Vector< Number > &src) const override
virtual void prolongate(const unsigned int to_level, LinearAlgebra::distributed::Vector< Number > &dst, const LinearAlgebra::distributed::Vector< Number > &src) const override
std::size_t memory_consumption() const
#define DeclException0(Exception0)
Definition: exceptions.h:385
std::vector< AlignedVector< VectorizedArray< Number > > > weights_on_refined
void do_restrict_add(const unsigned int from_level, LinearAlgebra::distributed::Vector< Number > &dst, const LinearAlgebra::distributed::Vector< Number > &src) const
void copy_to_mg(const DoFHandler< dim, spacedim > &mg_dof, MGLevelObject< LinearAlgebra::distributed::BlockVector< Number >> &dst, const LinearAlgebra::distributed::BlockVector< Number2 > &src) const
cell_iterator end() const
Definition: dof_handler.cc:959
std::vector< std::vector< unsigned int > > level_dof_indices
const IndexSet & locally_owned_mg_dofs(const unsigned int level) const
const unsigned int dofs_per_cell
Definition: fe_base.h:297
bool restriction_is_additive(const unsigned int index) const
Definition: fe.h:3253
SmartPointer< const MGConstrainedDoFs, MGLevelGlobalTransfer< LinearAlgebra::distributed::Vector< Number > > > mg_constrained_dofs
Definition: mg_transfer.h:582
cell_iterator begin(const unsigned int level=0) const
Definition: dof_handler.cc:930
virtual const FullMatrix< double > & get_restriction_matrix(const unsigned int child, const RefinementCase< dim > &refinement_case=RefinementCase< dim >::isotropic_refinement) const
Definition: fe.cc:306
std::vector< std::vector< std::pair< unsigned int, unsigned int > > > parent_child_connect
const FiniteElement< dim, spacedim > & get_fe(const unsigned int index=0) const
std::vector< MGTransferMatrixFree< dim, Number > > matrix_free_transfer_vector
virtual ~MGTransferMatrixFree() override=default
void initialize_constraints(const MGConstrainedDoFs &mg_constrained_dofs)
BlockType & block(const unsigned int i)
void build(const DoFHandler< dim, dim > &mg_dof)