Reference documentation for deal.II version 9.0.0
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 at
12 // the top level of the deal.II distribution.
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/lac/la_parallel_vector.h>
22 #include <deal.II/lac/la_parallel_block_vector.h>
23 #include <deal.II/multigrid/mg_base.h>
24 #include <deal.II/multigrid/mg_constrained_dofs.h>
25 #include <deal.II/base/mg_level_object.h>
26 #include <deal.II/multigrid/mg_transfer.h>
27 #include <deal.II/multigrid/mg_transfer_internal.h>
28 #include <deal.II/base/vectorization.h>
29 
30 #include <deal.II/dofs/dof_handler.h>
31 
32 
33 DEAL_II_NAMESPACE_OPEN
34 
35 
38 
54 template <int dim, typename Number>
55 class MGTransferMatrixFree : public MGLevelGlobalTransfer<LinearAlgebra::distributed::Vector<Number> >
56 {
57 public:
63 
69 
73  virtual ~MGTransferMatrixFree () = default;
74 
79 
83  void clear ();
84 
88  void build (const DoFHandler<dim,dim> &mg_dof);
89 
104  virtual void prolongate (const unsigned int to_level,
107 
126  virtual void restrict_and_add (const unsigned int from_level,
129 
137  template<typename Number2, int spacedim>
141 
146 
150  std::size_t memory_consumption () const;
151 
152 private:
153 
159  unsigned int fe_degree;
160 
166 
171  unsigned int n_components;
172 
178  unsigned int n_child_cell_dofs;
179 
190  std::vector<std::vector<unsigned int> > level_dof_indices;
191 
195  std::vector<std::vector<std::pair<unsigned int,unsigned int> > > parent_child_connect;
196 
201  std::vector<unsigned int> n_owned_level_cells;
202 
208 
213 
225  std::vector<AlignedVector<VectorizedArray<Number> > > weights_on_refined;
226 
232  std::vector<std::vector<std::vector<unsigned short> > > dirichlet_indices;
233 
237  template <int degree>
238  void do_prolongate_add(const unsigned int to_level,
241 
245  template <int degree>
246  void do_restrict_add(const unsigned int from_level,
249 };
250 
251 
268 template <int dim, typename Number>
269 class MGTransferBlockMatrixFree : public MGTransferBase<LinearAlgebra::distributed::BlockVector<Number>>
270 {
271 public:
276  MGTransferBlockMatrixFree () = default;
277 
282  MGTransferBlockMatrixFree (const MGConstrainedDoFs &mg_constrained_dofs);
283 
287  MGTransferBlockMatrixFree (const std::vector<MGConstrainedDoFs> &mg_constrained_dofs);
288 
292  virtual ~MGTransferBlockMatrixFree () = default;
293 
297  void initialize_constraints (const MGConstrainedDoFs &mg_constrained_dofs);
298 
302  void initialize_constraints (const std::vector<MGConstrainedDoFs> &mg_constrained_dofs);
303 
307  void clear ();
308 
312  void build (const DoFHandler<dim,dim> &mg_dof);
313 
317  void build (const std::vector<const DoFHandler<dim,dim>*> &mg_dof);
318 
333  virtual void prolongate (const unsigned int to_level,
336 
355  virtual void restrict_and_add (const unsigned int from_level,
358 
369  template <typename Number2, int spacedim>
370  void
371  copy_to_mg (const DoFHandler<dim,spacedim> &mg_dof,
374 
378  template <typename Number2, int spacedim>
379  void
380  copy_to_mg (const std::vector<const DoFHandler<dim,spacedim>*> &mg_dof,
383 
387  template <typename Number2, int spacedim>
388  void
389  copy_from_mg (const DoFHandler<dim,spacedim> &mg_dof,
392 
396  template <typename Number2, int spacedim>
397  void
398  copy_from_mg (const std::vector<const DoFHandler<dim,spacedim>*> &mg_dof,
401 
405  std::size_t memory_consumption () const;
406 
411  static const bool supports_dof_handler_vector = true;
412 
413 private:
414 
418  std::vector<MGTransferMatrixFree<dim,Number>> matrix_free_transfer_vector;
419 
424  const bool same_for_all;
425 };
426 
427 
431 //------------------------ templated functions -------------------------
432 #ifndef DOXYGEN
433 
434 
435 template <int dim, typename Number>
436 template <typename Number2, int spacedim>
437 void
442 {
443  const unsigned int min_level = dst.min_level();
444  const unsigned int max_level = dst.max_level();
445 
446  Assert (max_level == dof_handler.get_triangulation().n_global_levels()-1,
447  ExcDimensionMismatch(max_level,dof_handler.get_triangulation().n_global_levels()-1));
448 
450  (dynamic_cast<const parallel::Triangulation<dim,spacedim>*>
451  (&dof_handler.get_triangulation()));
452  MPI_Comm mpi_communicator = p_tria != nullptr ? p_tria->get_communicator() : MPI_COMM_SELF;
453 
454  // resize the dst vector if it's empty or has incorrect size
455  MGLevelObject<IndexSet> relevant_dofs(min_level,max_level);
456  for (unsigned int level = min_level; level <= max_level; ++level)
457  {
459  relevant_dofs[level]);
460  if (dst[level].size() != dof_handler.locally_owned_mg_dofs(level).size() ||
461  dst[level].local_size() != dof_handler.locally_owned_mg_dofs(level).n_elements())
462  dst[level].reinit(dof_handler.locally_owned_mg_dofs(level),
463  relevant_dofs[level],
464  mpi_communicator);
465  }
466 
467  const FiniteElement<dim,spacedim> &fe = dof_handler.get_fe();
468 
469  // copy fine level vector to active cells in MG hierarchy
470  this->copy_to_mg (dof_handler, dst, src, true);
471 
472  // FIXME: maybe need to store hanging nodes constraints per level?
473  // MGConstrainedDoFs does NOT keep this info right now, only periodicity constraints...
474  dst[max_level].update_ghost_values();
475  // do the transfer from level to level-1:
476  for (unsigned int level=max_level; level > min_level; --level)
477  {
478  // auxiliary vector which always has ghost elements
480  ghosted_vector(dof_handler.locally_owned_mg_dofs(level),
481  relevant_dofs[level],
482  mpi_communicator);
483  ghosted_vector = dst[level];
484  ghosted_vector.update_ghost_values();
485 
486  std::vector<Number> dof_values_coarse(fe.dofs_per_cell);
487  Vector<Number> dof_values_fine(fe.dofs_per_cell);
488  Vector<Number> tmp(fe.dofs_per_cell);
489  std::vector<types::global_dof_index> dof_indices(fe.dofs_per_cell);
490  typename DoFHandler<dim>::cell_iterator cell=dof_handler.begin(level-1);
491  typename DoFHandler<dim>::cell_iterator endc=dof_handler.end(level-1);
492  for ( ; cell != endc; ++cell)
493  if (cell->is_locally_owned_on_level())
494  {
495  // if we get to a cell without children (== active), we can
496  // skip it as there values should be already set by the
497  // equivalent of copy_to_mg()
498  if (!cell->has_children())
499  continue;
500 
501  std::fill(dof_values_coarse.begin(), dof_values_coarse.end(), 0.);
502  for (unsigned int child=0; child<cell->n_children(); ++child)
503  {
504  cell->child(child)->get_mg_dof_indices(dof_indices);
505  for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
506  dof_values_fine(i) = ghosted_vector(dof_indices[i]);
507  fe.get_restriction_matrix(child, cell->refinement_case()).vmult (tmp, dof_values_fine);
508  for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
509  if (fe.restriction_is_additive(i))
510  dof_values_coarse[i] += tmp[i];
511  else if (tmp(i) != 0.)
512  dof_values_coarse[i] = tmp[i];
513  }
514  cell->get_mg_dof_indices(dof_indices);
515  for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
516  dst[level-1](dof_indices[i]) = dof_values_coarse[i];
517  }
518 
519  dst[level-1].compress(VectorOperation::insert);
520  dst[level-1].update_ghost_values();
521  }
522 }
523 
524 
525 
526 template <int dim, typename Number>
527 template <typename Number2, int spacedim>
528 void
530 copy_to_mg (const DoFHandler<dim,spacedim> &mg_dof,
533 {
534  AssertDimension(matrix_free_transfer_vector.size(),1);
535  Assert(same_for_all,
536  ExcMessage("This object was initialized with support for usage with one "
537  "DoFHandler for each block, but this method assumes that "
538  "the same DoFHandler is used for all the blocks!"));
539  const std::vector<const DoFHandler<dim, spacedim>*> mg_dofs (src.n_blocks(),&mg_dof);
540 
541  copy_to_mg(mg_dofs, dst, src);
542 }
543 
544 template <int dim, typename Number>
545 template <typename Number2, int spacedim>
546 void
548 copy_to_mg (const std::vector<const DoFHandler<dim,spacedim>*> &mg_dof,
551 {
552  const unsigned int n_blocks = src.n_blocks();
553  AssertDimension(mg_dof.size(), n_blocks);
554 
555  if (n_blocks==0)
556  return;
557 
558  const unsigned int min_level = dst.min_level();
559  const unsigned int max_level = dst.max_level();
560 
561  // this function is normally called within the Multigrid class with
562  // dst == defect level block vector. At first run this vector is not
563  // initialized. Do this below:
564  {
566  (dynamic_cast<const parallel::Triangulation<dim,spacedim>*>
567  (&(mg_dof[0]->get_triangulation())));
568  for (unsigned int i=1; i<n_blocks; ++i)
570  (&(mg_dof[0]->get_triangulation())) == tria),
571  ExcMessage("The DoFHandler use different Triangulations!"));
572 
573  for (unsigned int level = min_level; level <= max_level; ++level)
574  {
575  dst[level].reinit(n_blocks);
576  bool collect_size = false;
577  for (unsigned int b = 0; b < n_blocks; ++b)
578  {
579  LinearAlgebra::distributed::Vector<Number> &v = dst[level].block(b);
580  if (v.size() != mg_dof[b]->locally_owned_mg_dofs(level).size() ||
581  v.local_size() != mg_dof[b]->locally_owned_mg_dofs(level).n_elements())
582  {
583  v.reinit(mg_dof[b]->locally_owned_mg_dofs(level), tria != nullptr ?
584  tria->get_communicator() : MPI_COMM_SELF);
585  collect_size = true;
586  }
587  else
588  v = 0.;
589  }
590  if (collect_size)
591  dst[level].collect_sizes ();
592  }
593  }
594 
595  // FIXME: this a quite ugly as we need a temporary object:
596  MGLevelObject<LinearAlgebra::distributed::Vector<Number>> dst_non_block(min_level, max_level);
597 
598  for (unsigned int b = 0; b < n_blocks; ++b)
599  {
600  for (unsigned int l = min_level; l <= max_level; ++l)
601  dst_non_block[l].reinit(dst[l].block(b));
602  const unsigned int data_block = same_for_all ? 0 : b;
603  matrix_free_transfer_vector[data_block].copy_to_mg(*mg_dof[b], dst_non_block, src.block(b));
604 
605  for (unsigned int l = min_level; l <= max_level; ++l)
606  dst[l].block(b) = dst_non_block[l];
607  }
608 }
609 
610 template <int dim, typename Number>
611 template <typename Number2, int spacedim>
612 void
617 {
618  AssertDimension(matrix_free_transfer_vector.size(),1);
619  const std::vector<const DoFHandler<dim, spacedim>*> mg_dofs (dst.n_blocks(), &mg_dof);
620 
621  copy_from_mg(mg_dofs, dst, src);
622 }
623 
624 template <int dim, typename Number>
625 template <typename Number2, int spacedim>
626 void
628 copy_from_mg (const std::vector<const DoFHandler<dim,spacedim>*> &mg_dof,
631 {
632  const unsigned int n_blocks = dst.n_blocks();
633  AssertDimension(mg_dof.size(), n_blocks);
634 
635  if (n_blocks==0)
636  return;
637 
638  const unsigned int min_level = src.min_level();
639  const unsigned int max_level = src.max_level();
640 
641  for (unsigned int l = min_level; l <= max_level; ++l)
642  AssertDimension(src[l].n_blocks(), dst.n_blocks());
643 
644  // FIXME: this a quite ugly as we need a temporary object:
645  MGLevelObject<LinearAlgebra::distributed::Vector<Number>> src_non_block(min_level, max_level);
646 
647  for (unsigned int b = 0; b < n_blocks; ++b)
648  {
649  for (unsigned int l = min_level; l <= max_level; ++l)
650  {
651  src_non_block[l].reinit(src[l].block(b));
652  src_non_block[l] = src[l].block(b);
653  }
654  const unsigned int data_block = same_for_all ? 0 : b;
655  matrix_free_transfer_vector[data_block].copy_from_mg(*mg_dof[b], dst.block(b), src_non_block);
656  }
657 }
658 
659 
660 
661 #endif // DOXYGEN
662 
663 
664 DEAL_II_NAMESPACE_CLOSE
665 
666 #endif
void reinit(const size_type size, const bool omit_zeroing_entries=false)
bool restriction_is_additive(const unsigned int index) const
Definition: fe.h:3194
void do_restrict_add(const unsigned int from_level, LinearAlgebra::distributed::Vector< Number > &dst, const LinearAlgebra::distributed::Vector< Number > &src) const
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1248
std::vector< unsigned int > n_owned_level_cells
cell_iterator begin(const unsigned int level=0) const
Definition: dof_handler.cc:723
AlignedVector< VectorizedArray< Number > > evaluation_data
static ::ExceptionBase & ExcNoProlongation()
virtual void restrict_and_add(const unsigned int from_level, LinearAlgebra::distributed::Vector< Number > &dst, const LinearAlgebra::distributed::Vector< Number > &src) const
std::size_t memory_consumption() const
std::vector< std::vector< std::vector< unsigned short > > > dirichlet_indices
void build(const DoFHandler< dim, dim > &mg_dof)
void initialize_constraints(const MGConstrainedDoFs &mg_constrained_dofs)
cell_iterator end() const
Definition: dof_handler.cc:751
#define AssertThrow(cond, exc)
Definition: exceptions.h:1221
void extract_locally_relevant_level_dofs(const DoFHandlerType &dof_handler, const unsigned int level, IndexSet &dof_set)
Definition: dof_tools.cc:1127
std::size_t memory_consumption() const
std::vector< MGTransferMatrixFree< dim, Number > > matrix_free_transfer_vector
size_type size() const
Definition: index_set.h:1575
void interpolate_to_mg(const DoFHandler< dim, spacedim > &mg_dof, MGLevelObject< LinearAlgebra::distributed::Vector< Number >> &dst, const LinearAlgebra::distributed::Vector< Number2 > &src) const
static ::ExceptionBase & ExcMessage(std::string arg1)
AlignedVector< VectorizedArray< Number > > prolongation_matrix_1d
std::vector< std::vector< std::pair< unsigned int, unsigned int > > > parent_child_connect
virtual size_type size() const override
#define Assert(cond, exc)
Definition: exceptions.h:1142
virtual const FullMatrix< double > & get_restriction_matrix(const unsigned int child, const RefinementCase< dim > &refinement_case=RefinementCase< dim >::isotropic_refinement) const
Definition: fe.cc:302
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
virtual MPI_Comm get_communicator() const
Definition: tria_base.cc:146
void copy_to_mg(const DoFHandler< dim, spacedim > &mg_dof, MGLevelObject< LinearAlgebra::distributed::BlockVector< Number >> &dst, const LinearAlgebra::distributed::BlockVector< Number2 > &src) const
const FiniteElement< dim, spacedim > & get_fe(const unsigned int index=0) const
#define DeclException0(Exception0)
Definition: exceptions.h:323
SmartPointer< const MGConstrainedDoFs, MGLevelGlobalTransfer< LinearAlgebra::distributed::Vector< Number > > > mg_constrained_dofs
Definition: mg_transfer.h:486
std::vector< AlignedVector< VectorizedArray< Number > > > weights_on_refined
virtual void prolongate(const unsigned int to_level, LinearAlgebra::distributed::BlockVector< Number > &dst, const LinearAlgebra::distributed::BlockVector< Number > &src) const
const IndexSet & locally_owned_mg_dofs(const unsigned int level) const
std::vector< std::vector< unsigned int > > level_dof_indices
virtual ~MGTransferMatrixFree()=default
const unsigned int dofs_per_cell
Definition: fe_base.h:295
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
static const bool supports_dof_handler_vector
void copy_from_mg(const DoFHandler< dim, spacedim > &mg_dof, LinearAlgebra::distributed::BlockVector< Number2 > &dst, const MGLevelObject< LinearAlgebra::distributed::BlockVector< Number >> &src) const
void do_prolongate_add(const unsigned int to_level, LinearAlgebra::distributed::Vector< Number > &dst, const LinearAlgebra::distributed::Vector< Number > &src) const
MGTransferBlockMatrixFree()=default
virtual void restrict_and_add(const unsigned int from_level, LinearAlgebra::distributed::BlockVector< Number > &dst, const LinearAlgebra::distributed::BlockVector< Number > &src) const
const Triangulation< dim, spacedim > & get_triangulation() const
virtual void prolongate(const unsigned int to_level, LinearAlgebra::distributed::Vector< Number > &dst, const LinearAlgebra::distributed::Vector< Number > &src) const
void initialize_constraints(const MGConstrainedDoFs &mg_constrained_dofs)
BlockType & block(const unsigned int i)
size_type n_elements() const
Definition: index_set.h:1717
virtual ~MGTransferBlockMatrixFree()=default
void build(const DoFHandler< dim, dim > &mg_dof)
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)