Reference documentation for deal.II version 9.1.0-pre
quadrature_point_data.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2016 - 2018 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_quadrature_point_data_h
17 #define dealii_quadrature_point_data_h
18 
19 #include <deal.II/base/config.h>
20 
21 #include <deal.II/base/quadrature.h>
22 #include <deal.II/base/subscriptor.h>
23 
24 #include <deal.II/distributed/tria.h>
25 
26 #include <deal.II/fe/fe.h>
27 #include <deal.II/fe/fe_tools.h>
28 
29 #include <deal.II/grid/tria.h>
30 #include <deal.II/grid/tria_accessor.h>
31 
32 #include <deal.II/lac/vector.h>
33 
34 #include <map>
35 #include <type_traits>
36 #include <vector>
37 
38 DEAL_II_NAMESPACE_OPEN
39 
42 
58 template <typename CellIteratorType, typename DataType>
60 {
61 public:
65  CellDataStorage() = default;
66 
70  ~CellDataStorage() override = default;
71 
93  template <typename T = DataType>
94  void
95  initialize(const CellIteratorType &cell,
96  const unsigned int number_of_data_points_per_cell);
97 
103  template <typename T = DataType>
104  void
105  initialize(const CellIteratorType &cell_start,
106  const CellIteratorType &cell_end,
107  const unsigned int number_of_data_points_per_cell);
108 
118  bool
119  erase(const CellIteratorType &cell);
120 
124  void
125  clear();
126 
138  template <typename T = DataType>
139  std::vector<std::shared_ptr<T>>
140  get_data(const CellIteratorType &cell);
141 
153  template <typename T = DataType>
154  std::vector<std::shared_ptr<const T>>
155  get_data(const CellIteratorType &cell) const;
156 
157 private:
161  std::map<CellIteratorType, std::vector<std::shared_ptr<DataType>>> map;
162 };
163 
164 
184 {
185 public:
190 
194  virtual ~TransferableQuadraturePointData() = default;
195 
201  virtual unsigned int
202  number_of_values() const = 0;
203 
214  virtual void
215  pack_values(std::vector<double> &values) const = 0;
216 
225  virtual void
226  unpack_values(const std::vector<double> &values) = 0;
227 };
228 
229 
230 #ifdef DEAL_II_WITH_P4EST
231 namespace parallel
232 {
233  namespace distributed
234  {
346  template <int dim, typename DataType>
348  {
349  public:
350  static_assert(
351  std::is_base_of<TransferableQuadraturePointData, DataType>::value,
352  "User's DataType class should be derived from TransferableQuadraturePointData");
353 
357  using CellIteratorType =
359 
371  const Quadrature<dim> &mass_quadrature,
372  const Quadrature<dim> &data_quadrature);
373 
378 
389  void
390  prepare_for_coarsening_and_refinement(
393 
404  void
405  interpolate();
406 
407  private:
413  std::vector<char>
414  pack_function(
416  &cell,
417  const typename parallel::distributed::Triangulation<dim>::CellStatus
418  status);
419 
425  void
426  unpack_function(
428  &cell,
429  const typename parallel::distributed::Triangulation<dim>::CellStatus
430  status,
431  const boost::iterator_range<std::vector<char>::const_iterator>
432  &data_range);
433 
437  const std::unique_ptr<const FiniteElement<dim>> projection_fe;
438 
443  std::size_t data_size_in_bytes;
444 
448  const unsigned int n_q_points;
449 
455 
461 
469 
474 
480 
485  unsigned int handle;
486 
491 
497  };
498 
499  } // namespace distributed
500 
501 } // namespace parallel
502 
503 #endif
504 
507 #ifndef DOXYGEN
508 
509 // ------------------- inline and template functions ----------------
510 
511 //--------------------------------------------------------------------
512 // CellDataStorage
513 //--------------------------------------------------------------------
514 
515 template <typename CellIteratorType, typename DataType>
516 template <typename T>
517 void
519  const CellIteratorType &cell,
520  const unsigned int n_q_points)
521 {
522  static_assert(std::is_base_of<DataType, T>::value,
523  "User's T class should be derived from user's DataType class");
524 
525  if (map.find(cell) == map.end())
526  {
527  map[cell] = std::vector<std::shared_ptr<DataType>>(n_q_points);
528  // we need to initialize one-by-one as the std::vector<>(q, T())
529  // will end with a single same T object stored in each element of the
530  // vector:
531  auto it = map.find(cell);
532  for (unsigned int q = 0; q < n_q_points; q++)
533  it->second[q] = std::make_shared<T>();
534  }
535 }
536 
537 
538 
539 template <typename CellIteratorType, typename DataType>
540 template <typename T>
541 void
543  const CellIteratorType &cell_start,
544  const CellIteratorType &cell_end,
545  const unsigned int number)
546 {
547  for (CellIteratorType it = cell_start; it != cell_end; it++)
548  if (it->is_locally_owned())
549  initialize<T>(it, number);
550 }
551 
552 
553 
554 template <typename CellIteratorType, typename DataType>
555 bool
557 {
558  const auto it = map.find(cell);
559  for (unsigned int i = 0; i < it->second.size(); i++)
560  {
561  Assert(
562  it->second[i].unique(),
563  ExcMessage(
564  "Can not erase the cell data multiple objects reference its data."));
565  }
566 
567  return (map.erase(cell) == 1);
568 }
569 
570 
571 
572 template <typename CellIteratorType, typename DataType>
573 void
575 {
576  // Do not call
577  // map.clear();
578  // as we want to be sure no one uses the stored objects. Loop manually:
579  auto it = map.begin();
580  while (it != map.end())
581  {
582  // loop over all objects and see if no one is using them
583  for (unsigned int i = 0; i < it->second.size(); i++)
584  {
585  Assert(
586  it->second[i].unique(),
587  ExcMessage(
588  "Can not erase the cell data, multiple objects reference it."));
589  }
590  it = map.erase(it);
591  }
592 }
593 
594 
595 
596 template <typename CellIteratorType, typename DataType>
597 template <typename T>
598 std::vector<std::shared_ptr<T>>
600  const CellIteratorType &cell)
601 {
602  static_assert(std::is_base_of<DataType, T>::value,
603  "User's T class should be derived from user's DataType class");
604 
605  auto it = map.find(cell);
606  Assert(it != map.end(), ExcMessage("Could not find data for the cell"));
607 
608  // It would be nice to have a specialized version of this function for
609  // T==DataType. However explicit (i.e full) specialization of a member
610  // template is only allowed when the enclosing class is also explicitly (i.e
611  // fully) specialized. Thus, stick with copying of shared pointers even when
612  // the T==DataType:
613  std::vector<std::shared_ptr<T>> res(it->second.size());
614  for (unsigned int q = 0; q < res.size(); q++)
615  res[q] = std::dynamic_pointer_cast<T>(it->second[q]);
616  return res;
617 }
618 
619 
620 
621 template <typename CellIteratorType, typename DataType>
622 template <typename T>
623 std::vector<std::shared_ptr<const T>>
625  const CellIteratorType &cell) const
626 {
627  static_assert(std::is_base_of<DataType, T>::value,
628  "User's T class should be derived from user's DataType class");
629 
630  auto it = map.find(cell);
631  Assert(it != map.end(), ExcMessage("Could not find QP data for the cell"));
632 
633  // Cast base class to the desired class. This has to be done irrespectively of
634  // T==DataType as we need to return shared_ptr<const T> to make sure the user
635  // does not modify the content of QP objects
636  std::vector<std::shared_ptr<const T>> res(it->second.size());
637  for (unsigned int q = 0; q < res.size(); q++)
638  res[q] = std::dynamic_pointer_cast<const T>(it->second[q]);
639  return res;
640 }
641 
642 //--------------------------------------------------------------------
643 // ContinuousQuadratureDataTransfer
644 //--------------------------------------------------------------------
645 
646 
647 /*
648  * Pack cell data of type @p DataType stored using @p data_storage in @p cell
649  * at each quadrature point to @p matrix_data. Here @p matrix_data is a matrix
650  * whose first index corresponds to different quadrature points on the cell
651  * whereas the second index represents different values stored at each
652  * quadrature point in the DataType class.
653  */
654 template <typename CellIteratorType, typename DataType>
655 void
656 pack_cell_data(const CellIteratorType & cell,
658  FullMatrix<double> & matrix_data)
659 {
660  static_assert(
661  std::is_base_of<TransferableQuadraturePointData, DataType>::value,
662  "User's DataType class should be derived from QPData");
663 
664  const std::vector<std::shared_ptr<const DataType>> qpd =
665  data_storage->get_data(cell);
666 
667  const unsigned int n = matrix_data.n();
668 
669  std::vector<double> single_qp_data(n);
670  Assert(qpd.size() == matrix_data.m(),
671  ExcDimensionMismatch(qpd.size(), matrix_data.m()));
672  for (unsigned int q = 0; q < qpd.size(); q++)
673  {
674  qpd[q]->pack_values(single_qp_data);
675  Assert(single_qp_data.size() == n,
676  ExcDimensionMismatch(single_qp_data.size(), n));
677 
678  for (unsigned int i = 0; i < n; i++)
679  matrix_data(q, i) = single_qp_data[i];
680  }
681 }
682 
683 
684 
685 /*
686  * the opposite of the pack function above.
687  */
688 template <typename CellIteratorType, typename DataType>
689 void
690 unpack_to_cell_data(const CellIteratorType & cell,
691  const FullMatrix<double> & values_at_qp,
693 {
694  static_assert(
695  std::is_base_of<TransferableQuadraturePointData, DataType>::value,
696  "User's DataType class should be derived from QPData");
697 
698  std::vector<std::shared_ptr<DataType>> qpd = data_storage->get_data(cell);
699 
700  const unsigned int n = values_at_qp.n();
701 
702  std::vector<double> single_qp_data(n);
703  Assert(qpd.size() == values_at_qp.m(),
704  ExcDimensionMismatch(qpd.size(), values_at_qp.m()));
705 
706  for (unsigned int q = 0; q < qpd.size(); q++)
707  {
708  for (unsigned int i = 0; i < n; i++)
709  single_qp_data[i] = values_at_qp(q, i);
710  qpd[q]->unpack_values(single_qp_data);
711  }
712 }
713 
714 
715 # ifdef DEAL_II_WITH_P4EST
716 
717 namespace parallel
718 {
719  namespace distributed
720  {
721  template <int dim, typename DataType>
724  const Quadrature<dim> & lhs_quadrature,
725  const Quadrature<dim> & rhs_quadrature)
726  : projection_fe(
727  std::unique_ptr<const FiniteElement<dim>>(projection_fe_.clone()))
728  , data_size_in_bytes(0)
729  , n_q_points(rhs_quadrature.size())
730  , project_to_fe_matrix(projection_fe->dofs_per_cell, n_q_points)
731  , project_to_qp_matrix(n_q_points, projection_fe->dofs_per_cell)
733  , data_storage(nullptr)
734  , triangulation(nullptr)
735  {
736  Assert(
737  projection_fe->n_components() == 1,
738  ExcMessage(
739  "ContinuousQuadratureDataTransfer requires scalar FiniteElement"));
740 
742  *projection_fe.get(),
743  lhs_quadrature,
744  rhs_quadrature,
745  project_to_fe_matrix);
746 
748  *projection_fe.get(), rhs_quadrature, project_to_qp_matrix);
749  }
750 
751 
752 
753  template <int dim, typename DataType>
756  {}
757 
758 
759 
760  template <int dim, typename DataType>
761  void
766  {
767  Assert(data_storage == nullptr,
768  ExcMessage("This function can be called only once"));
769  triangulation = &tr_;
770  data_storage = &data_storage_;
771  // get the number from the first active cell
772  unsigned int number_of_values = 0;
773  // if triangulation has some active cells locally owned cells on this
774  // processor we can expect data to be initialized. Do that to get the
775  // number:
777  dim>::active_cell_iterator it = triangulation->begin_active();
778  it != triangulation->end();
779  it++)
780  if (it->is_locally_owned())
781  {
782  std::vector<std::shared_ptr<DataType>> qpd =
783  data_storage->get_data(it);
784  number_of_values = qpd[0]->number_of_values();
785  break;
786  }
787  // some processors may have no data stored, thus get the maximum among all
788  // processors:
789  number_of_values = Utilities::MPI::max(number_of_values,
790  triangulation->get_communicator());
791  Assert(number_of_values > 0, ExcInternalError());
792  const unsigned int dofs_per_cell = projection_fe->dofs_per_cell;
793  matrix_dofs.reinit(dofs_per_cell, number_of_values);
794  matrix_dofs_child.reinit(dofs_per_cell, number_of_values);
795  matrix_quadrature.reinit(n_q_points, number_of_values);
796 
797  handle = triangulation->register_data_attach(
798  std::bind(
800  this,
801  std::placeholders::_1,
802  std::placeholders::_2),
803  /*returns_variable_size_data=*/false);
804  }
805 
806 
807 
808  template <int dim, typename DataType>
809  void
811  {
812  triangulation->notify_ready_to_unpack(
813  handle,
814  std::bind(
816  this,
817  std::placeholders::_1,
818  std::placeholders::_2,
819  std::placeholders::_3));
820 
821  // invalidate the pointers
822  data_storage = nullptr;
823  triangulation = nullptr;
824  }
825 
826 
827 
828  template <int dim, typename DataType>
829  std::vector<char>
832  &cell,
834  dim>::CellStatus /*status*/)
835  {
836  pack_cell_data(cell, data_storage, matrix_quadrature);
837 
838  // project to FE
839  project_to_fe_matrix.mmult(matrix_dofs, matrix_quadrature);
840 
841  // to get consistent data sizes on each cell for the fixed size transfer,
842  // we won't allow compression
843  return Utilities::pack(matrix_dofs, /*allow_compression=*/false);
844  }
845 
846 
847 
848  template <int dim, typename DataType>
849  void
852  &cell,
853  const typename parallel::distributed::Triangulation<dim>::CellStatus
854  status,
855  const boost::iterator_range<std::vector<char>::const_iterator>
856  &data_range)
857  {
858  Assert((status !=
861  (void)status;
862 
863  matrix_dofs =
864  Utilities::unpack<FullMatrix<double>>(data_range.begin(),
865  data_range.end(),
866  /*allow_compression=*/false);
867 
868  if (cell->has_children())
869  {
870  // we need to first use prolongation matrix to get dofvalues on child
871  // cells based on dofvalues stored in the parent's data_store
872  for (unsigned int child = 0; child < cell->n_children(); ++child)
873  if (cell->child(child)->is_locally_owned())
874  {
875  projection_fe
876  ->get_prolongation_matrix(child, cell->refinement_case())
877  .mmult(matrix_dofs_child, matrix_dofs);
878 
879  // now we do the usual business of evaluating FE on quadrature
880  // points:
881  project_to_qp_matrix.mmult(matrix_quadrature,
882  matrix_dofs_child);
883 
884  // finally, put back into the map:
885  unpack_to_cell_data(cell->child(child),
886  matrix_quadrature,
887  data_storage);
888  }
889  }
890  else
891  {
892  // if there are no children, evaluate FE field at
893  // rhs_quadrature points.
894  project_to_qp_matrix.mmult(matrix_quadrature, matrix_dofs);
895 
896  // finally, put back into the map:
897  unpack_to_cell_data(cell, matrix_quadrature, data_storage);
898  }
899  }
900 
901  } // namespace distributed
902 
903 } // namespace parallel
904 
905 # endif // DEAL_II_WITH_P4EST
906 
907 #endif // DOXYGEN
908 DEAL_II_NAMESPACE_CLOSE
909 
910 #endif
~CellDataStorage() override=default
static const unsigned int invalid_unsigned_int
Definition: types.h:173
void compute_interpolation_to_quadrature_points_matrix(const FiniteElement< dim, spacedim > &fe, const Quadrature< dim > &quadrature, FullMatrix< double > &I_q)
CellDataStorage()=default
virtual std::unique_ptr< FiniteElement< dim, spacedim > > clone() const =0
std::map< CellIteratorType, std::vector< std::shared_ptr< DataType > > > map
std::vector< std::shared_ptr< T > > get_data(const CellIteratorType &cell)
bool erase(const CellIteratorType &cell)
CellDataStorage< CellIteratorType, DataType > * data_storage
unsigned int size() const
static::ExceptionBase & ExcMessage(std::string arg1)
size_type n() const
#define Assert(cond, exc)
Definition: exceptions.h:1227
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)
const std::unique_ptr< const FiniteElement< dim > > projection_fe
size_type m() const
size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
Definition: utilities.h:1046
parallel::distributed::Triangulation< dim > * triangulation
static::ExceptionBase & ExcNotImplemented()
typename parallel::distributed::Triangulation< dim >::cell_iterator CellIteratorType
typename::Triangulation< dim, spacedim >::cell_iterator cell_iterator
Definition: tria.h:269
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()