deal.II version GIT relicensing-6842-g793a97d2aa 2026-10-02 14:00:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
quadrature_point_data.h
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2016 - 2025 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#ifndef dealii_quadrature_point_data_h
14#define dealii_quadrature_point_data_h
15
16#include <deal.II/base/config.h>
17
20
22
23#include <deal.II/fe/fe.h>
24#include <deal.II/fe/fe_tools.h>
25
26#include <deal.II/grid/tria.h>
28
29#include <deal.II/lac/vector.h>
30
31#include <map>
32#include <optional>
33#include <type_traits>
34#include <vector>
35
37
60template <typename CellIteratorType, typename DataType>
62{
63public:
67 CellDataStorage() = default;
68
72 ~CellDataStorage() override = default;
73
99 template <typename T = DataType>
100 void
101 initialize(const CellIteratorType &cell,
102 const unsigned int number_of_data_points_per_cell);
103
109 template <typename T = DataType>
110 void
112 const CellIteratorType &cell_start,
114 const unsigned int number_of_data_points_per_cell);
115
125 bool
126 erase(const CellIteratorType &cell);
127
131 void
133
148 template <typename T = DataType>
149 std::vector<std::shared_ptr<T>>
150 get_data(const CellIteratorType &cell);
151
166 template <typename T = DataType>
167 std::vector<std::shared_ptr<const T>>
168 get_data(const CellIteratorType &cell) const;
169
186 template <typename T = DataType>
187 std::optional<std::vector<std::shared_ptr<T>>>
188 try_get_data(const CellIteratorType &cell);
189
206 template <typename T = DataType>
207 std::optional<std::vector<std::shared_ptr<const T>>>
208 try_get_data(const CellIteratorType &cell) const;
209
210private:
214 static constexpr unsigned int dimension =
215 CellIteratorType::AccessorType::dimension;
216
220 static constexpr unsigned int space_dimension =
221 CellIteratorType::AccessorType::space_dimension;
222
231
237 std::map<CellId, std::vector<std::shared_ptr<DataType>>> map;
238
244 "Cell data is being retrieved with a type which is different than the type used to initialize it");
245
251 "The provided cell iterator does not belong to the triangulation that corresponds to the CellDataStorage object.");
252};
253
254
276{
277public:
282
287
293 virtual unsigned int
294 number_of_values() const = 0;
295
306 virtual void
307 pack_values(std::vector<double> &values) const = 0;
308
317 virtual void
318 unpack_values(const std::vector<double> &values) = 0;
319};
320
321
322#ifdef DEAL_II_WITH_P4EST
323namespace parallel
324{
325 namespace distributed
326 {
436 template <int dim, typename DataType>
438 {
439 public:
440 static_assert(
441 std::is_base_of_v<TransferableQuadraturePointData, DataType>,
442 "User's DataType class should be derived from TransferableQuadraturePointData");
443
449
461 const Quadrature<dim> &mass_quadrature,
462 const Quadrature<dim> &data_quadrature);
463
474 void
478
489 void
491
492 private:
498 std::vector<char>
501 &cell,
502 const CellStatus status);
503
509 void
512 &cell,
513 const CellStatus status,
514 const boost::iterator_range<std::vector<char>::const_iterator>
515 &data_range);
516
520 const std::unique_ptr<const FiniteElement<dim>> projection_fe;
521
527
531 const unsigned int n_q_points;
532
538
544
552
557
563
568 unsigned int handle;
569
574
580 };
581
582 } // namespace distributed
583
584} // namespace parallel
585
586#endif
587
590#ifndef DOXYGEN
591
592// ------------------- inline and template functions ----------------
593
594//--------------------------------------------------------------------
595// CellDataStorage
596//--------------------------------------------------------------------
597
598template <typename CellIteratorType, typename DataType>
599template <typename T>
600inline void
602 const CellIteratorType &cell,
603 const unsigned int n_q_points)
604{
605 static_assert(std::is_base_of_v<DataType, T>,
606 "User's T class should be derived from user's DataType class");
607 // The first time this method is called, it has to initialize the reference
608 // to the triangulation object
609 if (!tria)
610 tria = &cell->get_triangulation();
611 Assert(&cell->get_triangulation() == tria, ExcTriangulationMismatch());
612
613 const auto key = cell->id();
614 if (map.find(key) == map.end())
615 {
616 map[key] = std::vector<std::shared_ptr<DataType>>(n_q_points);
617 // we need to initialize one-by-one as the std::vector<>(q, T())
618 // will end with a single same T object stored in each element of the
619 // vector:
620 const auto it = map.find(key);
621 for (unsigned int q = 0; q < n_q_points; ++q)
622 it->second[q] = std::make_shared<T>();
623 }
624}
625
626
627
628template <typename CellIteratorType, typename DataType>
629template <typename T>
630inline void
632 const CellIteratorType &cell_start,
634 const unsigned int number)
635{
636 for (CellIteratorType it = cell_start; it != cell_end; ++it)
637 if (it->is_locally_owned())
638 initialize<T>(it, number);
639}
640
641
642
643template <typename CellIteratorType, typename DataType>
644inline bool
645CellDataStorage<CellIteratorType, DataType>::erase(const CellIteratorType &cell)
646{
647 const auto key = cell->id();
648 const auto it = map.find(key);
649 if (it == map.end())
650 return false;
651 Assert(&cell->get_triangulation() == tria, ExcTriangulationMismatch());
652 for (unsigned int i = 0; i < it->second.size(); ++i)
653 {
654 Assert(
655 it->second[i].use_count() == 1,
657 "Can not erase the cell data multiple objects reference its data."));
658 }
659
660 return (map.erase(key) == 1);
661}
662
663
664
665template <typename CellIteratorType, typename DataType>
666inline void
668{
669 // Do not call
670 // map.clear();
671 // as we want to be sure no one uses the stored objects. Loop manually:
672 auto it = map.begin();
673 while (it != map.end())
674 {
675 // loop over all objects and see if no one is using them
676 for (unsigned int i = 0; i < it->second.size(); ++i)
677 {
678 Assert(
679 it->second[i].use_count() == 1,
681 "Can not erase the cell data, multiple objects reference it."));
682 }
683 it = map.erase(it);
684 }
685}
686
687
688
689template <typename CellIteratorType, typename DataType>
690template <typename T>
691inline std::vector<std::shared_ptr<T>>
693 const CellIteratorType &cell)
694{
695 static_assert(std::is_base_of_v<DataType, T>,
696 "User's T class should be derived from user's DataType class");
697 Assert(&cell->get_triangulation() == tria, ExcTriangulationMismatch());
698
699 const auto it = map.find(cell->id());
700 Assert(it != map.end(), ExcMessage("Could not find data for the cell"));
701
702 // It would be nice to have a specialized version of this function for
703 // T==DataType. However explicit (i.e full) specialization of a member
704 // template is only allowed when the enclosing class is also explicitly (i.e
705 // fully) specialized. Thus, stick with copying of shared pointers even when
706 // the T==DataType:
707 std::vector<std::shared_ptr<T>> res(it->second.size());
708 for (unsigned int q = 0; q < res.size(); ++q)
709 {
710 res[q] = std::dynamic_pointer_cast<T>(it->second[q]);
711 Assert(res[q], ExcCellDataTypeMismatch());
712 }
713 return res;
714}
715
716
717
718template <typename CellIteratorType, typename DataType>
719template <typename T>
720inline std::vector<std::shared_ptr<const T>>
722 const CellIteratorType &cell) const
723{
724 static_assert(std::is_base_of_v<DataType, T>,
725 "User's T class should be derived from user's DataType class");
726 Assert(&cell->get_triangulation() == tria, ExcTriangulationMismatch());
727
728 const auto it = map.find(cell->id());
729 Assert(it != map.end(), ExcMessage("Could not find QP data for the cell"));
730
731 // Cast base class to the desired class. This has to be done irrespectively of
732 // T==DataType as we need to return shared_ptr<const T> to make sure the user
733 // does not modify the content of QP objects
734 std::vector<std::shared_ptr<const T>> res(it->second.size());
735 for (unsigned int q = 0; q < res.size(); ++q)
736 {
737 res[q] = std::dynamic_pointer_cast<const T>(it->second[q]);
738 Assert(res[q], ExcCellDataTypeMismatch());
739 }
740 return res;
741}
742
743template <typename CellIteratorType, typename DataType>
744template <typename T>
745inline std::optional<std::vector<std::shared_ptr<T>>>
747 const CellIteratorType &cell)
748{
749 static_assert(std::is_base_of_v<DataType, T>,
750 "User's T class should be derived from user's DataType class");
751 Assert(&cell->get_triangulation() == tria, ExcTriangulationMismatch());
752
753 const auto it = map.find(cell->id());
754 if (it != map.end())
755 {
756 // Cast base class to the desired class. This has to be done
757 // irrespectively of T==DataType as we need to return
758 // shared_ptr<const T> to make sure the user
759 // does not modify the content of QP objects
760 std::vector<std::shared_ptr<T>> result(it->second.size());
761 for (unsigned int q = 0; q < result.size(); ++q)
762 {
763 result[q] = std::dynamic_pointer_cast<T>(it->second[q]);
764 Assert(result[q], ExcCellDataTypeMismatch());
765 }
766 return {result};
767 }
768 else
769 {
770 return {};
771 }
772}
773
774template <typename CellIteratorType, typename DataType>
775template <typename T>
776inline std::optional<std::vector<std::shared_ptr<const T>>>
778 const CellIteratorType &cell) const
779{
780 static_assert(std::is_base_of_v<DataType, T>,
781 "User's T class should be derived from user's DataType class");
782 Assert(&cell->get_triangulation() == tria, ExcTriangulationMismatch());
783
784 const auto it = map.find(cell->id());
785 if (it != map.end())
786 {
787 // Cast base class to the desired class. This has to be done
788 // irrespectively of T==DataType as we need to return
789 // shared_ptr<const T> to make sure the user
790 // does not modify the content of QP objects
791 std::vector<std::shared_ptr<const T>> result(it->second.size());
792 for (unsigned int q = 0; q < result.size(); ++q)
793 {
794 result[q] = std::dynamic_pointer_cast<const T>(it->second[q]);
795 Assert(result[q], ExcCellDataTypeMismatch());
796 }
797 return {result};
798 }
799 else
800 {
801 return {};
802 }
803}
804
805//--------------------------------------------------------------------
806// ContinuousQuadratureDataTransfer
807//--------------------------------------------------------------------
808
809
810/*
811 * Pack cell data of type @p DataType stored using @p data_storage in @p cell
812 * at each quadrature point to @p matrix_data. Here @p matrix_data is a matrix
813 * whose first index corresponds to different quadrature points on the cell
814 * whereas the second index represents different values stored at each
815 * quadrature point in the DataType class.
816 */
817template <typename CellIteratorType, typename DataType>
818inline void
819pack_cell_data(const CellIteratorType &cell,
821 FullMatrix<double> &matrix_data)
822{
823 static_assert(std::is_base_of_v<TransferableQuadraturePointData, DataType>,
824 "User's DataType class should be derived from QPData");
825
826 if (const auto qpd = data_storage->try_get_data(cell))
827 {
828 const unsigned int m = qpd->size();
829 Assert(m > 0, ExcInternalError());
830 const unsigned int n = (*qpd)[0]->number_of_values();
831 matrix_data.reinit(m, n);
832
833 std::vector<double> single_qp_data(n);
834 for (unsigned int q = 0; q < m; ++q)
835 {
836 (*qpd)[q]->pack_values(single_qp_data);
837 AssertDimension(single_qp_data.size(), n);
838
839 for (unsigned int i = 0; i < n; ++i)
840 matrix_data(q, i) = single_qp_data[i];
841 }
842 }
843 else
844 {
845 matrix_data.reinit({0, 0});
846 }
847}
848
849
850
851/*
852 * the opposite of the pack function above.
853 */
854template <typename CellIteratorType, typename DataType>
855inline void
856unpack_to_cell_data(const CellIteratorType &cell,
857 const FullMatrix<double> &values_at_qp,
859{
860 static_assert(std::is_base_of_v<TransferableQuadraturePointData, DataType>,
861 "User's DataType class should be derived from QPData");
862
863 if (const auto qpd = data_storage->try_get_data(cell))
864 {
865 const unsigned int n = values_at_qp.n();
866 AssertDimension((*qpd)[0]->number_of_values(), n);
867
868 std::vector<double> single_qp_data(n);
869 AssertDimension(qpd->size(), values_at_qp.m());
870
871 for (unsigned int q = 0; q < qpd->size(); ++q)
872 {
873 for (unsigned int i = 0; i < n; ++i)
874 single_qp_data[i] = values_at_qp(q, i);
875 (*qpd)[q]->unpack_values(single_qp_data);
876 }
877 }
878}
879
880
881# ifdef DEAL_II_WITH_P4EST
882
883namespace parallel
884{
885 namespace distributed
886 {
887 template <int dim, typename DataType>
890 const Quadrature<dim> &lhs_quadrature,
891 const Quadrature<dim> &rhs_quadrature)
892 : projection_fe(
893 std::unique_ptr<const FiniteElement<dim>>(projection_fe_.clone()))
894 , data_size_in_bytes(0)
895 , n_q_points(rhs_quadrature.size())
896 , project_to_fe_matrix(projection_fe->n_dofs_per_cell(), n_q_points)
897 , project_to_qp_matrix(n_q_points, projection_fe->n_dofs_per_cell())
899 , data_storage(nullptr)
900 , triangulation(nullptr)
901 {
902 Assert(
903 projection_fe->n_components() == 1,
905 "ContinuousQuadratureDataTransfer requires scalar FiniteElement"));
906
908 *projection_fe.get(),
909 lhs_quadrature,
910 rhs_quadrature,
912
914 *projection_fe.get(), rhs_quadrature, project_to_qp_matrix);
915 }
916
917
918
919 template <int dim, typename DataType>
920 inline void
925 {
926 Assert(data_storage == nullptr,
927 ExcMessage("This function can be called only once"));
928 triangulation = &tr_;
929 data_storage = &data_storage_;
930
931 handle = triangulation->register_data_attach(
932 [this](const typename parallel::distributed::Triangulation<
933 dim>::cell_iterator &cell,
934 const CellStatus status) {
935 return this->pack_function(cell, status);
936 },
937 /*returns_variable_size_data=*/true);
938 }
939
940
941
942 template <int dim, typename DataType>
943 inline void
945 {
946 triangulation->notify_ready_to_unpack(
947 handle,
948 [this](const typename parallel::distributed::Triangulation<
949 dim>::cell_iterator &cell,
950 const CellStatus status,
951 const boost::iterator_range<std::vector<char>::const_iterator>
952 &data_range) {
953 this->unpack_function(cell, status, data_range);
954 });
955
956 // invalidate the pointers
957 data_storage = nullptr;
958 triangulation = nullptr;
959 }
960
961
962
963 template <int dim, typename DataType>
964 inline std::vector<char>
967 &cell,
968 const CellStatus /*status*/)
969 {
970 pack_cell_data(cell, data_storage, matrix_quadrature);
971
972 // project to FE
973 const unsigned int number_of_values = matrix_quadrature.n();
974 matrix_dofs.reinit(project_to_fe_matrix.m(), number_of_values);
975 if (number_of_values > 0)
976 project_to_fe_matrix.mmult(matrix_dofs, matrix_quadrature);
977
978 return Utilities::pack(matrix_dofs, /*allow_compression=*/false);
979 }
980
981
982
983 template <int dim, typename DataType>
984 inline void
987 &cell,
988 const CellStatus status,
989 const boost::iterator_range<std::vector<char>::const_iterator>
990 &data_range)
991 {
994 (void)status;
995
996 matrix_dofs =
997 Utilities::unpack<FullMatrix<double>>(data_range.begin(),
998 data_range.end(),
999 /*allow_compression=*/false);
1000 const unsigned int number_of_values = matrix_dofs.n();
1001 if (number_of_values == 0)
1002 return;
1003
1004 matrix_quadrature.reinit(n_q_points, number_of_values);
1005
1006 if (cell->has_children())
1007 {
1008 // we need to first use prolongation matrix to get dofvalues on child
1009 // cells based on dofvalues stored in the parent's data_store
1010 matrix_dofs_child.reinit(projection_fe->n_dofs_per_cell(),
1011 number_of_values);
1012 for (unsigned int child = 0; child < cell->n_children(); ++child)
1013 if (cell->child(child)->is_locally_owned())
1014 {
1015 projection_fe
1016 ->get_prolongation_matrix(child, cell->refinement_case())
1017 .mmult(matrix_dofs_child, matrix_dofs);
1018
1019 // now we do the usual business of evaluating FE on quadrature
1020 // points:
1021 project_to_qp_matrix.mmult(matrix_quadrature,
1022 matrix_dofs_child);
1023
1024 // finally, put back into the map:
1025 unpack_to_cell_data(cell->child(child),
1026 matrix_quadrature,
1027 data_storage);
1028 }
1029 }
1030 else
1031 {
1032 // if there are no children, evaluate FE field at
1033 // rhs_quadrature points.
1034 project_to_qp_matrix.mmult(matrix_quadrature, matrix_dofs);
1035
1036 // finally, put back into the map:
1037 unpack_to_cell_data(cell, matrix_quadrature, data_storage);
1038 }
1039 }
1040
1041 } // namespace distributed
1042
1043} // namespace parallel
1044
1045# endif // DEAL_II_WITH_P4EST
1046
1047#endif // DOXYGEN
1049
1050#endif
CellStatus
Definition cell_status.h:29
@ children_will_be_coarsened
std::optional< std::vector< std::shared_ptr< const T > > > try_get_data(const CellIteratorType &cell) const
CellDataStorage()=default
void initialize(const CellIteratorType &cell_start, const typename std_cxx20::type_identity< CellIteratorType >::type &cell_end, const unsigned int number_of_data_points_per_cell)
void initialize(const CellIteratorType &cell, const unsigned int number_of_data_points_per_cell)
bool erase(const CellIteratorType &cell)
static constexpr unsigned int space_dimension
std::vector< std::shared_ptr< const T > > get_data(const CellIteratorType &cell) const
ObserverPointer< const Triangulation< dimension, space_dimension >, CellDataStorage< CellIteratorType, DataType > > tria
std::optional< std::vector< std::shared_ptr< T > > > try_get_data(const CellIteratorType &cell)
~CellDataStorage() override=default
std::map< CellId, std::vector< std::shared_ptr< DataType > > > map
std::vector< std::shared_ptr< T > > get_data(const CellIteratorType &cell)
static constexpr unsigned int dimension
size_type n() const
size_type m() const
virtual ~TransferableQuadraturePointData()=default
virtual unsigned int number_of_values() const =0
virtual void unpack_values(const std::vector< double > &values)=0
virtual void pack_values(std::vector< double > &values) const =0
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)
parallel::distributed::Triangulation< dim > * triangulation
typename parallel::distributed::Triangulation< dim >::cell_iterator CellIteratorType
std::vector< char > pack_function(const typename parallel::distributed::Triangulation< dim >::cell_iterator &cell, const CellStatus status)
void prepare_for_coarsening_and_refinement(parallel::distributed::Triangulation< dim > &tria, CellDataStorage< CellIteratorType, DataType > &data_storage)
void unpack_function(const typename parallel::distributed::Triangulation< dim >::cell_iterator &cell, const CellStatus status, const boost::iterator_range< std::vector< char >::const_iterator > &data_range)
CellDataStorage< CellIteratorType, DataType > * data_storage
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
static ::ExceptionBase & ExcCellDataTypeMismatch()
#define AssertDimension(dim1, dim2)
#define DeclExceptionMsg(Exception, defaulttext)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcTriangulationMismatch()
static ::ExceptionBase & ExcMessage(std::string arg1)
typename ::Triangulation< dim, spacedim >::cell_iterator cell_iterator
Definition tria.h:322
std::size_t size
Definition mpi.cc:733
void compute_interpolation_to_quadrature_points_matrix(const FiniteElement< dim, spacedim > &fe, const Quadrature< dim > &quadrature, FullMatrix< double > &I_q)
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)
*  *  *  *  std::vector< Number > ThermoPlasticMaterial< dim, ViscoplasticYieldLaw, Number >::get_state_parameters   const
std::size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
Definition utilities.h:1352
constexpr unsigned int invalid_unsigned_int
Definition types.h:228
STL namespace.