Reference documentation for deal.II version 8.5.1
quadrature_point_data.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__quadrature_point_data_h
17 #define dealii__quadrature_point_data_h
18 
19 // must include config before checking for DEAL_II_WITH_CXX11
20 #include <deal.II/base/config.h>
21 
22 #ifdef DEAL_II_WITH_CXX11
23 
24 #include <deal.II/base/quadrature.h>
25 #include <deal.II/base/subscriptor.h>
26 #include <deal.II/grid/tria.h>
27 #include <deal.II/grid/tria_accessor.h>
28 #include <deal.II/distributed/tria.h>
29 #include <deal.II/fe/fe_tools.h>
30 #include <deal.II/fe/fe.h>
31 #include <deal.II/lac/vector.h>
32 
33 #include <vector>
34 #include <map>
35 #include <type_traits>
36 
37 DEAL_II_NAMESPACE_OPEN
38 
41 
59 template <typename CellIteratorType, typename DataType>
61 {
62 public:
67 
72 
94  template<typename T=DataType>
95  void initialize(const CellIteratorType &cell,
96  const unsigned int number_of_data_points_per_cell);
97 
103  template<typename T=DataType>
104  void initialize(const CellIteratorType &cell_start,
105  const CellIteratorType &cell_end,
106  const unsigned int number_of_data_points_per_cell);
107 
117  bool erase(const CellIteratorType &cell);
118 
122  void clear();
123 
134  template<typename T=DataType>
135  std::vector<std::shared_ptr<T> > get_data(const CellIteratorType &cell);
136 
147  template<typename T=DataType>
148  std::vector<std::shared_ptr<const T> > get_data(const CellIteratorType &cell) const;
149 
150 private:
154  std::map<CellIteratorType, std::vector<std::shared_ptr<DataType>>> map;
155 
156 };
157 
158 
177 {
178 public:
183 
188 
194  virtual unsigned int number_of_values() const = 0;
195 
205  virtual void pack_values(std::vector<double> &values) const = 0;
206 
214  virtual void unpack_values(const std::vector<double> &values) = 0;
215 };
216 
217 
218 #ifdef DEAL_II_WITH_P4EST
219 namespace parallel
220 {
221  namespace distributed
222  {
325  template <int dim, typename DataType>
327  {
328  public:
329  static_assert(std::is_base_of<TransferableQuadraturePointData, DataType>::value,
330  "User's DataType class should be derived from QPData");
331 
336 
348  const Quadrature<dim> &mass_quadrature,
349  const Quadrature<dim> &data_quadrature);
350 
355 
368 
379  void interpolate ();
380 
381  private:
388  const typename parallel::distributed::Triangulation<dim,dim>::CellStatus status,
389  void *data);
390 
397  const typename parallel::distributed::Triangulation<dim,dim>::CellStatus status,
398  const void *data);
399 
403  const std::unique_ptr<const FiniteElement<dim> > projection_fe;
404 
408  std::size_t data_size_in_bytes;
409 
413  const unsigned int n_q_points;
414 
420 
426 
433 
438 
444 
449  unsigned int offset;
450 
455 
460  };
461 
462  } // distributed
463 
464 } // parallel
465 
466 #endif
467 
470 #ifndef DOXYGEN
471 
472 // ------------------- inline and template functions ----------------
473 
474 //--------------------------------------------------------------------
475 // TransferableQuadraturePointData
476 //--------------------------------------------------------------------
478 {}
479 
481 {}
482 
483 //--------------------------------------------------------------------
484 // CellDataStorage
485 //--------------------------------------------------------------------
486 
487 template <typename CellIteratorType, typename DataType>
490  :
491  Subscriptor()
492 {}
493 
494 
495 
496 template <typename CellIteratorType, typename DataType>
499 {}
500 
501 
502 
503 template <typename CellIteratorType, typename DataType>
504 template<typename T>
505 void CellDataStorage<CellIteratorType,DataType>::initialize(const CellIteratorType &cell,
506  const unsigned int n_q_points)
507 {
508  static_assert(std::is_base_of<DataType, T>::value,
509  "User's T class should be derived from user's DataType class");
510 
511  if (map.find(cell) == map.end())
512  {
513  map[cell] = std::vector<std::shared_ptr<DataType> >(n_q_points);
514  // we need to initialise one-by-one as the std::vector<>(q, T())
515  // will end with a single same T object stored in each element of the vector:
516  auto it = map.find(cell);
517  for (unsigned int q=0; q < n_q_points; q++)
518  it->second[q] = std::make_shared<T>();
519  }
520 }
521 
522 
523 
524 template <typename CellIteratorType, typename DataType>
525 template<typename T>
526 void CellDataStorage<CellIteratorType,DataType>::initialize(const CellIteratorType &cell_start,
527  const CellIteratorType &cell_end,
528  const unsigned int number)
529 {
530  for (CellIteratorType it = cell_start; it != cell_end; it++)
531  if (it->is_locally_owned())
532  initialize<T>(it,number);
533 }
534 
535 
536 
537 template <typename CellIteratorType, typename DataType>
538 bool CellDataStorage<CellIteratorType,DataType>::erase(const CellIteratorType &cell)
539 {
540  const auto it = map.find(cell);
541  for (unsigned int i = 0; i < it->second.size(); i++)
542  {
543  Assert(it->second[i].unique(),
544  ExcMessage("Can not erase the cell data multiple objects reference its data."));
545  }
546 
547  return (map.erase(cell)==1);
548 }
549 
550 
551 
552 
553 template <typename CellIteratorType, typename DataType>
555 {
556  // Do not call
557  // map.clear();
558  // as we want to be sure no one uses the stored objects. Loop manually:
559  auto it = map.begin();
560  while (it != map.end())
561  {
562  // loop over all objects and see if noone is using them
563  for (unsigned int i = 0; i < it->second.size(); i++)
564  {
565  Assert(it->second[i].unique(),
566  ExcMessage("Can not erase the cell data, multiple objects reference it."));
567  }
568  it = map.erase(it);
569  }
570 }
571 
572 
573 
574 
575 template <typename CellIteratorType, typename DataType>
576 template <typename T>
577 std::vector<std::shared_ptr<T> >
578 CellDataStorage<CellIteratorType,DataType>::get_data(const CellIteratorType &cell)
579 {
580  static_assert(std::is_base_of<DataType, T>::value,
581  "User's T class should be derived from user's DataType class");
582 
583  auto it = map.find(cell);
584  Assert(it != map.end(), ExcMessage("Could not find data for the cell"));
585 
586  // It would be nice to have a specialized version of this function for T==DataType.
587  // However explicit (i.e full) specialization of a member template is only allowed
588  // when the enclosing class is also explicitly (i.e fully) specialized.
589  // Thus, stick with copying of shared pointers even when the T==DataType:
590  std::vector<std::shared_ptr<T>> res (it->second.size());
591  for (unsigned int q = 0; q < res.size(); q++)
592  res[q] = std::dynamic_pointer_cast<T>(it->second[q]);
593  return res;
594 }
595 
596 
597 
598 
599 template <typename CellIteratorType, typename DataType>
600 template <typename T>
601 std::vector<std::shared_ptr<const T> >
602 CellDataStorage<CellIteratorType,DataType>::get_data(const CellIteratorType &cell) const
603 {
604  static_assert(std::is_base_of<DataType, T>::value,
605  "User's T class should be derived from user's DataType class");
606 
607  auto it = map.find(cell);
608  Assert(it != map.end(), ExcMessage("Could not find QP data for the cell"));
609 
610  // Cast base class to the desired class. This has to be done irrespectively of
611  // T==DataType as we need to return shapred_ptr<const T> to make sure the user
612  // does not modify the content of QP objects
613  std::vector<std::shared_ptr<const T>> res (it->second.size());
614  for (unsigned int q = 0; q < res.size(); q++)
615  res[q] = std::dynamic_pointer_cast<const T>(it->second[q]);
616  return res;
617 }
618 
619 //--------------------------------------------------------------------
620 // ContinuousQuadratureDataTransfer
621 //--------------------------------------------------------------------
622 
623 
624 /*
625  * Pack cell data of type @p DataType stored using @p data_storage in @p cell
626  * at each quadrature point to @p matrix_data. Here @p matrix_data is a matrix
627  * whose first index corresponds to different quadrature points on the cell
628  * whereas the second index represents different values stored at each
629  * quadrature point in the DataType class.
630  */
631 template<typename CellIteratorType, typename DataType>
632 void pack_cell_data
633 (const CellIteratorType &cell,
634  const CellDataStorage<CellIteratorType,DataType> *data_storage,
635  FullMatrix<double> &matrix_data)
636 {
637  static_assert(std::is_base_of<TransferableQuadraturePointData, DataType>::value,
638  "User's DataType class should be derived from QPData");
639 
640  const std::vector<std::shared_ptr<const DataType> > qpd = data_storage->get_data(cell);
641 
642  const unsigned int n = matrix_data.n();
643 
644  std::vector<double> single_qp_data(n);
645  Assert (qpd.size() == matrix_data.m(),
646  ExcDimensionMismatch(qpd.size(), matrix_data.m()));
647  for (unsigned int q = 0; q < qpd.size(); q++)
648  {
649  qpd[q]->pack_values(single_qp_data);
650  Assert (single_qp_data.size() == n,
651  ExcDimensionMismatch(single_qp_data.size(),n));
652 
653  for (unsigned int i = 0; i < n; i++)
654  matrix_data(q,i) = single_qp_data[i];
655  }
656 }
657 
658 
659 
660 
661 /*
662  * the opposite of the pack function above.
663  */
664 template<typename CellIteratorType, typename DataType>
665 void unpack_to_cell_data
666 (const CellIteratorType &cell,
667  const FullMatrix<double> &values_at_qp,
669 {
670  static_assert(std::is_base_of<TransferableQuadraturePointData, DataType>::value,
671  "User's DataType class should be derived from QPData");
672 
673  std::vector<std::shared_ptr<DataType> > qpd = data_storage->get_data(cell);
674 
675  const unsigned int n = values_at_qp.n();
676 
677  std::vector<double> single_qp_data(n);
678  Assert(qpd.size() == values_at_qp.m(),
679  ExcDimensionMismatch(qpd.size(), values_at_qp.m()));
680 
681  for (unsigned int q = 0; q < qpd.size(); q++)
682  {
683  for (unsigned int i = 0; i < n; i++)
684  single_qp_data[i] = values_at_qp(q,i);
685  qpd[q]->unpack_values(single_qp_data);
686  }
687 }
688 
689 
690 #ifdef DEAL_II_WITH_P4EST
691 
692 namespace parallel
693 {
694  namespace distributed
695  {
696  template<int dim, typename DataType>
698  (const FiniteElement<dim> &projection_fe_,
699  const Quadrature<dim> &lhs_quadrature,
700  const Quadrature<dim> &rhs_quadrature)
701  :
702  projection_fe(std::unique_ptr<const FiniteElement<dim> >(projection_fe_.clone())),
703  data_size_in_bytes(0),
704  n_q_points(rhs_quadrature.size()),
705  project_to_fe_matrix(projection_fe->dofs_per_cell,n_q_points),
706  project_to_qp_matrix(n_q_points,projection_fe->dofs_per_cell),
707  offset(0),
708  data_storage(nullptr),
709  triangulation(nullptr)
710  {
711  Assert(projection_fe->n_components() == 1,
712  ExcMessage("ContinuousQuadratureDataTransfer requires scalar FiniteElement"));
713 
715  (*projection_fe.get(),
716  lhs_quadrature,
717  rhs_quadrature,
719 
721  (*projection_fe.get(),
722  rhs_quadrature,
724  }
725 
726 
727 
728  template<int dim, typename DataType>
730  {}
731 
732 
733 
734  template<int dim, typename DataType>
738  {
739  Assert (data_storage == nullptr,
740  ExcMessage("This function can be called only once"));
741  triangulation = &tr_;
742  data_storage = &data_storage_;
743  // get the number from the first active cell
744  unsigned int number_of_values = 0;
745  // if triangulation has some active cells locally owned cells on this processor we can expect
746  // data to be initialized. Do that to get the number:
747  for (typename parallel::distributed::Triangulation<dim>::active_cell_iterator it = triangulation->begin_active();
748  it != triangulation->end(); it++)
749  if (it->is_locally_owned())
750  {
751  std::vector<std::shared_ptr<DataType> > qpd = data_storage->get_data(it);
752  number_of_values = qpd[0]->number_of_values();
753  break;
754  }
755  // some processors may have no data stored, thus get the maximum among all processors:
756  number_of_values = Utilities::MPI::max(number_of_values, triangulation->get_communicator ());
757  Assert (number_of_values > 0,
758  ExcInternalError());
759  const unsigned int dofs_per_cell = projection_fe->dofs_per_cell;
760  matrix_dofs.reinit(dofs_per_cell,number_of_values);
761  matrix_dofs_child.reinit(dofs_per_cell,number_of_values);
762  matrix_quadrature.reinit(n_q_points,number_of_values);
763  data_size_in_bytes = sizeof(double) * dofs_per_cell * number_of_values;
764 
765  offset = triangulation->register_data_attach(data_size_in_bytes,
767  this,
768  std_cxx11::_1,
769  std_cxx11::_2,
770  std_cxx11::_3));
771  }
772 
773 
774 
775  template<int dim, typename DataType>
777  {
778  triangulation->notify_ready_to_unpack(offset,
780  this,
781  std_cxx11::_1,
782  std_cxx11::_2,
783  std_cxx11::_3));
784 
785  // invalidate the pointers
786  data_storage = nullptr;
787  triangulation = nullptr;
788  }
789 
790 
791 
792  template<int dim, typename DataType>
795  const typename parallel::distributed::Triangulation<dim,dim>::CellStatus /*status*/,
796  void *data)
797  {
798  double *data_store = reinterpret_cast<double *>(data);
799 
800  pack_cell_data(cell,data_storage,matrix_quadrature);
801 
802  // project to FE
803  project_to_fe_matrix.mmult(matrix_dofs, matrix_quadrature);
804 
805  std::memcpy(data_store, &matrix_dofs(0,0), data_size_in_bytes);
806  }
807 
808 
809 
810  template<int dim, typename DataType>
813  const typename parallel::distributed::Triangulation<dim,dim>::CellStatus status,
814  const void *data)
815  {
818  (void) status;
819 
820  const double *data_store = reinterpret_cast<const double *>(data);
821 
822  std::memcpy(&matrix_dofs(0,0), data_store, data_size_in_bytes);
823 
824  if (cell->has_children())
825  {
826  // we need to first use prolongation matrix to get dofvalues on child
827  // cells based on dofvalues stored in the parent's data_store
828  for (unsigned int child=0; child<cell->n_children(); ++child)
829  if (cell->child(child)->is_locally_owned())
830  {
831  projection_fe->get_prolongation_matrix(child, cell->refinement_case())
832  .mmult (matrix_dofs_child, matrix_dofs);
833 
834  // now we do the usual business of evaluating FE on quadrature points:
835  project_to_qp_matrix.mmult(matrix_quadrature,matrix_dofs_child);
836 
837  // finally, put back into the map:
838  unpack_to_cell_data(cell->child(child),matrix_quadrature,data_storage);
839  }
840  }
841  else
842  {
843  // if there are no children, evaluate FE field at
844  // rhs_quadrature points.
845  project_to_qp_matrix.mmult(matrix_quadrature,matrix_dofs);
846 
847  // finally, put back into the map:
848  unpack_to_cell_data(cell,matrix_quadrature,data_storage);
849  }
850  }
851 
852  } // distributed
853 
854 } // parallel
855 
856 #endif // DEAL_II_WITH_P4EST
857 
858 #endif // DOXYGEN
859 DEAL_II_NAMESPACE_CLOSE
860 
861 #endif // CXX11
862 
863 #endif
size_type m() const
void compute_interpolation_to_quadrature_points_matrix(const FiniteElement< dim, spacedim > &fe, const Quadrature< dim > &quadrature, FullMatrix< double > &I_q)
Definition: fe_tools.cc:2719
STL namespace.
std::map< CellIteratorType, std::vector< std::shared_ptr< DataType > > > map
virtual unsigned int number_of_values() const =0
std::vector< std::shared_ptr< T > > get_data(const CellIteratorType &cell)
bool erase(const CellIteratorType &cell)
static ::ExceptionBase & ExcMessage(std::string arg1)
size_type n() const
#define Assert(cond, exc)
Definition: exceptions.h:313
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
void compute_projection_from_quadrature_points_matrix(const FiniteElement< dim, spacedim > &fe, const Quadrature< dim > &lhs_quadrature, const Quadrature< dim > &rhs_quadrature, FullMatrix< double > &X)
Definition: fe_tools.cc:2679
const std::unique_ptr< const FiniteElement< dim > > projection_fe
ContinuousQuadratureDataTransfer(const FiniteElement< dim > &projection_fe, const Quadrature< dim > &mass_quadrature, const Quadrature< dim > &data_quadrature)
void prepare_for_coarsening_and_refinement(parallel::distributed::Triangulation< dim > &tria, CellDataStorage< CellIteratorType, DataType > &data_storage)
virtual void unpack_values(const std::vector< double > &values)=0
void unpack_function(const typename parallel::distributed::Triangulation< dim, dim >::cell_iterator &cell, const typename parallel::distributed::Triangulation< dim, dim >::CellStatus status, const void *data)
::Triangulation< dim, spacedim >::active_cell_iterator active_cell_iterator
Definition: tria.h:285
parallel::distributed::Triangulation< dim >::cell_iterator CellIteratorType
void pack_function(const typename parallel::distributed::Triangulation< dim, dim >::cell_iterator &cell, const typename parallel::distributed::Triangulation< dim, dim >::CellStatus status, void *data)
parallel::distributed::Triangulation< dim > * triangulation
::Triangulation< dim, spacedim >::cell_iterator cell_iterator
Definition: tria.h:265
static ::ExceptionBase & ExcNotImplemented()
CellDataStorage< CellIteratorType, DataType > * data_storage
virtual void pack_values(std::vector< double > &values) const =0
T max(const T &t, const MPI_Comm &mpi_communicator)
void initialize(const CellIteratorType &cell, const unsigned int number_of_data_points_per_cell)
static ::ExceptionBase & ExcInternalError()