deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20: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
dof_accessor.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) 1998 - 2026 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_dof_accessor_h
14#define dealii_dof_accessor_h
15
16
17#include <deal.II/base/config.h>
18
19#include <deal.II/base/types.h>
20
24
26
30
31#include <boost/container/small_vector.hpp>
32
33#include <set>
34#include <type_traits>
35#include <vector>
36
37
39
40// Forward declarations
41#ifndef DOXYGEN
42template <typename number>
43class FullMatrix;
44template <typename number>
45class Vector;
46template <typename number>
48
49template <typename Accessor>
50class TriaRawIterator;
51
52template <int, int>
53class FiniteElement;
54
55namespace internal
56{
57 namespace DoFCellAccessorImplementation
58 {
59 struct Implementation;
60 }
61
62 namespace DoFHandlerImplementation
63 {
64 struct Implementation;
65 namespace Policy
66 {
67 struct Implementation;
68 }
69 } // namespace DoFHandlerImplementation
70
71 namespace hp
72 {
73 namespace DoFHandlerImplementation
74 {
75 struct Implementation;
76 }
77 } // namespace hp
78} // namespace internal
79#endif
80
81
82namespace internal
83{
84 namespace DoFAccessorImplementation
85 {
102 template <int structdim, int dim, int spacedim>
111
112
118 template <int dim, int spacedim>
119 struct Inheritance<dim, dim, spacedim>
120 {
126 };
127
128 struct Implementation;
129 } // namespace DoFAccessorImplementation
130} // namespace internal
131
132
133/* -------------------------------------------------------------------------- */
134
135
136
209template <int structdim, int dim, int spacedim, bool level_dof_access>
210class DoFAccessor : public ::internal::DoFAccessorImplementation::
211 Inheritance<structdim, dim, spacedim>::BaseClass
212{
213public:
218 static constexpr unsigned int dimension = dim;
219
224 static constexpr unsigned int space_dimension = spacedim;
225
230 using BaseClass = typename ::internal::DoFAccessorImplementation::
231 Inheritance<structdim, dimension, space_dimension>::BaseClass;
232
237
249
266 const int level,
267 const int index,
269
274 default;
275
279 DoFAccessor( // NOLINT
281 default; // NOLINT
282
286 ~DoFAccessor() = default;
287
300 template <int structdim2, int dim2, int spacedim2>
302
307 template <int structdim2, int dim2, int spacedim2, bool level_dof_access2>
310
314 template <bool level_dof_access2>
316
328 delete;
329
334 operator=( // NOLINT
336 default; // NOLINT
337
347
351 template <bool level_dof_access2>
352 void
354
359 void
361
366 static bool
368
380 child(const unsigned int c) const;
381
387 typename ::internal::DoFHandlerImplementation::
388 Iterators<dim, spacedim, level_dof_access>::line_iterator
389 line(const unsigned int i) const;
390
396 typename ::internal::DoFHandlerImplementation::
397 Iterators<dim, spacedim, level_dof_access>::quad_iterator
398 quad(const unsigned int i) const;
399
445 void
447 std::vector<types::global_dof_index> &dof_indices,
448 const types::fe_index fe_index = numbers::invalid_fe_index) const;
449
456 void
458 const int level,
459 std::vector<types::global_dof_index> &dof_indices,
460 const types::fe_index fe_index = numbers::invalid_fe_index) const;
461
465 void
467 const int level,
468 const std::vector<types::global_dof_index> &dof_indices,
470
494 const unsigned int vertex,
495 const unsigned int i,
496 const types::fe_index fe_index = numbers::invalid_fe_index) const;
497
505 const int level,
506 const unsigned int vertex,
507 const unsigned int i,
508 const types::fe_index fe_index = numbers::invalid_fe_index) const;
509
538 dof_index(const unsigned int i,
539 const types::fe_index fe_index = numbers::invalid_fe_index) const;
540
545 mg_dof_index(const int level, const unsigned int i) const;
546
568 unsigned int
570
579 nth_active_fe_index(const unsigned int n) const;
580
587 std::set<types::fe_index>
589
599 bool
600 fe_index_is_active(const types::fe_index fe_index) const;
601
608 get_fe(const types::fe_index fe_index) const;
609
620 "This accessor object has not been "
621 "associated with any DoFHandler object.");
654
655protected:
660
661public:
675 template <int structdim2, int dim2, int spacedim2, bool level_dof_access2>
676 bool
679
683 template <int structdim2, int dim2, int spacedim2, bool level_dof_access2>
684 bool
687
688protected:
692 void
694
713 void
715 const unsigned int i,
716 const types::global_dof_index index,
717 const types::fe_index fe_index = numbers::invalid_fe_index) const;
718
719 void
721 const unsigned int i,
722 const types::global_dof_index index) const;
723
724 void
726 const int level,
727 const unsigned int vertex,
728 const unsigned int i,
729 const types::global_dof_index index,
730 const types::fe_index fe_index = numbers::invalid_fe_index) const;
731
732 // Iterator classes need to be friends because they need to access
733 // operator== and operator!=.
734 template <typename>
735 friend class TriaRawIterator;
736 template <int, int, int, bool>
737 friend class DoFAccessor;
738
739private:
740 // Make the DoFHandler class a friend so that it can call the set_xxx()
741 // functions.
742 friend class DoFHandler<dim, spacedim>;
743
744 friend struct ::internal::DoFHandlerImplementation::Policy::
745 Implementation;
746 friend struct ::internal::DoFHandlerImplementation::Implementation;
747 friend struct ::internal::hp::DoFHandlerImplementation::Implementation;
748 friend struct ::internal::DoFCellAccessorImplementation::Implementation;
749 friend struct ::internal::DoFAccessorImplementation::Implementation;
750};
751
752
753
761template <int spacedim, bool level_dof_access>
762class DoFAccessor<0, 1, spacedim, level_dof_access>
763 : public TriaAccessor<0, 1, spacedim>
764{
765public:
770 static constexpr unsigned int dimension = 1;
771
776 static constexpr unsigned int space_dimension = spacedim;
777
783
788
799 DoFAccessor();
800
818 const Triangulation<1, spacedim> *tria,
819 const typename TriaAccessor<0, 1, spacedim>::VertexKind vertex_kind,
820 const unsigned int vertex_index,
822
830 const int = 0,
831 const int = 0,
833
846 template <int structdim2, int dim2, int spacedim2>
848
853 template <int structdim2, int dim2, int spacedim2, bool level_dof_access2>
856
861
865 // NOLINTNEXTLINE OSX does not compile with noexcept
867
871 ~DoFAccessor() = default;
872
884
890 default;
891
899 const DoFHandler<1, spacedim> &
900 get_dof_handler() const;
901
905 template <bool level_dof_access2>
906 void
907 copy_from(const DoFAccessor<0, 1, spacedim, level_dof_access2> &a);
908
913 void
914 copy_from(const TriaAccessorBase<0, 1, spacedim> &da);
915
928 TriaIterator<DoFAccessor<0, 1, spacedim, level_dof_access>>
929 child(const unsigned int c) const;
930
937 typename ::internal::DoFHandlerImplementation::
938 Iterators<1, spacedim, level_dof_access>::line_iterator
939 line(const unsigned int i) const;
940
947 typename ::internal::DoFHandlerImplementation::
948 Iterators<1, spacedim, level_dof_access>::quad_iterator
949 quad(const unsigned int i) const;
950
994 void
996 std::vector<types::global_dof_index> &dof_indices,
997 const types::fe_index fe_index = numbers::invalid_fe_index) const;
998
1005 void
1007 const int level,
1008 std::vector<types::global_dof_index> &dof_indices,
1009 const types::fe_index fe_index = numbers::invalid_fe_index) const;
1010
1029 types::global_dof_index
1031 const unsigned int vertex,
1032 const unsigned int i,
1033 const types::fe_index fe_index = numbers::invalid_fe_index) const;
1034
1052 types::global_dof_index
1053 dof_index(const unsigned int i,
1054 const types::fe_index fe_index = numbers::invalid_fe_index) const;
1055
1074 unsigned int
1075 n_active_fe_indices() const;
1076
1084 types::fe_index
1085 nth_active_fe_index(const unsigned int n) const;
1086
1095 bool
1096 fe_index_is_active(const types::fe_index fe_index) const;
1097
1103 const FiniteElement<1, spacedim> &
1104 get_fe(const types::fe_index fe_index) const;
1105
1116 "This accessor object has not been "
1117 "associated with any DoFHandler object.");
1150
1151protected:
1156
1160 template <int structdim2, int dim2, int spacedim2, bool level_dof_access2>
1161 bool
1162 operator==(
1163 const DoFAccessor<structdim2, dim2, spacedim2, level_dof_access2> &) const;
1164
1168 template <int structdim2, int dim2, int spacedim2, bool level_dof_access2>
1169 bool
1170 operator!=(
1171 const DoFAccessor<structdim2, dim2, spacedim2, level_dof_access2> &) const;
1172
1176 void
1177 set_dof_handler(DoFHandler<1, spacedim> *dh);
1178
1197 void
1199 const unsigned int i,
1200 const types::global_dof_index index,
1201 const types::fe_index fe_index = numbers::invalid_fe_index) const;
1202
1203 // Iterator classes need to be friends because they need to access
1204 // operator== and operator!=.
1205 template <typename>
1206 friend class TriaRawIterator;
1207
1208
1209 // Make the DoFHandler class a friend so that it can call the set_xxx()
1210 // functions.
1211 friend class DoFHandler<1, spacedim>;
1212
1213 friend struct ::internal::DoFHandlerImplementation::Policy::
1215 friend struct ::internal::DoFHandlerImplementation::Implementation;
1216 friend struct ::internal::hp::DoFHandlerImplementation::Implementation;
1217 friend struct ::internal::DoFCellAccessorImplementation::Implementation;
1218};
1219
1220
1221
1222/* -------------------------------------------------------------------------- */
1223
1224
1245template <int structdim, int dim, int spacedim = dim>
1246class DoFInvalidAccessor : public InvalidAccessor<structdim, dim, spacedim>
1247{
1248public:
1254
1262 DoFInvalidAccessor(const void *parent = nullptr,
1263 const int level = -1,
1264 const int index = -1,
1265 const AccessorData *local_data = nullptr);
1266
1275
1280 template <typename OtherAccessor>
1281 DoFInvalidAccessor(const OtherAccessor &);
1282
1289 dof_index(const unsigned int i,
1290 const types::fe_index fe_index =
1292
1298 void
1300 const unsigned int i,
1301 const types::global_dof_index index,
1302 const types::fe_index fe_index = numbers::invalid_fe_index) const;
1303};
1304
1305
1306
1307/* -------------------------------------------------------------------------- */
1308
1309
1321template <int dimension_, int space_dimension_, bool level_dof_access>
1322class DoFCellAccessor : public DoFAccessor<dimension_,
1323 dimension_,
1324 space_dimension_,
1325 level_dof_access>
1326{
1327public:
1331 static const unsigned int dim = dimension_;
1332
1336 static const unsigned int spacedim = space_dimension_;
1337
1338
1343
1350
1355
1361 dimension_,
1362 space_dimension_,
1363 level_dof_access>>;
1364
1376 const int level,
1377 const int index,
1378 const AccessorData *local_data);
1379
1392 template <int structdim2, int dim2, int spacedim2>
1394
1399 template <int structdim2, int dim2, int spacedim2, bool level_dof_access2>
1400 explicit DoFCellAccessor(
1402
1408 default;
1409
1415 &&) = default; // NOLINT
1416
1420 ~DoFCellAccessor() = default;
1421
1434 delete;
1435
1440 operator=( // NOLINT
1442 &&) = default; // NOLINT
1443
1458 parent() const;
1459
1473 neighbor(const unsigned int i) const;
1474
1481 periodic_neighbor(const unsigned int i) const;
1482
1489 neighbor_or_periodic_neighbor(const unsigned int i) const;
1490
1497 child(const unsigned int i) const;
1498
1502 boost::container::small_vector<
1506 child_iterators() const;
1507
1515 face(const unsigned int i) const;
1516
1520 boost::container::small_vector<face_iterator,
1522 face_iterators() const;
1523
1531 neighbor_child_on_subface(const unsigned int face_no,
1532 const unsigned int subface_no) const;
1533
1541 periodic_neighbor_child_on_subface(const unsigned int face_no,
1542 const unsigned int subface_no) const;
1543
1572 template <class InputVector, typename number>
1573 void
1574 get_dof_values(const InputVector &values, Vector<number> &local_values) const;
1575
1593 template <typename Number, typename ForwardIterator>
1594 void
1595 get_dof_values(const ReadVector<Number> &values,
1596 ForwardIterator local_values_begin,
1597 ForwardIterator local_values_end) const;
1598
1619 template <class InputVector, typename ForwardIterator>
1620 void
1621 get_dof_values(
1623 const InputVector &values,
1624 ForwardIterator local_values_begin,
1625 ForwardIterator local_values_end) const;
1626
1651 template <class OutputVector, typename number>
1652 void
1653 set_dof_values(const Vector<number> &local_values,
1654 OutputVector &values) const;
1655
1687 template <typename Number>
1688 void
1689 get_interpolated_dof_values(
1690 const ReadVector<Number> &values,
1691 ArrayView<Number> interpolated_values,
1692 const types::fe_index fe_index = numbers::invalid_fe_index) const;
1693
1698 template <typename Number>
1699 void
1700 get_interpolated_dof_values(
1701 const ReadVector<Number> &values,
1702 Vector<Number> &interpolated_values,
1703 const types::fe_index fe_index = numbers::invalid_fe_index) const;
1704
1766 template <class OutputVector, typename number>
1767 void
1768 set_dof_values_by_interpolation(
1769 const Vector<number> &local_values,
1770 OutputVector &values,
1772 const bool perform_check = false) const;
1773
1783 template <class OutputVector, typename number>
1784 void
1785 distribute_local_to_global_by_interpolation(
1786 const Vector<number> &local_values,
1787 OutputVector &values,
1788 const types::fe_index fe_index = numbers::invalid_fe_index) const;
1789
1804 template <typename number, typename OutputVector>
1805 void
1806 distribute_local_to_global(const Vector<number> &local_source,
1807 OutputVector &global_destination) const;
1808
1823 template <typename ForwardIterator, typename OutputVector>
1824 void
1825 distribute_local_to_global(ForwardIterator local_source_begin,
1826 ForwardIterator local_source_end,
1827 OutputVector &global_destination) const;
1828
1842 template <typename ForwardIterator, typename OutputVector>
1843 void
1844 distribute_local_to_global(
1846 ForwardIterator local_source_begin,
1847 ForwardIterator local_source_end,
1848 OutputVector &global_destination) const;
1849
1856 template <typename number, typename OutputMatrix>
1857 void
1858 distribute_local_to_global(const FullMatrix<number> &local_source,
1859 OutputMatrix &global_destination) const;
1860
1865 template <typename number, typename OutputMatrix, typename OutputVector>
1866 void
1867 distribute_local_to_global(const FullMatrix<number> &local_matrix,
1868 const Vector<number> &local_vector,
1869 OutputMatrix &global_matrix,
1870 OutputVector &global_vector) const;
1871
1896 void
1897 get_active_or_mg_dof_indices(
1898 std::vector<types::global_dof_index> &dof_indices) const;
1899
1931 void
1932 get_dof_indices(std::vector<types::global_dof_index> &dof_indices) const;
1933
1938 void
1939 get_mg_dof_indices(std::vector<types::global_dof_index> &dof_indices) const;
1940
1966 get_fe() const;
1967
1994 active_fe_index() const;
1995
2022 void
2023 set_active_fe_index(const types::fe_index i) const;
2032 void
2033 set_dof_indices(const std::vector<types::global_dof_index> &dof_indices);
2034
2038 void
2039 set_mg_dof_indices(const std::vector<types::global_dof_index> &dof_indices);
2040
2067 get_future_fe() const;
2068
2088 future_fe_index() const;
2089
2098 void
2099 set_future_fe_index(const types::fe_index i) const;
2100
2107 bool
2108 future_fe_index_set() const;
2109
2118 void
2119 clear_future_fe_index() const;
2124private:
2125 friend struct ::internal::DoFCellAccessorImplementation::Implementation;
2126};
2127
2128
2129template <int structdim, int dim, int spacedim, bool level_dof_access>
2130inline bool
2135
2136
2137
2138template <int structdim, int dim, int spacedim>
2139template <typename OtherAccessor>
2141 const OtherAccessor &)
2142{
2143 Assert(false,
2144 ExcMessage("You are attempting an illegal conversion between "
2145 "iterator/accessor types. The constructor you call "
2146 "only exists to make certain template constructs "
2147 "easier to write as dimension independent code but "
2148 "the conversion is not valid in the current context."));
2149}
2150
2151
2152
2153/*------------------------- Functions: DoFAccessor ---------------------------*/
2154
2155
2156template <int structdim, int dim, int spacedim, bool level_dof_access>
2161
2162
2163
2164template <int structdim, int dim, int spacedim, bool level_dof_access>
2166 const Triangulation<dim, spacedim> *tria,
2167 const int level,
2168 const int index,
2170 : ::internal::DoFAccessorImplementation::
2171 Inheritance<structdim, dim, spacedim>::BaseClass(tria, level, index)
2172 , dof_handler(const_cast<DoFHandler<dim, spacedim> *>(dof_handler))
2173{
2174 Assert(
2175 tria == nullptr || &dof_handler->get_triangulation() == tria,
2176 ExcMessage(
2177 "You can't create a DoF accessor in which the DoFHandler object "
2178 "uses a different triangulation than the one you pass as argument."));
2179}
2180
2181
2182
2183template <int structdim, int dim, int spacedim, bool level_dof_access>
2184template <int structdim2, int dim2, int spacedim2>
2190
2191
2192
2193template <int structdim, int dim, int spacedim, bool level_dof_access>
2194template <int structdim2, int dim2, int spacedim2, bool level_dof_access2>
2197 : BaseClass(other)
2198 , dof_handler(nullptr)
2199{
2200 Assert(false,
2201 ExcMessage(
2202 "You are trying to assign iterators that are incompatible. "
2203 "The reason for incompatibility is that they refer to objects of "
2204 "different dimensionality (e.g., assigning a line iterator "
2205 "to a quad iterator)."));
2206}
2207
2208
2209
2210template <int structdim, int dim, int spacedim, bool level_dof_access>
2211template <bool level_dof_access2>
2214 : BaseClass(other)
2215 , dof_handler(const_cast<DoFHandler<dim, spacedim> *>(other.dof_handler))
2216{}
2217
2218
2219
2220template <int structdim, int dim, int spacedim, bool level_dof_access>
2221inline void
2224{
2225 Assert(dh != nullptr, ExcInvalidObject());
2226 this->dof_handler = dh;
2227}
2228
2229
2230
2231template <int structdim, int dim, int spacedim, bool level_dof_access>
2232inline const DoFHandler<dim, spacedim> &
2234{
2235 Assert(this->dof_handler != nullptr, ExcInvalidObject());
2236 return *this->dof_handler;
2237}
2238
2239
2240
2241template <int structdim, int dim, int spacedim, bool level_dof_access>
2242inline void
2245{
2246 Assert(this->dof_handler != nullptr, ExcInvalidObject());
2247 BaseClass::copy_from(da);
2248}
2249
2250
2251
2252template <int structdim, int dim, int spacedim, bool level_dof_access>
2253template <bool level_dof_access2>
2254inline void
2261
2262
2263
2264template <int structdim, int dim, int spacedim, bool level_dof_access>
2265template <int structdim2, int dim2, int spacedim2, bool level_dof_access2>
2266inline bool
2269{
2270 Assert(structdim == structdim2, ExcCantCompareIterators());
2271 Assert(this->dof_handler == a.dof_handler, ExcCantCompareIterators());
2272 return (BaseClass::operator==(a));
2273}
2274
2275
2276
2277template <int structdim, int dim, int spacedim, bool level_dof_access>
2278template <int structdim2, int dim2, int spacedim2, bool level_dof_access2>
2279inline bool
2282{
2283 Assert(structdim == structdim2, ExcCantCompareIterators());
2284 Assert(this->dof_handler == a.dof_handler, ExcCantCompareIterators());
2285 return (BaseClass::operator!=(a));
2286}
2287
2288
2289
2290template <int structdim, int dim, int spacedim, bool level_dof_access>
2293 const unsigned int i) const
2294{
2295 Assert(static_cast<unsigned int>(this->level()) <
2296 this->dof_handler->object_dof_indices.size(),
2297 ExcMessage("DoFHandler not initialized"));
2298
2301
2303 *t, this->dof_handler);
2304 return q;
2305}
2306
2307
2308namespace internal
2309{
2310 namespace DoFAccessorImplementation
2311 {
2316 template <int structdim, int dim, int spacedim, bool level_dof_access>
2320 const types::fe_index fe_index)
2321 {
2322 if (cell.get_dof_handler().has_hp_capabilities() == false)
2323 {
2324 // No hp enabled, and the argument is at its default value -> we
2325 // can translate to the default active fe index
2326 Assert(
2327 (fe_index == numbers::invalid_fe_index) ||
2329 ExcMessage(
2330 "It is not possible to specify a FE index if no hp support is used!"));
2331
2333 }
2334 else
2335 {
2336 // Otherwise: If anything other than the default is provided by
2337 // the caller, then we should take just that. As an exception, if
2338 // we are on a cell (rather than a face/edge/vertex), then we know
2339 // that there is only one active fe index on this cell and we can
2340 // use that:
2341 if ((dim == structdim) && (fe_index == numbers::invalid_fe_index))
2342 {
2344
2345 return cell.nth_active_fe_index(0);
2346 }
2347
2348 Assert((fe_index != numbers::invalid_fe_index),
2349 ExcMessage(
2350 "You need to specify a FE index if hp support is used!"));
2351
2352 return fe_index;
2353 }
2354 }
2355
2361 {
2371 boost::container::small_vector<::types::global_dof_index, 100>;
2372
2383 template <int dim,
2384 int spacedim,
2385 int structdim,
2386 typename GlobalIndexType,
2387 typename DoFPProcessor>
2388 static void
2390 const unsigned int obj_level,
2391 const unsigned int obj_index,
2392 const types::fe_index fe_index,
2393 const unsigned int local_index,
2394 const std::integral_constant<int, structdim> &,
2395 GlobalIndexType &global_index,
2396 const DoFPProcessor &process)
2397 {
2398 Assert(structdim == dim || obj_level == 0, ExcNotImplemented());
2399
2400 // 1) no hp used -> fe_index == 0
2401 if (dof_handler.hp_capability_enabled == false)
2402 {
2403 AssertDimension(fe_index,
2405
2406 process(
2407 dof_handler.object_dof_indices
2408 [obj_level][structdim]
2409 [dof_handler.object_dof_ptr[obj_level][structdim][obj_index] +
2410 local_index],
2411 global_index);
2412
2413 return;
2414 }
2415
2416 // 2) cell and hp is used -> there is only one fe_index
2417 if (structdim == dim)
2418 {
2419 process(
2420 dof_handler.object_dof_indices
2421 [obj_level][structdim]
2422 [dof_handler.object_dof_ptr[obj_level][structdim][obj_index] +
2423 local_index],
2424 global_index);
2425 return;
2426 }
2427
2428 // 3) general entity and hp is used
2429 AssertIndexRange(obj_level, dof_handler.object_dof_indices.size());
2430 AssertIndexRange(structdim,
2431 dof_handler.object_dof_indices[obj_level].size());
2432
2434
2435 AssertIndexRange(structdim, dof_handler.hp_object_fe_ptr.size());
2436 AssertIndexRange(obj_index,
2437 dof_handler.hp_object_fe_ptr[structdim].size());
2438
2439 const auto ptr =
2440 std::find(dof_handler.hp_object_fe_indices[structdim].begin() +
2441 dof_handler.hp_object_fe_ptr[structdim][obj_index],
2442 dof_handler.hp_object_fe_indices[structdim].begin() +
2443 dof_handler.hp_object_fe_ptr[structdim][obj_index + 1],
2444 fe_index);
2445
2446 Assert(ptr != dof_handler.hp_object_fe_indices[structdim].begin() +
2447 dof_handler.hp_object_fe_ptr[structdim][obj_index + 1],
2448 ExcMessage(
2449 "You are requesting an active FE index that is not assigned "
2450 "to any of the cells connected to this entity."));
2451
2452 const types::fe_index fe_index_ =
2453 std::distance(dof_handler.hp_object_fe_indices[structdim].begin() +
2454 dof_handler.hp_object_fe_ptr[structdim][obj_index],
2455 ptr);
2456
2458 dof_handler.hp_capability_enabled ?
2459 (dof_handler.hp_object_fe_ptr[structdim][obj_index] + fe_index_) :
2460 obj_index,
2461 dof_handler.object_dof_ptr[obj_level][structdim].size());
2462
2464 dof_handler.object_dof_ptr
2465 [obj_level][structdim]
2466 [dof_handler.hp_capability_enabled ?
2467 (dof_handler.hp_object_fe_ptr[structdim][obj_index] +
2468 fe_index_) :
2469 obj_index] +
2470 local_index,
2471 dof_handler.object_dof_indices[obj_level][structdim].size());
2472
2473 process(dof_handler.object_dof_indices
2474 [obj_level][structdim]
2475 [dof_handler.object_dof_ptr
2476 [obj_level][structdim]
2477 [dof_handler.hp_capability_enabled ?
2478 (dof_handler.hp_object_fe_ptr[structdim][obj_index] +
2479 fe_index_) :
2480 obj_index] +
2481 local_index],
2482 global_index);
2483 }
2484
2494 template <int dim, int spacedim, int structdim>
2495 static std::pair<unsigned int, unsigned int>
2497 const unsigned int obj_level,
2498 const unsigned int obj_index,
2499 const types::fe_index fe_index,
2500 const std::integral_constant<int, structdim> &)
2501 {
2502 Assert(structdim == dim || obj_level == 0, ExcNotImplemented());
2503
2504 // determine range of dofs in global data structure
2505 // 1) cell
2506 if (structdim == dim)
2507 {
2508 const unsigned int ptr_0 =
2509 dof_handler.object_dof_ptr[obj_level][structdim][obj_index];
2510 const unsigned int length =
2511 dof_handler.get_fe(fe_index).template n_dofs_per_object<dim>(0);
2512
2513 return {ptr_0, length};
2514 }
2515
2516 // 2) hp is not used -> fe_index == 0
2517 if (dof_handler.hp_capability_enabled == false)
2518 {
2519 AssertDimension(fe_index,
2521
2522 const unsigned int ptr_0 =
2523 dof_handler.object_dof_ptr[obj_level][structdim][obj_index];
2524 const unsigned int length =
2525 dof_handler.object_dof_ptr[obj_level][structdim][obj_index + 1] -
2526 ptr_0;
2527
2528 return {ptr_0, length};
2529 }
2530
2531 // 3) hp is used
2532 AssertIndexRange(obj_level, dof_handler.object_dof_indices.size());
2533 AssertIndexRange(structdim,
2534 dof_handler.object_dof_indices[obj_level].size());
2535
2536 AssertIndexRange(structdim, dof_handler.hp_object_fe_ptr.size());
2537 AssertIndexRange(obj_index,
2538 dof_handler.hp_object_fe_ptr[structdim].size());
2539
2540 const auto fe_index_local_ptr =
2541 std::find(dof_handler.hp_object_fe_indices[structdim].begin() +
2542 dof_handler.hp_object_fe_ptr[structdim][obj_index],
2543 dof_handler.hp_object_fe_indices[structdim].begin() +
2544 dof_handler.hp_object_fe_ptr[structdim][obj_index + 1],
2545 fe_index);
2546
2547 Assert(fe_index_local_ptr !=
2548 dof_handler.hp_object_fe_indices[structdim].begin() +
2549 dof_handler.hp_object_fe_ptr[structdim][obj_index + 1],
2550 ExcMessage(
2551 "You tried to call a function accessing DoF indices, but "
2552 "they appear not be available (yet) or inconsistent. "
2553 "Did you call distribute_dofs() first? Alternatively, if "
2554 "you are using different elements on different cells (i.e., "
2555 "you are using the hp capabilities of deal.II), did you "
2556 "change the active_fe_index of a cell since you last "
2557 "called distribute_dofs()?"));
2558
2559 const types::fe_index fe_index_local =
2560 std::distance(dof_handler.hp_object_fe_indices[structdim].begin() +
2561 dof_handler.hp_object_fe_ptr[structdim][obj_index],
2562 fe_index_local_ptr);
2563
2565 dof_handler.hp_object_fe_ptr[structdim][obj_index] + fe_index_local,
2566 dof_handler.object_dof_ptr[obj_level][structdim].size());
2567
2568 const unsigned int ptr_0 =
2569 dof_handler
2570 .object_dof_ptr[obj_level][structdim]
2571 [dof_handler.hp_object_fe_ptr[structdim][obj_index] +
2572 fe_index_local];
2573 const unsigned int ptr_1 =
2574 dof_handler
2575 .object_dof_ptr[obj_level][structdim]
2576 [dof_handler.hp_object_fe_ptr[structdim][obj_index] +
2577 fe_index_local + 1];
2578
2579 return {ptr_0, ptr_1 - ptr_0};
2580 }
2581
2582 template <int dim, int spacedim, int structdim, bool level_dof_access>
2583 static std::pair<unsigned int, unsigned int>
2585 const ::DoFAccessor<structdim, dim, spacedim, level_dof_access>
2586 accessor,
2587 const types::fe_index fe_index)
2588 {
2589 return process_object_range(accessor.get_dof_handler(),
2590 accessor.level(),
2591 accessor.index(),
2592 fe_index,
2593 std::integral_constant<int, structdim>());
2594 }
2595
2596 template <int dim, int spacedim, int structdim>
2597 static std::pair<unsigned int, unsigned int>
2599 const unsigned int)
2600 {
2602
2603 return {0, 0};
2604 }
2605
2606
2607
2616 template <int dim,
2617 int spacedim,
2618 int structdim,
2619 typename DoFProcessor,
2620 typename DoFMapping>
2621 static DEAL_II_ALWAYS_INLINE void
2623 const unsigned int obj_level,
2624 const unsigned int obj_index,
2625 const types::fe_index fe_index,
2626 const DoFMapping &mapping,
2627 const std::integral_constant<int, structdim> &dd,
2628 types::global_dof_index *&dof_indices_ptr,
2629 const DoFProcessor &process)
2630 {
2631 Assert(structdim == dim || obj_level == 0, ExcNotImplemented());
2632
2633 // determine range of dofs in global data structure
2634 const auto range =
2635 process_object_range(dof_handler, obj_level, obj_index, fe_index, dd);
2636 if (range.second == 0)
2637 return;
2638
2639 std::vector<types::global_dof_index> &object_dof_indices =
2640 dof_handler
2641 .object_dof_indices[structdim < dim ? 0 : obj_level][structdim];
2642 AssertIndexRange(range.first, object_dof_indices.size());
2644 object_dof_indices.data() + range.first;
2645
2646 // process dofs
2647 for (unsigned int i = 0; i < range.second; ++i)
2648 {
2649 process(
2650 stored_indices[(structdim == 0 || structdim == dim) ? i :
2651 mapping(i)],
2652 dof_indices_ptr);
2653 if (dof_indices_ptr != nullptr)
2654 ++dof_indices_ptr;
2655 }
2656 }
2657
2658
2659
2670 template <int dim, int spacedim, int structdim>
2671 static void
2673 const unsigned int obj_level,
2674 const unsigned int obj_index,
2675 const types::fe_index fe_index,
2676 const unsigned int local_index,
2677 const std::integral_constant<int, structdim> &dd,
2678 const types::global_dof_index global_index)
2679 {
2680 process_dof_index(dof_handler,
2681 obj_level,
2682 obj_index,
2683 fe_index,
2684 local_index,
2685 dd,
2686 global_index,
2687 [](auto &ptr, const auto &value) { ptr = value; });
2688 }
2689
2690
2701 template <int dim, int spacedim, int structdim>
2704 const unsigned int obj_level,
2705 const unsigned int obj_index,
2706 const types::fe_index fe_index,
2707 const unsigned int local_index,
2708 const std::integral_constant<int, structdim> &dd)
2709 {
2710 types::global_dof_index global_index;
2711 process_dof_index(dof_handler,
2712 obj_level,
2713 obj_index,
2714 fe_index,
2715 local_index,
2716 dd,
2717 global_index,
2718 [](const auto &ptr, auto &value) { value = ptr; });
2719 return global_index;
2720 }
2721
2722
2723 template <int dim, int spacedim>
2726 const int level,
2727 const unsigned int vertex_index,
2728 const unsigned int i)
2729 {
2730 Assert(dof_handler.hp_capability_enabled == false,
2731 ExcMessage(
2732 "DoFHandler in hp-mode does not implement multilevel DoFs."));
2733
2734 return dof_handler.mg_vertex_dofs[vertex_index].access_index(
2735 level, i, dof_handler.get_fe().n_dofs_per_vertex());
2736 }
2737
2738
2739
2749 template <int dim, int spacedim, int structdim>
2750 static unsigned int
2752 const unsigned int obj_level,
2753 const unsigned int obj_index,
2754 const std::integral_constant<int, structdim> &)
2755 {
2756 (void)obj_level;
2757
2758 Assert(structdim == dim || obj_level == 0, ExcNotImplemented());
2759
2760 // 1) no hp used -> fe_index == 0
2761 if (dof_handler.hp_capability_enabled == false)
2762 return 1;
2763
2764 // 2) cell and hp is used -> there is only one fe_index
2765 if (structdim == dim)
2766 return 1;
2767
2768 // 3) general entity and hp is used
2769 AssertIndexRange(structdim, dof_handler.hp_object_fe_ptr.size());
2770 AssertIndexRange(obj_index + 1,
2771 dof_handler.hp_object_fe_ptr[structdim].size());
2772
2773 return dof_handler.hp_object_fe_ptr[structdim][obj_index + 1] -
2774 dof_handler.hp_object_fe_ptr[structdim][obj_index];
2775 }
2776
2777
2778
2788 template <int dim, int spacedim, int structdim>
2789 static types::fe_index
2791 const unsigned int obj_level,
2792 const unsigned int obj_index,
2793 const unsigned int local_index,
2794 const std::integral_constant<int, structdim> &)
2795 {
2796 Assert(structdim == dim || obj_level == 0, ExcNotImplemented());
2797
2798 // for cells only one active FE index available
2799 Assert(((structdim == dim) &&
2801 false,
2803
2804 // 1) no hp used -> fe_index == 0
2805 if (dof_handler.hp_capability_enabled == false)
2807
2808 // 2) cell and hp is used -> there is only one fe_index
2809 if (structdim == dim)
2810 return dof_handler.hp_cell_active_fe_indices[obj_level][obj_index];
2811
2812 // 3) general entity and hp is used
2813 AssertIndexRange(structdim, dof_handler.hp_object_fe_indices.size());
2814 AssertIndexRange(structdim, dof_handler.hp_object_fe_ptr.size());
2815 AssertIndexRange(obj_index,
2816 dof_handler.hp_object_fe_ptr[structdim].size());
2817 AssertIndexRange(dof_handler.hp_object_fe_ptr[structdim][obj_index] +
2818 local_index,
2819 dof_handler.hp_object_fe_indices[structdim].size());
2820
2821 return dof_handler.hp_object_fe_indices
2822 [structdim]
2823 [dof_handler.hp_object_fe_ptr[structdim][obj_index] + local_index];
2824 }
2825
2826
2827
2840 template <int dim, int spacedim, int structdim>
2841 static std::set<types::fe_index>
2843 const unsigned int obj_level,
2844 const unsigned int obj_index,
2845 const std::integral_constant<int, structdim> &t)
2846 {
2847 Assert(structdim == dim || obj_level == 0, ExcNotImplemented());
2848
2849 // 1) no hp used -> fe_index == 0
2850 if (dof_handler.hp_capability_enabled == false)
2852
2853 // 2) cell and hp is used -> there is only one fe_index
2854 if (structdim == dim)
2855 return {dof_handler.hp_cell_active_fe_indices[obj_level][obj_index]};
2856
2857 // 3) general entity and hp is used
2858 std::set<types::fe_index> active_fe_indices;
2859 for (unsigned int i = 0;
2860 i < n_active_fe_indices(dof_handler, obj_level, obj_index, t);
2861 ++i)
2862 active_fe_indices.insert(
2863 nth_active_fe_index(dof_handler, obj_level, obj_index, i, t));
2864 return active_fe_indices;
2865 }
2866
2867
2868
2869 template <int dim, int spacedim, int structdim>
2870 static bool
2872 const unsigned int obj_level,
2873 const unsigned int obj_index,
2874 const types::fe_index fe_index,
2875 const std::integral_constant<int, structdim> &)
2876 {
2877 Assert(structdim == dim || obj_level == 0, ExcNotImplemented());
2878
2879 // 1) no hp used -> fe_index == 0
2880 if (dof_handler.hp_capability_enabled == false)
2882
2883 // 2) cell and hp is used -> there is only one fe_index
2884 if (structdim == dim)
2885 return dof_handler.hp_cell_active_fe_indices[obj_level][obj_index] ==
2886 fe_index;
2887
2888 // 3) general entity and hp is used
2889 return std::find(
2890 dof_handler.hp_object_fe_indices[structdim].begin() +
2891 dof_handler.hp_object_fe_ptr[structdim][obj_index],
2892 dof_handler.hp_object_fe_indices[structdim].begin() +
2893 dof_handler.hp_object_fe_ptr[structdim][obj_index + 1],
2894 fe_index) !=
2895 (dof_handler.hp_object_fe_indices[structdim].begin() +
2896 dof_handler.hp_object_fe_ptr[structdim][obj_index + 1]);
2897 }
2898
2899
2900
2901 template <typename InputVector, typename ForwardIterator>
2902 static void
2903 extract_subvector_to(const InputVector &values,
2904 const types::global_dof_index *cache,
2905 const types::global_dof_index *cache_end,
2906 ForwardIterator local_values_begin)
2907 {
2908 values.extract_subvector_to(cache, cache_end, local_values_begin);
2909 }
2910
2911
2912
2913#ifdef DEAL_II_WITH_TRILINOS
2914 static std::vector<unsigned int>
2916 const types::global_dof_index *v_end)
2917 {
2918 // initialize original index locations
2919 std::vector<unsigned int> idx(v_end - v_begin);
2920 std::iota(idx.begin(), idx.end(), 0u);
2921
2922 // sort indices based on comparing values in v
2923 std::sort(idx.begin(),
2924 idx.end(),
2925 [&v_begin](unsigned int i1, unsigned int i2) {
2926 return *(v_begin + i1) < *(v_begin + i2);
2927 });
2928
2929 return idx;
2930 }
2931
2932
2933
2934# ifdef DEAL_II_TRILINOS_WITH_TPETRA
2935 template <typename ForwardIterator, typename Number, typename MemorySpace>
2936 static void
2939 &values,
2940 const types::global_dof_index *cache_begin,
2941 const types::global_dof_index *cache_end,
2942 ForwardIterator local_values_begin)
2943 {
2944 std::vector<unsigned int> sorted_indices_pos =
2945 sort_indices(cache_begin, cache_end);
2946 const unsigned int cache_size = cache_end - cache_begin;
2947 std::vector<types::global_dof_index> cache_indices(cache_size);
2948 for (unsigned int i = 0; i < cache_size; ++i)
2949 cache_indices[i] = *(cache_begin + sorted_indices_pos[i]);
2950
2951 IndexSet index_set(cache_indices.back() + 1);
2952 index_set.add_indices(cache_indices.begin(), cache_indices.end());
2953 index_set.compress();
2954 LinearAlgebra::ReadWriteVector<Number> read_write_vector(index_set);
2955 read_write_vector.import_elements(values, VectorOperation::insert);
2956
2957 // Copy the elements from read_write_vector and reorder them.
2958 for (unsigned int i = 0; i < cache_size; ++i, ++local_values_begin)
2959 *local_values_begin = read_write_vector[sorted_indices_pos[i]];
2960 }
2961# endif
2962
2963
2964# ifdef DEAL_II_TRILINOS_WITH_EPETRA
2965 template <typename ForwardIterator>
2966 static void
2968 const types::global_dof_index *cache_begin,
2969 const types::global_dof_index *cache_end,
2970 ForwardIterator local_values_begin)
2971 {
2972 std::vector<unsigned int> sorted_indices_pos =
2973 sort_indices(cache_begin, cache_end);
2974 const unsigned int cache_size = cache_end - cache_begin;
2975 std::vector<types::global_dof_index> cache_indices(cache_size);
2976 for (unsigned int i = 0; i < cache_size; ++i)
2977 cache_indices[i] = *(cache_begin + sorted_indices_pos[i]);
2978
2979 IndexSet index_set(cache_indices.back() + 1);
2980 index_set.add_indices(cache_indices.begin(), cache_indices.end());
2981 index_set.compress();
2982 LinearAlgebra::ReadWriteVector<double> read_write_vector(index_set);
2983 read_write_vector.import_elements(values, VectorOperation::insert);
2984
2985 // Copy the elements from read_write_vector and reorder them.
2986 for (unsigned int i = 0; i < cache_size; ++i, ++local_values_begin)
2987 *local_values_begin = read_write_vector[sorted_indices_pos[i]];
2988 }
2989# endif
2990#endif
2991
2996 template <int dim, int spacedim, bool level_dof_access, int structdim>
2997 static unsigned int
2999 const ::DoFAccessor<structdim, dim, spacedim, level_dof_access>
3000 &accessor,
3001 const types::fe_index fe_index_,
3002 const bool count_level_dofs)
3003 {
3004 // note: we cannot rely on the template parameter level_dof_access here,
3005 // since the function get_mg_dof_indices()/set_mg_dof_indices() can be
3006 // called even if level_dof_access==false.
3007 if (count_level_dofs)
3008 {
3009 const auto &fe = accessor.get_fe(fe_index_);
3010
3011 const unsigned int //
3012 dofs_per_vertex = fe.n_dofs_per_vertex(), //
3013 dofs_per_line = fe.n_dofs_per_line(), //
3014 dofs_per_quad = fe.n_dofs_per_quad(0 /*dummy*/), //
3015 dofs_per_hex = fe.n_dofs_per_hex(); //
3016
3017 unsigned int index = 0;
3018
3019 // 1) VERTEX dofs
3020 index += dofs_per_vertex * accessor.n_vertices();
3021
3022 // 2) LINE dofs
3023 if (structdim == 2 || structdim == 3)
3024 index += dofs_per_line * accessor.n_lines();
3025
3026 // 3) FACE dofs
3027 if (structdim == 3)
3028 index += dofs_per_quad * accessor.n_faces();
3029
3030 // 4) INNER dofs
3031 const unsigned int interior_dofs =
3032 structdim == 1 ? dofs_per_line :
3033 (structdim == 2 ? dofs_per_quad : dofs_per_hex);
3034
3035 index += interior_dofs;
3036
3037 return index;
3038 }
3039 else
3040 {
3041 const auto fe_index =
3043 accessor, fe_index_);
3044
3045 unsigned int index = 0;
3046
3047 // 1) VERTEX dofs
3048 for (const auto vertex : accessor.vertex_indices())
3049 index += process_object_range(accessor.get_dof_handler(),
3050 0,
3051 accessor.vertex_index(vertex),
3052 fe_index,
3053 std::integral_constant<int, 0>())
3054 .second;
3055
3056 // 2) LINE dofs
3057 if constexpr (structdim == 2 || structdim == 3)
3058 {
3059 const auto line_indices = TriaAccessorImplementation::
3060 Implementation::get_line_indices_of_cell(accessor);
3061 for (const auto line_no : accessor.line_indices())
3062 {
3064 &accessor.get_triangulation(),
3065 0,
3066 line_indices[line_no],
3067 &accessor.get_dof_handler());
3068 index += process_object_range(line, fe_index).second;
3069 }
3070 }
3071
3072 // 3) FACE dofs
3073 if (structdim == 3)
3074 for (const auto face : accessor.face_indices())
3075 index +=
3076 process_object_range(*accessor.quad(face), fe_index).second;
3077
3078 // 4) INNER dofs
3079 index += process_object_range(accessor, fe_index).second;
3080
3081 return index;
3082 }
3083 }
3084
3085
3086
3087 // The next few internal helper functions are needed to support various
3088 // DoFIndicesType kinds, e.g. actual vectors of DoFIndices or empty
3089 // types that we use when we only want to work on the internally stored
3090 // DoFs and never extract any number.
3091 template <typename ArrayType>
3092 static unsigned int
3093 get_array_length(const ArrayType &array)
3094 {
3095 return array.size();
3096 }
3097
3098 static unsigned int
3099 get_array_length(const std::tuple<> &)
3100 {
3101 return 0;
3102 }
3103
3104 template <typename ArrayType>
3106 get_array_ptr(const ArrayType &array)
3107 {
3108 return const_cast<types::global_dof_index *>(array.data());
3109 }
3110
3112 get_array_ptr(const std::tuple<> &)
3113 {
3114 return nullptr;
3115 }
3116
3117
3118
3124 template <int dim,
3125 int spacedim,
3126 bool level_dof_access,
3127 int structdim,
3128 typename DoFIndicesType,
3129 typename DoFOperation,
3130 typename DoFProcessor>
3131 static void
3133 const ::DoFAccessor<structdim, dim, spacedim, level_dof_access>
3134 &accessor,
3135 const DoFIndicesType &const_dof_indices,
3136 const types::fe_index fe_index_,
3137 const DoFOperation &dof_operation,
3138 const DoFProcessor &dof_processor,
3139 const bool count_level_dofs)
3140 {
3141 const types::fe_index fe_index =
3143 accessor, fe_index_);
3144
3145 // we cannot rely on the template parameter level_dof_access here, since
3146 // the function get_mg_dof_indices()/set_mg_dof_indices() can be called
3147 // even if level_dof_access==false.
3148 (void)count_level_dofs;
3149
3150 const auto &fe = accessor.get_fe(fe_index);
3151
3152 // we want to pass in rvalue 'std::tuple<>' types as `DoFIndicesType`,
3153 // but we need non-const references for std::vector<> types, so get in
3154 // a const reference here and immediately cast the constness away -
3155 // note that any use of the dereferenced invalid type will result in a
3156 // segfault
3157 types::global_dof_index *dof_indices_ptr =
3158 get_array_ptr(const_dof_indices);
3159 types::global_dof_index *end_dof_indices =
3160 dof_indices_ptr + get_array_length(const_dof_indices);
3161
3162 // 1) VERTEX dofs, only step into the functions if we actually have
3163 // DoFs on them
3164 if (fe.n_dofs_per_vertex() > 0)
3165 for (const auto vertex : accessor.vertex_indices())
3166 dof_operation.process_vertex_dofs(*accessor.dof_handler,
3167 accessor.vertex_index(vertex),
3168 fe_index,
3169 dof_indices_ptr,
3170 dof_processor);
3171
3172 // 2) copy dof numbers from the LINE, accounting for the possibility of
3173 // reversed line orientations.
3174 if (structdim > 1 && fe.n_dofs_per_line() > 0)
3175 {
3176 const auto [line_indices, line_orientations] =
3177 internal::TriaAccessorImplementation::Implementation::
3178 get_line_indices_and_orientations_of_cell(accessor);
3179
3180 for (const auto line : accessor.line_indices())
3181 {
3182 const auto line_orientation = line_orientations[line];
3183 if (line_orientation == numbers::default_geometric_orientation)
3184 dof_operation.process_dofs(
3185 accessor.get_dof_handler(),
3186 0,
3187 line_indices[line],
3188 fe_index,
3189 [](const auto d) { return d; },
3190 std::integral_constant<int, 1>(),
3191 dof_indices_ptr,
3192 dof_processor);
3193 else
3194 {
3195 Assert(line_orientation ==
3198 dof_operation.process_dofs(
3199 accessor.get_dof_handler(),
3200 0,
3201 line_indices[line],
3202 fe_index,
3203 [&fe](const auto d) {
3204 return fe.adjust_line_dof_index_for_line_orientation(
3205 d, numbers::reverse_line_orientation);
3206 },
3207 std::integral_constant<int, 1>(),
3208 dof_indices_ptr,
3209 dof_processor);
3210 }
3211 }
3212 }
3213
3214 // 3) copy dof numbers from the QUAD (i.e., 3d faces). Like lines we
3215 // only adjust dof indices (which has some cost) if we are not in the
3216 // default orientation.
3217 if (structdim == 3 && fe.max_dofs_per_quad() > 0)
3218 for (const auto face_no : accessor.face_indices())
3219 {
3220 const auto combined_orientation =
3221 accessor.combined_face_orientation(face_no);
3222 const unsigned int quad_index = accessor.quad_index(face_no);
3223 if (combined_orientation ==
3225 dof_operation.process_dofs(
3226 accessor.get_dof_handler(),
3227 0,
3228 quad_index,
3229 fe_index,
3230 [](const auto d) { return d; },
3231 std::integral_constant<int, 2>(),
3232 dof_indices_ptr,
3233 dof_processor);
3234 else
3235 dof_operation.process_dofs(
3236 accessor.get_dof_handler(),
3237 0,
3238 quad_index,
3239 fe_index,
3240 [&](const auto d) {
3241 return fe.adjust_quad_dof_index_for_face_orientation(
3242 d, face_no, combined_orientation);
3243 },
3244 std::integral_constant<int, 2>(),
3245 dof_indices_ptr,
3246 dof_processor);
3247 }
3248
3249 // 4) INNER dofs (i.e., line dofs in 1d, quad dofs in 2d, or hex dofs in
3250 // 3d) - here we need to make sure that the shortcut to not run the
3251 // function does not miss the faces of wedge and pyramid elements where
3252 // n_dofs_per_object might not return the largest possible value
3253 if (((dim == 3 && structdim == 2) ?
3254 fe.max_dofs_per_quad() :
3255 fe.template n_dofs_per_object<structdim>()) > 0)
3256 dof_operation.process_dofs(
3257 accessor.get_dof_handler(),
3258 accessor.level(),
3259 accessor.index(),
3260 fe_index,
3261 [&](const auto d) { return d; },
3262 std::integral_constant<int, structdim>(),
3263 dof_indices_ptr,
3264 dof_processor);
3265
3266 if (dof_indices_ptr != nullptr)
3267 {
3268 AssertDimension(n_dof_indices(accessor, fe_index, count_level_dofs),
3269 dof_indices_ptr - get_array_ptr(const_dof_indices));
3270 }
3271
3272 // PM: This is a part that should not be reached since it indicates that
3273 // an object (and/or its subobjects) is not active. However,
3274 // unfortunately this function is called by
3275 // DoFTools::set_periodicity_constraints() indirectly by
3276 // get_dof_indices() also for artificial faces to determine if a face
3277 // is artificial.
3279 for (; dof_indices_ptr < end_dof_indices; ++dof_indices_ptr)
3280 dof_processor(invalid_index, dof_indices_ptr);
3281 }
3282
3283
3284
3289 template <int dim, int spacedim>
3291 {
3295 template <typename DoFProcessor>
3298 const unsigned int vertex_index,
3299 const types::fe_index fe_index,
3300 types::global_dof_index *&dof_indices_ptr,
3301 const DoFProcessor &dof_processor) const
3302 {
3304 dof_handler,
3305 0,
3306 vertex_index,
3307 fe_index,
3308 [](const auto d) {
3310 return d;
3311 },
3312 std::integral_constant<int, 0>(),
3313 dof_indices_ptr,
3314 dof_processor);
3315 }
3316
3320 template <int structdim, typename DoFMapping, typename DoFProcessor>
3323 const unsigned int obj_level,
3324 const unsigned int obj_index,
3325 const types::fe_index fe_index,
3326 const DoFMapping &mapping,
3327 const std::integral_constant<int, structdim>,
3328 types::global_dof_index *&dof_indices_ptr,
3329 const DoFProcessor &dof_processor) const
3330 {
3332 dof_handler,
3333 obj_level,
3334 obj_index,
3335 fe_index,
3336 mapping,
3337 std::integral_constant<int, std::min(structdim, dim)>(),
3338 dof_indices_ptr,
3339 dof_processor);
3340 }
3341 };
3342
3343
3344
3349 template <int dim, int spacedim>
3351 {
3355 MGDoFIndexProcessor(const unsigned int level)
3356 : level(level)
3357 {}
3358
3362 template <typename DoFProcessor>
3365 const unsigned int vertex_index,
3366 const types::fe_index,
3367 types::global_dof_index *&dof_indices_ptr,
3368 const DoFProcessor &dof_processor) const
3369 {
3370 const unsigned int n_indices =
3371 dof_handler.get_fe(0).template n_dofs_per_object<0>();
3372 types::global_dof_index *stored_indices =
3373 &dof_handler.mg_vertex_dofs[vertex_index].access_index(level,
3374 0,
3375 n_indices);
3376 for (unsigned int d = 0; d < n_indices; ++d, ++dof_indices_ptr)
3377 dof_processor(stored_indices[d], dof_indices_ptr);
3378 }
3379
3383 template <int structdim, typename DoFMapping, typename DoFProcessor>
3386 const unsigned int,
3387 const unsigned int obj_index,
3388 const types::fe_index fe_index,
3389 const DoFMapping &mapping,
3390 const std::integral_constant<int, structdim>,
3391 types::global_dof_index *&dof_indices_ptr,
3392 const DoFProcessor &dof_processor) const
3393 {
3394 const unsigned int n_indices =
3395 dof_handler.get_fe(0).template n_dofs_per_object<structdim>();
3396 types::global_dof_index *stored_indices = &get_mg_dof_index(
3397 dof_handler,
3398 dof_handler.mg_levels[level],
3399 dof_handler.mg_faces,
3400 obj_index,
3401 fe_index,
3402 0,
3403 std::integral_constant<int, std::min(structdim, dim)>());
3404 for (unsigned int d = 0; d < n_indices; ++d, ++dof_indices_ptr)
3405 dof_processor(stored_indices[structdim < dim ? mapping(d) : d],
3406 dof_indices_ptr);
3407 }
3408
3409 private:
3410 const unsigned int level;
3411 };
3412
3413
3414
3415 template <int dim, int spacedim, bool level_dof_access, int structdim>
3416 static void
3418 const ::DoFAccessor<structdim, dim, spacedim, level_dof_access>
3419 &accessor,
3420 std::vector<types::global_dof_index> &dof_indices,
3421 const types::fe_index fe_index)
3422 {
3424 accessor,
3425 dof_indices,
3426 fe_index,
3428 [](auto stored_index, auto dof_ptr) { *dof_ptr = stored_index; },
3429 false);
3430 }
3431
3432
3433
3434 template <int dim, int spacedim, bool level_dof_access, int structdim>
3435 static void
3437 const ::DoFAccessor<structdim, dim, spacedim, level_dof_access>
3438 &accessor,
3439 const std::vector<types::global_dof_index> &dof_indices,
3440 const types::fe_index fe_index)
3441 {
3442 // Note: this function is as general as `get_dof_indices()`. This
3443 // assert is placed here since it is currently only used by the
3444 // function DoFCellAccessor::set_dof_indices(), which is called by
3445 // internal::DoFHandlerImplementation::Policy::Implementation::distribute_dofs().
3446 // In the case of new use cases, this assert can be removed.
3447 Assert(
3448 dim == structdim,
3449 ExcMessage(
3450 "This function is intended to be used for DoFCellAccessor, i.e., "
3451 "dimension == structdim."));
3452
3454 accessor,
3455 dof_indices,
3456 fe_index,
3458 [](auto &stored_index, auto dof_ptr) { stored_index = *dof_ptr; },
3459 false);
3460 }
3461
3462
3463
3464 template <int dim, int spacedim, bool level_dof_access, int structdim>
3465 static void
3467 const ::DoFAccessor<structdim, dim, spacedim, level_dof_access>
3468 &accessor,
3469 const int level,
3470 std::vector<types::global_dof_index> &dof_indices,
3471 const types::fe_index fe_index)
3472 {
3474 ExcMessage("MG DoF indices cannot be queried in hp case"));
3476 accessor,
3477 dof_indices,
3478 fe_index,
3480 [](auto stored_index, auto dof_ptr) { *dof_ptr = stored_index; },
3481 true);
3482 }
3483
3484
3485
3486 template <int dim, int spacedim, bool level_dof_access, int structdim>
3487 static void
3489 const ::DoFAccessor<structdim, dim, spacedim, level_dof_access>
3490 &accessor,
3491 const int level,
3492 const std::vector<types::global_dof_index> &dof_indices,
3493 const types::fe_index fe_index)
3494 {
3496 ExcMessage("MG DoF indices cannot be queried in hp case"));
3497
3498 // Note: this function is as general as `get_mg_dof_indices()`. This
3499 // assert is placed here since it is currently only used by the
3500 // function DoFCellAccessor::set_mg_dof_indices(), which is called by
3501 // internal::DoFHandlerImplementation::Policy::Implementation::distribute_mg_dofs().
3502 // In the case of new use cases, this assert can be removed.
3503 Assert(dim == structdim,
3504 ExcMessage("This function is intended to be used for "
3505 "DoFCellAccessor, i.e., dimension == structdim."));
3506
3508 accessor,
3509 dof_indices,
3510 fe_index,
3512 [](auto &stored_index, auto dof_ptr) { stored_index = *dof_ptr; },
3513 true);
3514 }
3515
3516
3517
3518 template <int dim, int spacedim>
3521 const DoFHandler<dim, spacedim> &dof_handler,
3523 &mg_level,
3525 &,
3526 const unsigned int obj_index,
3527 const types::fe_index fe_index,
3528 const unsigned int local_index,
3529 const std::integral_constant<int, dim>)
3530 {
3531 Assert(dof_handler.hp_capability_enabled == false,
3533
3534 return mg_level->dof_object.access_dof_index(
3535 static_cast<const DoFHandler<dim, spacedim> &>(dof_handler),
3536 obj_index,
3537 fe_index,
3538 local_index);
3539 }
3540
3541
3542
3543 template <int dim, int spacedim, std::enable_if_t<(dim > 1), int> = 0>
3546 const DoFHandler<dim, spacedim> &dof_handler,
3548 &,
3550 &mg_faces,
3551 const unsigned int obj_index,
3552 const types::fe_index fe_index,
3553 const unsigned int local_index,
3554 const std::integral_constant<int, 1>)
3555 {
3556 return mg_faces->lines.access_dof_index(
3557 static_cast<const DoFHandler<dim, spacedim> &>(dof_handler),
3558 obj_index,
3559 fe_index,
3560 local_index);
3561 }
3562
3563
3564
3565 template <int spacedim>
3568 const DoFHandler<3, spacedim> &dof_handler,
3570 &,
3572 &mg_faces,
3573 const unsigned int obj_index,
3574 const types::fe_index fe_index,
3575 const unsigned int local_index,
3576 const std::integral_constant<int, 2>)
3577 {
3578 Assert(dof_handler.hp_capability_enabled == false,
3580 return mg_faces->quads.access_dof_index(
3581 static_cast<const DoFHandler<3, spacedim> &>(dof_handler),
3582 obj_index,
3583 fe_index,
3584 local_index);
3585 }
3586 };
3587
3588
3589
3590 template <int dim, int spacedim, bool level_dof_access>
3591 void
3593 const ::DoFCellAccessor<dim, spacedim, level_dof_access> &accessor,
3595 const unsigned int fe_index);
3596 } // namespace DoFAccessorImplementation
3597} // namespace internal
3598
3599
3600
3601template <int structdim, int dim, int spacedim, bool level_dof_access>
3604 const unsigned int i,
3605 const types::fe_index fe_index_) const
3606{
3607 const auto fe_index =
3609 fe_index_);
3610
3611 // access the respective DoF
3612 return ::internal::DoFAccessorImplementation::Implementation::
3613 get_dof_index(*this->dof_handler,
3614 this->level(),
3615 this->index(),
3616 fe_index,
3617 i,
3618 std::integral_constant<int, structdim>());
3619}
3620
3621
3622template <int structdim, int dim, int spacedim, bool level_dof_access>
3625 const int level,
3626 const unsigned int i) const
3627{
3629 *this->dof_handler,
3630 this->dof_handler->mg_levels[level],
3631 this->dof_handler->mg_faces,
3632 this->index(),
3633 0,
3634 i,
3635 std::integral_constant<int, structdim>());
3636}
3637
3638
3639template <int structdim, int dim, int spacedim, bool level_dof_access>
3640inline void
3642 const unsigned int i,
3643 const types::global_dof_index index,
3644 const types::fe_index fe_index_) const
3645{
3646 const auto fe_index =
3648 fe_index_);
3649
3650 // access the respective DoF
3652 *this->dof_handler,
3653 this->level(),
3654 this->index(),
3655 fe_index,
3656 i,
3657 std::integral_constant<int, structdim>(),
3658 index);
3659}
3660
3661
3662
3663template <int structdim, int dim, int spacedim, bool level_dof_access>
3664inline void
3666 const int level,
3667 const unsigned int i,
3668 const types::global_dof_index index) const
3669{
3671 *this->dof_handler,
3672 this->dof_handler->mg_levels[level],
3673 this->dof_handler->mg_faces,
3674 this->index(),
3675 0,
3676 i,
3677 std::integral_constant<int, structdim>()) = index;
3678}
3679
3680
3681
3682template <int structdim, int dim, int spacedim, bool level_dof_access>
3683inline unsigned int
3685 const
3686{
3687 // access the respective DoF
3688 return ::internal::DoFAccessorImplementation::Implementation::
3689 n_active_fe_indices(*this->dof_handler,
3690 this->level(),
3691 this->index(),
3692 std::integral_constant<int, structdim>());
3693}
3694
3695
3696
3697template <int structdim, int dim, int spacedim, bool level_dof_access>
3698inline types::fe_index
3700 const unsigned int n) const
3701{
3702 // access the respective DoF
3703 return ::internal::DoFAccessorImplementation::Implementation::
3704 nth_active_fe_index(*this->dof_handler,
3705 this->level(),
3706 this->index(),
3707 n,
3708 std::integral_constant<int, structdim>());
3709}
3710
3711
3712
3713template <int structdim, int dim, int spacedim, bool level_dof_access>
3714inline std::set<types::fe_index>
3716 const
3717{
3718 std::set<types::fe_index> active_fe_indices;
3719 for (unsigned int i = 0; i < n_active_fe_indices(); ++i)
3720 active_fe_indices.insert(nth_active_fe_index(i));
3721 return active_fe_indices;
3722}
3723
3724
3725
3726template <int structdim, int dim, int spacedim, bool level_dof_access>
3727inline bool
3729 const types::fe_index fe_index) const
3730{
3731 // access the respective DoF
3732 return ::internal::DoFAccessorImplementation::Implementation::
3733 fe_index_is_active(*this->dof_handler,
3734 this->level(),
3735 this->index(),
3736 fe_index,
3737 std::integral_constant<int, structdim>());
3738}
3739
3740
3741
3742template <int structdim, int dim, int spacedim, bool level_dof_access>
3745 const unsigned int vertex,
3746 const unsigned int i,
3747 const types::fe_index fe_index_) const
3748{
3749 const types::fe_index fe_index =
3750 (((this->dof_handler->hp_capability_enabled == false) &&
3751 (fe_index_ == numbers::invalid_fe_index)) ?
3752 // No hp enabled, and the argument is at its default value -> we
3753 // can translate to the default active fe index
3755 // Otherwise: If anything other than the default is provided by
3756 // the caller, then we should take just that. As an exception, if
3757 // we are on a cell (rather than a face/edge/vertex), then we know
3758 // that there is only one active fe index on this cell and we can
3759 // use that:
3760 ((dim == structdim) && (fe_index_ == numbers::invalid_fe_index) ?
3761 this->nth_active_fe_index(0) :
3762 fe_index_));
3763
3764 return ::internal::DoFAccessorImplementation::Implementation::
3765 get_dof_index(*this->dof_handler,
3766 0,
3767 this->vertex_index(vertex),
3768 fe_index,
3769 i,
3770 std::integral_constant<int, 0>());
3771}
3772
3773
3774template <int structdim, int dim, int spacedim, bool level_dof_access>
3777 const int level,
3778 const unsigned int vertex,
3779 const unsigned int i,
3780 const types::fe_index fe_index_) const
3781{
3782 const auto fe_index =
3784 fe_index_);
3785 (void)fe_index;
3786 Assert(this->dof_handler != nullptr, ExcInvalidObject());
3787 Assert(this->dof_handler->mg_vertex_dofs.size() > 0,
3788 ExcMessage("Multigrid DoF indices can only be accessed after "
3789 "DoFHandler::distribute_mg_dofs() has been called!"));
3790 AssertIndexRange(vertex, this->n_vertices());
3791 AssertIndexRange(i, this->dof_handler->get_fe(fe_index).n_dofs_per_vertex());
3792
3793 Assert(dof_handler->hp_capability_enabled == false,
3794 ExcMessage(
3795 "DoFHandler in hp-mode does not implement multilevel DoFs."));
3796
3797 return this->dof_handler->mg_vertex_dofs[this->vertex_index(vertex)]
3798 .access_index(level, i, this->dof_handler->get_fe().n_dofs_per_vertex());
3799}
3800
3801
3802
3803template <int structdim, int dim, int spacedim, bool level_dof_access>
3804inline void
3807 const unsigned int vertex,
3808 const unsigned int i,
3809 const types::global_dof_index index,
3810 const types::fe_index fe_index_) const
3811{
3812 const auto fe_index =
3814 fe_index_);
3815 (void)fe_index;
3816 Assert(this->dof_handler != nullptr, ExcInvalidObject());
3817 AssertIndexRange(vertex, this->n_vertices());
3818 AssertIndexRange(i, this->dof_handler->get_fe(fe_index).n_dofs_per_vertex());
3819
3820 Assert(dof_handler->hp_capability_enabled == false,
3821 ExcMessage(
3822 "DoFHandler in hp-mode does not implement multilevel DoFs."));
3823
3824 this->dof_handler->mg_vertex_dofs[this->vertex_index(vertex)].access_index(
3825 level, i, this->dof_handler->get_fe().n_dofs_per_vertex()) = index;
3826}
3827
3828
3829
3830template <int structdim, int dim, int spacedim, bool level_dof_access>
3831inline const FiniteElement<dim, spacedim> &
3833 const types::fe_index fe_index) const
3834{
3835 Assert(fe_index_is_active(fe_index) == true,
3836 ExcMessage("This function can only be called for active FE indices"));
3837
3838 return this->dof_handler->get_fe(fe_index);
3839}
3840
3841
3842
3843template <int structdim, int dim, int spacedim, bool level_dof_access>
3844inline typename ::internal::DoFHandlerImplementation::
3845 Iterators<dim, spacedim, level_dof_access>::line_iterator
3847 const unsigned int i) const
3848{
3849 // if we are asking for a particular line and this object refers to
3850 // a line, then the only valid index is i==0 and we should return
3851 // *this
3852 if (structdim == 1)
3853 {
3854 Assert(i == 0,
3855 ExcMessage("You can only ask for line zero if the "
3856 "current object is a line itself."));
3857 return typename ::internal::DoFHandlerImplementation::
3858 Iterators<dim, spacedim, level_dof_access>::cell_iterator(
3859 &this->get_triangulation(),
3860 this->level(),
3861 this->index(),
3862 &this->get_dof_handler());
3863 }
3864
3865 // otherwise we need to be in structdim>=2
3866 Assert(structdim > 1, ExcImpossibleInDim(structdim));
3867 Assert(dim > 1, ExcImpossibleInDim(dim));
3868
3869 // checking of 'i' happens in line_index(i)
3870 return typename ::internal::DoFHandlerImplementation::
3871 Iterators<dim, spacedim, level_dof_access>::line_iterator(
3872 this->tria,
3873 0, // only sub-objects are allowed, which have no level
3874 this->line_index(i),
3875 this->dof_handler);
3876}
3877
3878
3879template <int structdim, int dim, int spacedim, bool level_dof_access>
3880inline typename ::internal::DoFHandlerImplementation::
3881 Iterators<dim, spacedim, level_dof_access>::quad_iterator
3883 const unsigned int i) const
3884{
3885 // if we are asking for a
3886 // particular quad and this object
3887 // refers to a quad, then the only
3888 // valid index is i==0 and we
3889 // should return *this
3890 if (structdim == 2)
3891 {
3892 Assert(i == 0,
3893 ExcMessage("You can only ask for quad zero if the "
3894 "current object is a quad itself."));
3895 return typename ::internal::DoFHandlerImplementation::
3896 Iterators<dim, spacedim>::cell_iterator(&this->get_triangulation(),
3897 this->level(),
3898 this->index(),
3899 &this->get_dof_handler());
3900 }
3901
3902 // otherwise we need to be in structdim>=3
3903 Assert(structdim > 2, ExcImpossibleInDim(structdim));
3904 Assert(dim > 2, ExcImpossibleInDim(dim));
3905
3906 // checking of 'i' happens in quad_index(i)
3907 return typename ::internal::DoFHandlerImplementation::
3908 Iterators<dim, spacedim, level_dof_access>::quad_iterator(
3909 this->tria,
3910 0, // only sub-objects are allowed, which have no level
3911 this->quad_index(i),
3912 this->dof_handler);
3913}
3914
3915
3916/*----------------- Functions: DoFAccessor<0,1,spacedim> --------------------*/
3917
3918
3919template <int spacedim, bool level_dof_access>
3921{
3922 Assert(false, ExcInvalidObject());
3923}
3924
3925
3926
3927template <int spacedim, bool level_dof_access>
3929 const Triangulation<1, spacedim> *tria,
3930 const typename TriaAccessor<0, 1, spacedim>::VertexKind vertex_kind,
3931 const unsigned int vertex_index,
3932 const DoFHandler<1, spacedim> *dof_handler)
3933 : BaseClass(tria, vertex_kind, vertex_index)
3934 , dof_handler(const_cast<DoFHandler<1, spacedim> *>(dof_handler))
3935{}
3936
3937
3938
3939template <int spacedim, bool level_dof_access>
3941 const Triangulation<1, spacedim> *tria,
3942 const int level,
3943 const int index,
3944 const DoFHandler<1, spacedim> *dof_handler)
3945 // This is the constructor signature for "ordinary" (non-vertex)
3946 // accessors and we shouldn't be calling it altogether. But it is also
3947 // the constructor that the default-constructor of TriaRawIterator
3948 // calls when default-constructing an iterator object. If so, this
3949 // happens with level==-2 and index==-2, and this is the only case we
3950 // would like to support. We do this by just forwarding to the
3951 // other constructor of this class, and then asserting the condition
3952 // on level and index.
3953 : DoFAccessor<0, 1, spacedim, level_dof_access>(
3954 tria,
3955 TriaAccessor<0, 1, spacedim>::interior_vertex,
3956 0U,
3957 dof_handler)
3958{
3959 (void)level;
3960 (void)index;
3961 Assert((tria == nullptr) && (level == -2) && (index == -2) &&
3962 (dof_handler == nullptr),
3963 ExcMessage(
3964 "This constructor can not be called for face iterators in 1d, "
3965 "except to default-construct iterator objects."));
3966}
3967
3968
3969
3970template <int spacedim, bool level_dof_access>
3971template <int structdim2, int dim2, int spacedim2>
3977
3978
3979
3980template <int spacedim, bool level_dof_access>
3981template <int structdim2, int dim2, int spacedim2, bool level_dof_access2>
3987
3988
3989
3990template <int spacedim, bool level_dof_access>
3991inline void
3994{
3995 Assert(dh != nullptr, ExcInvalidObject());
3996 this->dof_handler = dh;
3997}
3998
3999
4000
4001template <int spacedim, bool level_dof_access>
4002inline void
4004 const unsigned int /*i*/,
4005 const types::global_dof_index /*index*/,
4006 const types::fe_index /*fe_index*/) const
4007{
4009}
4010
4011
4012
4013template <int spacedim, bool level_dof_access>
4014inline const DoFHandler<1, spacedim> &
4016{
4017 return *this->dof_handler;
4018}
4019
4020
4021
4022template <int spacedim, bool level_dof_access>
4023inline void
4025 std::vector<types::global_dof_index> &dof_indices,
4026 const types::fe_index fe_index_) const
4027{
4028 const auto fe_index =
4030 fe_index_);
4031
4032 for (unsigned int i = 0; i < dof_indices.size(); ++i)
4033 dof_indices[i] = ::internal::DoFAccessorImplementation::
4034 Implementation::get_dof_index(*dof_handler,
4035 0,
4036 this->global_vertex_index,
4037 fe_index,
4038 i,
4039 std::integral_constant<int, 0>());
4040}
4041
4042
4043
4044template <int spacedim, bool level_dof_access>
4045inline void
4047 const int level,
4048 std::vector<types::global_dof_index> &dof_indices,
4049 const types::fe_index fe_index_) const
4050{
4051 const auto fe_index =
4053 fe_index_);
4054 (void)fe_index;
4056
4057 for (unsigned int i = 0; i < dof_indices.size(); ++i)
4058 dof_indices[i] =
4060 mg_vertex_dof_index(*dof_handler, level, this->global_vertex_index, i);
4061}
4062
4063
4064
4065template <int spacedim, bool level_dof_access>
4068 const unsigned int vertex,
4069 const unsigned int i,
4070 const types::fe_index fe_index_) const
4071{
4072 const auto fe_index =
4074 fe_index_);
4075
4076 (void)vertex;
4077 AssertIndexRange(vertex, 1);
4078 return ::internal::DoFAccessorImplementation::Implementation::
4079 get_dof_index(*dof_handler,
4080 0,
4081 this->global_vertex_index,
4082 fe_index,
4083 i,
4084 std::integral_constant<int, 0>());
4085}
4086
4087
4088
4089template <int spacedim, bool level_dof_access>
4092 const unsigned int i,
4093 const types::fe_index fe_index_) const
4094{
4095 const auto fe_index =
4097 fe_index_);
4098
4099 return ::internal::DoFAccessorImplementation::Implementation::
4100 get_dof_index(*this->dof_handler,
4101 0,
4102 this->vertex_index(0),
4103 fe_index,
4104 i,
4105 std::integral_constant<int, 0>());
4106}
4107
4108
4109
4110template <int spacedim, bool level_dof_access>
4111inline unsigned int
4116
4117
4118
4119template <int spacedim, bool level_dof_access>
4120inline types::fe_index
4122 const unsigned int /*n*/) const
4123{
4124 return 0;
4125}
4126
4127
4128
4129template <int spacedim, bool level_dof_access>
4130inline bool
4132 const types::fe_index /*fe_index*/) const
4133{
4135 return false;
4136}
4137
4138
4139
4140template <int spacedim, bool level_dof_access>
4141inline const FiniteElement<1, spacedim> &
4143 const types::fe_index fe_index) const
4144{
4145 Assert(this->dof_handler != nullptr, ExcInvalidObject());
4146 return dof_handler->get_fe(fe_index);
4147}
4148
4149
4150
4151template <int spacedim, bool level_dof_access>
4152inline void
4155{
4156 Assert(this->dof_handler != nullptr, ExcInvalidObject());
4157 BaseClass::copy_from(da);
4158}
4159
4160
4161
4162template <int spacedim, bool level_dof_access>
4163template <bool level_dof_access2>
4164inline void
4167{
4168 BaseClass::copy_from(a);
4169 set_dof_handler(a.dof_handler);
4170}
4171
4172
4173
4174template <int spacedim, bool level_dof_access>
4181
4182
4183
4184template <int spacedim, bool level_dof_access>
4185inline typename ::internal::DoFHandlerImplementation::
4186 Iterators<1, spacedim, level_dof_access>::line_iterator
4188 const unsigned int /*c*/) const
4189{
4191 return typename ::internal::DoFHandlerImplementation::
4192 Iterators<1, spacedim, level_dof_access>::line_iterator();
4193}
4194
4195
4196
4197template <int spacedim, bool level_dof_access>
4198inline typename ::internal::DoFHandlerImplementation::
4199 Iterators<1, spacedim, level_dof_access>::quad_iterator
4201 const unsigned int /*c*/) const
4202{
4204 return typename ::internal::DoFHandlerImplementation::
4205 Iterators<1, spacedim, level_dof_access>::quad_iterator();
4206}
4207
4208
4209
4210template <int spacedim, bool level_dof_access>
4211template <int structdim2, int dim2, int spacedim2, bool level_dof_access2>
4212inline bool
4215{
4216 Assert(structdim2 == 0, ExcCantCompareIterators());
4217 Assert(this->dof_handler == a.dof_handler, ExcCantCompareIterators());
4218 return (BaseClass::operator==(a));
4219}
4220
4221
4222
4223template <int spacedim, bool level_dof_access>
4224template <int structdim2, int dim2, int spacedim2, bool level_dof_access2>
4225inline bool
4228{
4229 Assert(structdim2 == 0, ExcCantCompareIterators());
4230 Assert(this->dof_handler == a.dof_handler, ExcCantCompareIterators());
4231 return (BaseClass::operator!=(a));
4232}
4233
4234
4235
4236/*------------------------- Functions: DoFCellAccessor -----------------------*/
4237
4238
4239namespace internal
4240{
4241 namespace DoFCellAccessorImplementation
4242 {
4248 {
4253 template <int dim, int spacedim, bool level_dof_access>
4254 static types::fe_index
4257 {
4258 if (accessor.dof_handler->hp_capability_enabled == false)
4260
4261 Assert(accessor.dof_handler != nullptr,
4262 (typename std::decay_t<decltype(accessor)>::ExcInvalidObject()));
4263 Assert(static_cast<unsigned int>(accessor.level()) <
4264 accessor.dof_handler->hp_cell_future_fe_indices.size(),
4265 ExcMessage("DoFHandler not initialized"));
4266
4267 return accessor.dof_handler
4268 ->hp_cell_active_fe_indices[accessor.level()][accessor.present_index];
4269 }
4270
4271
4272
4277 template <int dim, int spacedim, bool level_dof_access>
4278 static void
4281 const types::fe_index i)
4282 {
4283 if (accessor.dof_handler->hp_capability_enabled == false)
4284 {
4286 return;
4287 }
4288
4289 Assert(accessor.dof_handler != nullptr,
4290 (typename std::decay_t<decltype(accessor)>::ExcInvalidObject()));
4291 Assert(static_cast<unsigned int>(accessor.level()) <
4292 accessor.dof_handler->hp_cell_future_fe_indices.size(),
4293 ExcMessage("DoFHandler not initialized"));
4295 ExcMessage("Invalid finite element index."));
4296
4297 accessor.dof_handler
4298 ->hp_cell_active_fe_indices[accessor.level()]
4299 [accessor.present_index] = i;
4300 }
4301
4302
4303
4308 template <int dim, int spacedim, bool level_dof_access>
4309 static types::fe_index
4312 {
4313 if (accessor.dof_handler->hp_capability_enabled == false)
4315
4316 Assert(accessor.dof_handler != nullptr,
4317 (typename std::decay_t<decltype(accessor)>::ExcInvalidObject()));
4318 Assert(static_cast<unsigned int>(accessor.level()) <
4319 accessor.dof_handler->hp_cell_future_fe_indices.size(),
4320 ExcMessage("DoFHandler not initialized"));
4321
4322 if (future_fe_index_set(accessor))
4323 return accessor.dof_handler
4324 ->hp_cell_future_fe_indices[accessor.level()]
4325 [accessor.present_index];
4326 else
4327 return accessor.dof_handler
4328 ->hp_cell_active_fe_indices[accessor.level()]
4329 [accessor.present_index];
4330 }
4331
4332
4337 template <int dim, int spacedim, bool level_dof_access>
4338 static void
4341 const types::fe_index i)
4342 {
4343 if (accessor.dof_handler->hp_capability_enabled == false)
4344 {
4346 return;
4347 }
4348
4349 Assert(accessor.dof_handler != nullptr,
4350 (typename std::decay_t<decltype(accessor)>::ExcInvalidObject()));
4351 Assert(static_cast<unsigned int>(accessor.level()) <
4352 accessor.dof_handler->hp_cell_future_fe_indices.size(),
4353 ExcMessage("DoFHandler not initialized"));
4355 ExcMessage("Invalid finite element index."));
4356
4357 accessor.dof_handler
4358 ->hp_cell_future_fe_indices[accessor.level()]
4359 [accessor.present_index] = i;
4360 }
4361
4362
4363
4368 template <int dim, int spacedim, bool level_dof_access>
4369 static bool
4372 {
4373 if (accessor.dof_handler->hp_capability_enabled == false)
4374 return false;
4375
4376 Assert(accessor.dof_handler != nullptr,
4377 (typename std::decay_t<decltype(accessor)>::ExcInvalidObject()));
4378 Assert(static_cast<unsigned int>(accessor.level()) <
4379 accessor.dof_handler->hp_cell_future_fe_indices.size(),
4380 ExcMessage("DoFHandler not initialized"));
4381
4382 return accessor.dof_handler
4383 ->hp_cell_future_fe_indices[accessor.level()]
4384 [accessor.present_index] !=
4386 }
4387
4388
4389
4394 template <int dim, int spacedim, bool level_dof_access>
4395 static void
4398 {
4399 if (accessor.dof_handler->hp_capability_enabled == false)
4400 return;
4401
4402 Assert(accessor.dof_handler != nullptr,
4403 (typename std::decay_t<decltype(accessor)>::ExcInvalidObject()));
4404 Assert(static_cast<unsigned int>(accessor.level()) <
4405 accessor.dof_handler->hp_cell_future_fe_indices.size(),
4406 ExcMessage("DoFHandler not initialized"));
4407
4408 accessor.dof_handler
4409 ->hp_cell_future_fe_indices[accessor.level()]
4410 [accessor.present_index] =
4412 }
4413 };
4414 } // namespace DoFCellAccessorImplementation
4415} // namespace internal
4416
4417
4418
4419template <int dimension_, int space_dimension_, bool level_dof_access>
4422 const int level,
4423 const int index,
4424 const AccessorData *local_data)
4425 : DoFAccessor<dimension_, dimension_, space_dimension_, level_dof_access>(
4426 tria,
4427 level,
4428 index,
4429 local_data)
4430{}
4431
4432
4433
4434template <int dimension_, int space_dimension_, bool level_dof_access>
4435template <int structdim2, int dim2, int spacedim2>
4441
4442
4443
4444template <int dimension_, int space_dimension_, bool level_dof_access>
4445template <int structdim2, int dim2, int spacedim2, bool level_dof_access2>
4451
4452
4453
4454template <int dimension_, int space_dimension_, bool level_dof_access>
4455inline TriaIterator<
4458 const unsigned int i) const
4459{
4461 q(this->tria,
4462 this->neighbor_level(i),
4463 this->neighbor_index(i),
4464 this->dof_handler);
4465
4466 if constexpr (running_in_debug_mode())
4467 {
4469 Assert(q->used(), ExcInternalError());
4470 }
4471 return q;
4472}
4473
4474
4475
4476template <int dimension_, int space_dimension_, bool level_dof_access>
4477inline TriaIterator<
4480 const unsigned int i) const
4481{
4483 q(this->tria, this->level() + 1, this->child_index(i), this->dof_handler);
4484
4485 if constexpr (running_in_debug_mode())
4486 {
4488 Assert(q->used(), ExcInternalError());
4489 }
4490 return q;
4491}
4492
4493
4494
4495template <int dimension_, int space_dimension_, bool level_dof_access>
4496inline boost::container::small_vector<
4500 child_iterators() const
4501{
4502 boost::container::small_vector<
4506 child_iterators(this->n_children());
4507
4508 for (unsigned int i = 0; i < this->n_children(); ++i)
4509 child_iterators[i] = this->child(i);
4510
4511 return child_iterators;
4512}
4513
4514
4515
4516template <int dimension_, int space_dimension_, bool level_dof_access>
4517inline TriaIterator<
4520{
4522 q(this->tria, this->level() - 1, this->parent_index(), this->dof_handler);
4523
4524 return q;
4525}
4526
4527
4528
4529namespace internal
4530{
4531 namespace DoFCellAccessorImplementation
4532 {
4533 template <int dim, int spacedim, bool level_dof_access>
4534 inline TriaIterator<
4535 ::DoFAccessor<dim - 1, dim, spacedim, level_dof_access>>
4537 const ::DoFCellAccessor<dim, spacedim, level_dof_access> &cell,
4538 const unsigned int i,
4539 const std::integral_constant<int, 1>)
4540 {
4542 &cell.get_triangulation(),
4543 ((i == 0) && cell.at_boundary(0) ?
4545 ((i == 1) && cell.at_boundary(1) ?
4548 cell.vertex_index(i),
4549 &cell.get_dof_handler());
4550 return ::TriaIterator<
4552 }
4553
4554
4555 template <int dim, int spacedim, bool level_dof_access>
4556 inline TriaIterator<
4557 ::DoFAccessor<dim - 1, dim, spacedim, level_dof_access>>
4559 const ::DoFCellAccessor<dim, spacedim, level_dof_access> &cell,
4560 const unsigned int i,
4561 const std::integral_constant<int, 2>)
4562 {
4563 return cell.line(i);
4564 }
4565
4566
4567 template <int dim, int spacedim, bool level_dof_access>
4568 inline TriaIterator<
4569 ::DoFAccessor<dim - 1, dim, spacedim, level_dof_access>>
4571 const ::DoFCellAccessor<dim, spacedim, level_dof_access> &cell,
4572 const unsigned int i,
4573 const std::integral_constant<int, 3>)
4574 {
4575 return cell.quad(i);
4576 }
4577 } // namespace DoFCellAccessorImplementation
4578} // namespace internal
4579
4580
4581
4582template <int dimension_, int space_dimension_, bool level_dof_access>
4583inline typename DoFCellAccessor<dimension_,
4584 space_dimension_,
4585 level_dof_access>::face_iterator
4587 const unsigned int i) const
4588{
4589 AssertIndexRange(i, this->n_faces());
4590
4591 return ::internal::DoFCellAccessorImplementation::get_face(
4592 *this, i, std::integral_constant<int, dimension_>());
4593}
4594
4595
4596
4597template <int dimension_, int space_dimension_, bool level_dof_access>
4598inline boost::container::small_vector<
4600 face_iterator,
4603 face_iterators() const
4604{
4605 boost::container::small_vector<
4607 face_iterator,
4609 face_iterators(this->n_faces());
4610
4611 for (const unsigned int i : this->face_indices())
4612 face_iterators[i] =
4614 *this, i, std::integral_constant<int, dimension_>());
4615
4616 return face_iterators;
4617}
4618
4619
4620
4621template <int dimension_, int space_dimension_, bool level_dof_access>
4622inline void
4625 std::vector<types::global_dof_index> &dof_indices) const
4626{
4627 if (level_dof_access)
4628 get_mg_dof_indices(dof_indices);
4629 else
4630 get_dof_indices(dof_indices);
4631}
4632
4633
4634
4635template <int dimension_, int space_dimension_, bool level_dof_access>
4636template <class InputVector, typename number>
4637inline void
4639 const InputVector &values,
4640 Vector<number> &local_values) const
4641{
4642 get_dof_values(values, local_values.begin(), local_values.end());
4643}
4644
4645
4646
4647template <int dimension_, int space_dimension_, bool level_dof_access>
4648template <typename Number, typename ForwardIterator>
4649inline void
4651 const ReadVector<Number> &values,
4652 ForwardIterator local_values_begin,
4653 ForwardIterator local_values_end) const
4654{
4655 (void)local_values_end;
4656 Assert(this->is_artificial() == false,
4657 ExcMessage("Can't ask for DoF indices on artificial cells."));
4658 Assert(this->is_active(), ExcMessage("Cell must be active."));
4659 Assert(this->dof_handler != nullptr, typename BaseClass::ExcInvalidObject());
4660
4661 Assert(static_cast<unsigned int>(local_values_end - local_values_begin) ==
4662 this->get_fe().n_dofs_per_cell(),
4664 Assert(values.size() == this->get_dof_handler().n_dofs(),
4666
4668 dof_indices(this->get_fe().n_dofs_per_cell());
4670 *this, dof_indices, this->active_fe_index());
4671
4672 boost::container::small_vector<Number, 100> values_temp(local_values_end -
4673 local_values_begin);
4674 auto view = make_array_view(values_temp.begin(), values_temp.end());
4675 values.extract_subvector_to(make_array_view(dof_indices.begin(),
4676 dof_indices.end()),
4677 view);
4678 using view_type = std::remove_reference_t<decltype(*local_values_begin)>;
4679 ArrayView<view_type> values_view2(&*local_values_begin,
4680 local_values_end - local_values_begin);
4681 std::copy(values_temp.begin(), values_temp.end(), values_view2.begin());
4682}
4683
4684
4685
4686template <int dimension_, int space_dimension_, bool level_dof_access>
4687template <class InputVector, typename ForwardIterator>
4688inline void
4691 const InputVector &values,
4692 ForwardIterator local_values_begin,
4693 ForwardIterator local_values_end) const
4694{
4695 Assert(this->is_artificial() == false,
4696 ExcMessage("Can't ask for DoF indices on artificial cells."));
4697 Assert(this->is_active(), ExcMessage("Cell must be active."));
4698
4699 Assert(static_cast<unsigned int>(local_values_end - local_values_begin) ==
4700 this->get_fe().n_dofs_per_cell(),
4702 Assert(values.size() == this->get_dof_handler().n_dofs(),
4704
4705
4707 dof_indices(this->get_fe().n_dofs_per_cell());
4709 *this, dof_indices, this->active_fe_index());
4710
4711 constraints.get_dof_values(values,
4712 dof_indices.data(),
4713 local_values_begin,
4714 local_values_end);
4715}
4716
4717
4718
4719template <int dimension_, int space_dimension_, bool level_dof_access>
4720template <class OutputVector, typename number>
4721inline void
4723 const Vector<number> &local_values,
4724 OutputVector &values) const
4725{
4726 Assert(this->is_artificial() == false,
4727 ExcMessage("Can't ask for DoF indices on artificial cells."));
4728 Assert(this->is_active(), ExcMessage("Cell must be active."));
4729
4730 Assert(static_cast<unsigned int>(local_values.size()) ==
4731 this->get_fe().n_dofs_per_cell(),
4733 Assert(values.size() == this->get_dof_handler().n_dofs(),
4735
4736
4737 Assert(this->dof_handler != nullptr, typename BaseClass::ExcInvalidObject());
4739 dof_indices(this->get_fe().n_dofs_per_cell());
4741 *this, dof_indices, this->active_fe_index());
4742
4743 for (unsigned int i = 0; i < this->get_fe().n_dofs_per_cell(); ++i)
4745 dof_indices[i],
4746 values);
4747}
4748
4749
4750
4751template <int dimension_, int space_dimension_, bool level_dof_access>
4754{
4755 Assert(this->dof_handler != nullptr, typename BaseClass::ExcInvalidObject());
4756 Assert((this->dof_handler->hp_capability_enabled == false) ||
4757 this->is_active(),
4758 ExcMessage(
4759 "For DoFHandler objects in hp-mode, finite elements are only "
4760 "associated with active cells. Consequently, you can not ask "
4761 "for the active finite element on cells with children."));
4762
4763 const auto &fe = this->dof_handler->get_fe(active_fe_index());
4764
4765 Assert(this->reference_cell() == fe.reference_cell(),
4766 ExcMessage(
4767 "The reference-cell type used on this cell (" +
4768 this->reference_cell().to_string() +
4769 ") does not match the reference-cell type of the finite element "
4770 "associated with this cell (" +
4771 fe.reference_cell().to_string() +
4772 "). "
4773 "Did you accidentally use simplex elements on hypercube meshes "
4774 "(or the other way around), or are you using a mixed mesh and "
4775 "assigned a simplex element to a hypercube cell (or the other "
4776 "way around) via the active_fe_index?"));
4777
4778 return fe;
4779}
4780
4781
4782
4783template <int dimension_, int space_dimension_, bool level_dof_access>
4784inline types::fe_index
4786 active_fe_index() const
4787{
4788 Assert((this->dof_handler->hp_capability_enabled == false) ||
4789 this->is_active(),
4790 ExcMessage(
4791 "You can not ask for the active FE index on a cell that has "
4792 "children because no degrees of freedom are assigned "
4793 "to this cell and, consequently, no finite element "
4794 "is associated with it."));
4795 Assert((this->dof_handler->hp_capability_enabled == false) ||
4796 (this->is_locally_owned() || this->is_ghost()),
4797 ExcMessage("You can only query active FE index information on cells "
4798 "that are either locally owned or (after distributing "
4799 "degrees of freedom) are ghost cells."));
4800
4801 return ::internal::DoFCellAccessorImplementation::Implementation::
4802 active_fe_index(*this);
4803}
4804
4805
4806
4807template <int dimension_, int space_dimension_, bool level_dof_access>
4808inline void
4811{
4812 Assert((this->dof_handler->hp_capability_enabled == false) ||
4813 this->is_active(),
4814 ExcMessage("You can not set the active FE index on a cell that has "
4815 "children because no degrees of freedom will be assigned "
4816 "to this cell."));
4817
4818 Assert((this->dof_handler->hp_capability_enabled == false) ||
4819 this->is_locally_owned(),
4820 ExcMessage("You can only set active FE index information on cells "
4821 "that are locally owned. On ghost cells, this information "
4822 "will automatically be propagated from the owning process "
4823 "of that cell, and there is no information at all on "
4824 "artificial cells."));
4825
4827 set_active_fe_index(*this, i);
4828}
4829
4830
4831
4832template <int dimension_, int space_dimension_, bool level_dof_access>
4835 const
4836{
4837 Assert(this->dof_handler != nullptr, typename BaseClass::ExcInvalidObject());
4838 Assert((this->dof_handler->hp_capability_enabled == false) ||
4839 this->is_active(),
4840 ExcMessage(
4841 "For DoFHandler objects in hp-mode, finite elements are only "
4842 "associated with active cells. Consequently, you can not ask "
4843 "for the future finite element on cells with children."));
4844
4845 return this->dof_handler->get_fe(future_fe_index());
4846}
4847
4848
4849
4850template <int dimension_, int space_dimension_, bool level_dof_access>
4851inline types::fe_index
4853 future_fe_index() const
4854{
4855 Assert((this->dof_handler->hp_capability_enabled == false) ||
4856 (this->has_children() == false),
4857 ExcMessage(
4858 "You can not ask for the future FE index on a cell that has "
4859 "children because no degrees of freedom are assigned "
4860 "to this cell and, consequently, no finite element "
4861 "is associated with it."));
4862 Assert((this->dof_handler->hp_capability_enabled == false) ||
4863 (this->is_locally_owned()),
4864 ExcMessage("You can only query future FE index information on cells "
4865 "that are locally owned."));
4866
4867 return ::internal::DoFCellAccessorImplementation::Implementation::
4868 future_fe_index(*this);
4869}
4870
4871
4872
4873template <int dimension_, int space_dimension_, bool level_dof_access>
4874inline void
4877{
4878 Assert((this->dof_handler->hp_capability_enabled == false) ||
4879 (this->has_children() == false),
4880 ExcMessage("You can not set the future FE index on a cell that has "
4881 "children because no degrees of freedom will be assigned "
4882 "to this cell."));
4883
4884 Assert((this->dof_handler->hp_capability_enabled == false) ||
4885 this->is_locally_owned(),
4886 ExcMessage("You can only set future FE index information on cells "
4887 "that are locally owned."));
4888
4890 set_future_fe_index(*this, i);
4891}
4892
4893
4894
4895template <int dimension_, int space_dimension_, bool level_dof_access>
4896inline bool
4899{
4900 Assert((this->dof_handler->hp_capability_enabled == false) ||
4901 (this->has_children() == false),
4902 ExcMessage(
4903 "You can not ask for the future FE index on a cell that has "
4904 "children because no degrees of freedom are assigned "
4905 "to this cell and, consequently, no finite element "
4906 "is associated with it."));
4907 Assert((this->dof_handler->hp_capability_enabled == false) ||
4908 (this->is_locally_owned()),
4909 ExcMessage("You can only query future FE index information on cells "
4910 "that are locally owned."));
4911
4912 return ::internal::DoFCellAccessorImplementation::Implementation::
4913 future_fe_index_set(*this);
4914}
4915
4916
4917
4918template <int dimension_, int space_dimension_, bool level_dof_access>
4919inline void
4922{
4923 Assert((this->dof_handler->hp_capability_enabled == false) ||
4924 (this->has_children() == false),
4925 ExcMessage(
4926 "You can not ask for the future FE index on a cell that has "
4927 "children because no degrees of freedom are assigned "
4928 "to this cell and, consequently, no finite element "
4929 "is associated with it."));
4930 Assert((this->dof_handler->hp_capability_enabled == false) ||
4931 (this->is_locally_owned()),
4932 ExcMessage("You can only query future FE index information on cells "
4933 "that are locally owned."));
4934
4937}
4938
4939
4940
4941template <int dimension_, int space_dimension_, bool level_dof_access>
4942template <typename number, typename OutputVector>
4943inline void
4946 OutputVector &global_destination) const
4947{
4948 this->distribute_local_to_global(local_source.begin(),
4949 local_source.end(),
4950 global_destination);
4951}
4952
4953
4954
4955template <int dimension_, int space_dimension_, bool level_dof_access>
4956template <typename ForwardIterator, typename OutputVector>
4957inline void
4959 distribute_local_to_global(ForwardIterator local_source_begin,
4960 ForwardIterator local_source_end,
4961 OutputVector &global_destination) const
4962{
4963 Assert(this->dof_handler != nullptr,
4964 (typename std::decay_t<decltype(*this)>::ExcInvalidObject()));
4965 Assert(static_cast<unsigned int>(local_source_end - local_source_begin) ==
4966 this->get_fe().n_dofs_per_cell(),
4967 (typename std::decay_t<decltype(*this)>::ExcVectorDoesNotMatch()));
4968 Assert(this->dof_handler->n_dofs() == global_destination.size(),
4969 (typename std::decay_t<decltype(*this)>::ExcVectorDoesNotMatch()));
4970
4971 Assert(!this->has_children(), ExcMessage("Cell must be active"));
4972
4973 Assert(
4974 internal::ArrayViewHelper::is_contiguous(local_source_begin,
4975 local_source_end),
4976 ExcMessage(
4977 "This function can not be called with iterator types that do not point to contiguous memory."));
4978
4979 const unsigned int n_dofs = local_source_end - local_source_begin;
4980
4982 dof_indices(n_dofs);
4984 *this, dof_indices, this->active_fe_index());
4985
4986 // distribute cell vector
4987 global_destination.add(n_dofs, dof_indices.data(), &(*local_source_begin));
4988}
4989
4990
4991
4992template <int dimension_, int space_dimension_, bool level_dof_access>
4993template <typename ForwardIterator, typename OutputVector>
4994inline void
4998 ForwardIterator local_source_begin,
4999 ForwardIterator local_source_end,
5000 OutputVector &global_destination) const
5001{
5002 Assert(this->dof_handler != nullptr,
5003 (typename std::decay_t<decltype(*this)>::ExcInvalidObject()));
5004 Assert(local_source_end - local_source_begin ==
5005 this->get_fe().n_dofs_per_cell(),
5006 (typename std::decay_t<decltype(*this)>::ExcVectorDoesNotMatch()));
5007 Assert(this->dof_handler->n_dofs() == global_destination.size(),
5008 (typename std::decay_t<decltype(*this)>::ExcVectorDoesNotMatch()));
5009
5010 Assert(!this->has_children(), ExcMessage("Cell must be active."));
5011
5013 dof_indices(this->get_fe().n_dofs_per_cell());
5015 *this, dof_indices, this->active_fe_index());
5016
5017 // distribute cell vector
5018 constraints.distribute_local_to_global(local_source_begin,
5019 local_source_end,
5020 dof_indices.data(),
5021 global_destination);
5022}
5023
5024
5025
5026template <int dimension_, int space_dimension_, bool level_dof_access>
5027template <typename number, typename OutputMatrix>
5028inline void
5031 OutputMatrix &global_destination) const
5032{
5033 Assert(this->dof_handler != nullptr,
5034 (typename std::decay_t<decltype(*this)>::ExcInvalidObject()));
5035 Assert(local_source.m() == this->get_fe().n_dofs_per_cell(),
5036 (typename std::decay_t<decltype(*this)>::ExcMatrixDoesNotMatch()));
5037 Assert(local_source.n() == this->get_fe().n_dofs_per_cell(),
5038 (typename std::decay_t<decltype(*this)>::ExcMatrixDoesNotMatch()));
5039 Assert(this->dof_handler->n_dofs() == global_destination.m(),
5040 (typename std::decay_t<decltype(*this)>::ExcMatrixDoesNotMatch()));
5041 Assert(this->dof_handler->n_dofs() == global_destination.n(),
5042 (typename std::decay_t<decltype(*this)>::ExcMatrixDoesNotMatch()));
5043
5044 Assert(!this->has_children(), ExcMessage("Cell must be active."));
5045
5046 const unsigned int n_dofs = local_source.m();
5047
5049 dof_indices(n_dofs);
5051 *this, dof_indices, this->active_fe_index());
5052
5053 // distribute cell matrix
5054 for (unsigned int i = 0; i < n_dofs; ++i)
5055 global_destination.add(dof_indices[i],
5056 n_dofs,
5057 dof_indices.data(),
5058 &local_source(i, 0));
5059}
5060
5061
5062
5063template <int dimension_, int space_dimension_, bool level_dof_access>
5064template <typename number, typename OutputMatrix, typename OutputVector>
5065inline void
5068 const Vector<number> &local_vector,
5069 OutputMatrix &global_matrix,
5070 OutputVector &global_vector) const
5071{
5072 Assert(this->dof_handler != nullptr,
5073 (typename std::decay_t<decltype(*this)>::ExcInvalidObject()));
5074 Assert(local_matrix.m() == this->get_fe().n_dofs_per_cell(),
5075 (typename std::decay_t<decltype(*this)>::ExcMatrixDoesNotMatch()));
5076 Assert(local_matrix.n() == this->get_fe().n_dofs_per_cell(),
5077 (typename std::decay_t<decltype(*this)>::ExcVectorDoesNotMatch()));
5078 Assert(this->dof_handler->n_dofs() == global_matrix.m(),
5079 (typename std::decay_t<decltype(*this)>::ExcMatrixDoesNotMatch()));
5080 Assert(this->dof_handler->n_dofs() == global_matrix.n(),
5081 (typename std::decay_t<decltype(*this)>::ExcMatrixDoesNotMatch()));
5082 Assert(local_vector.size() == this->get_fe().n_dofs_per_cell(),
5083 (typename std::decay_t<decltype(*this)>::ExcVectorDoesNotMatch()));
5084 Assert(this->dof_handler->n_dofs() == global_vector.size(),
5085 (typename std::decay_t<decltype(*this)>::ExcVectorDoesNotMatch()));
5086
5087 Assert(!this->has_children(), ExcMessage("Cell must be active."));
5088
5089 const unsigned int n_dofs = this->get_fe().n_dofs_per_cell();
5091 dof_indices(n_dofs);
5093 *this, dof_indices, this->active_fe_index());
5094
5095 // distribute cell matrices
5096 for (unsigned int i = 0; i < n_dofs; ++i)
5097 {
5098 global_matrix.add(dof_indices[i],
5099 n_dofs,
5100 dof_indices.data(),
5101 &local_matrix(i, 0));
5102 global_vector(dof_indices[i]) += local_vector(i);
5103 }
5104}
5105
5106
5107
5109
5110
5111#endif
ArrayView< std::remove_reference_t< typename std::iterator_traits< Iterator >::reference >, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
void get_dof_values(const VectorType &global_vector, ForwardIteratorInd local_indices_begin, ForwardIteratorVec local_vector_begin, ForwardIteratorVec local_vector_end) const
void distribute_local_to_global(const InVector &local_vector, const std::vector< size_type > &local_dof_indices, OutVector &global_vector) const
iterator begin() const
Definition array_view.h:755
DoFAccessor< 0, 1, spacedim, level_dof_access > & operator=(const DoFAccessor< 0, 1, spacedim, level_dof_access > &da)=delete
DoFAccessor< 0, 1, spacedim, level_dof_access > & operator=(DoFAccessor< 0, 1, spacedim, level_dof_access > &&) noexcept=default
DoFAccessor(DoFAccessor< 0, 1, spacedim, level_dof_access > &&)=default
DoFAccessor(const DoFAccessor< 0, 1, spacedim, level_dof_access > &)=default
typename::internal::DoFHandlerImplementation::Iterators< dim, spacedim, level_dof_access >::line_iterator line(const unsigned int i) const
friend struct ::internal::DoFHandlerImplementation::Policy::Implementation
static constexpr unsigned int space_dimension
const DoFHandler< dim, spacedim > & get_dof_handler() const
void set_mg_dof_index(const int level, const unsigned int i, const types::global_dof_index index) const
friend class DoFAccessor
DoFAccessor< structdim, dim, spacedim, level_dof_access > & operator=(const DoFAccessor< structdim, dim, spacedim, level_dof_access > &da)=delete
types::fe_index nth_active_fe_index(const unsigned int n) const
DoFAccessor(DoFAccessor< structdim, dim, spacedim, level_dof_access > &&)
DoFAccessor(const DoFAccessor< structdim, dim, spacedim, level_dof_access2 > &)
TriaIterator< DoFAccessor< structdim, dim, spacedim, level_dof_access > > child(const unsigned int c) const
void set_mg_vertex_dof_index(const int level, const unsigned int vertex, const unsigned int i, const types::global_dof_index index, const types::fe_index fe_index=numbers::invalid_fe_index) const
~DoFAccessor()=default
static constexpr unsigned int dimension
void set_dof_handler(DoFHandler< dim, spacedim > *dh)
DoFAccessor(const DoFAccessor< structdim2, dim2, spacedim2, level_dof_access2 > &)
DoFAccessor< structdim, dim, spacedim, level_dof_access > & operator=(DoFAccessor< structdim, dim, spacedim, level_dof_access > &&)
std::set< types::fe_index > get_active_fe_indices() const
DoFAccessor(const DoFAccessor< structdim, dim, spacedim, level_dof_access > &)=default
void set_mg_dof_indices(const int level, const std::vector< types::global_dof_index > &dof_indices, const types::fe_index fe_index=numbers::invalid_fe_index)
void get_mg_dof_indices(const int level, std::vector< types::global_dof_index > &dof_indices, const types::fe_index fe_index=numbers::invalid_fe_index) const
types::global_dof_index mg_vertex_dof_index(const int level, const unsigned int vertex, const unsigned int i, const types::fe_index fe_index=numbers::invalid_fe_index) const
DoFAccessor(const Triangulation< dim, spacedim > *tria, const int level, const int index, const DoFHandler< dim, spacedim > *dof_handler)
bool operator!=(const DoFAccessor< structdim2, dim2, spacedim2, level_dof_access2 > &) const
void copy_from(const TriaAccessorBase< structdim, dim, spacedim > &da)
types::global_dof_index dof_index(const unsigned int i, const types::fe_index fe_index=numbers::invalid_fe_index) const
typename::internal::DoFHandlerImplementation::Iterators< dim, spacedim, level_dof_access >::quad_iterator quad(const unsigned int i) const
void copy_from(const DoFAccessor< structdim, dim, spacedim, level_dof_access2 > &a)
const FiniteElement< dim, spacedim > & get_fe(const types::fe_index fe_index) const
void get_dof_indices(std::vector< types::global_dof_index > &dof_indices, const types::fe_index fe_index=numbers::invalid_fe_index) const
bool operator==(const DoFAccessor< structdim2, dim2, spacedim2, level_dof_access2 > &) const
types::global_dof_index mg_dof_index(const int level, const unsigned int i) const
void set_dof_index(const unsigned int i, const types::global_dof_index index, const types::fe_index fe_index=numbers::invalid_fe_index) const
unsigned int n_active_fe_indices() const
static bool is_level_cell()
typename ::internal::DoFAccessorImplementation::Inheritance< structdim, dimension, space_dimension >::BaseClass BaseClass
types::global_dof_index vertex_dof_index(const unsigned int vertex, const unsigned int i, const types::fe_index fe_index=numbers::invalid_fe_index) const
DoFHandler< dim, spacedim > * dof_handler
DoFAccessor(const InvalidAccessor< structdim2, dim2, spacedim2 > &)
bool fe_index_is_active(const types::fe_index fe_index) const
boost::container::small_vector< TriaIterator< DoFCellAccessor< dimension_, space_dimension_, level_dof_access > >, GeometryInfo< dimension_ >::max_children_per_cell > child_iterators() const
DoFCellAccessor(DoFCellAccessor< dimension_, space_dimension_, level_dof_access > &&)=default
void get_active_or_mg_dof_indices(std::vector< types::global_dof_index > &dof_indices) const
void get_dof_values(const InputVector &values, Vector< number > &local_values) const
boost::container::small_vector< face_iterator, GeometryInfo< dimension_ >::faces_per_cell > face_iterators() const
types::fe_index future_fe_index() const
DoFCellAccessor< dimension_, space_dimension_, level_dof_access > & operator=(const DoFCellAccessor< dimension_, space_dimension_, level_dof_access > &da)=delete
const FiniteElement< dimension_, space_dimension_ > & get_fe() const
TriaIterator< DoFCellAccessor< dimension_, space_dimension_, level_dof_access > > child(const unsigned int i) const
DoFCellAccessor(const Triangulation< dimension_, space_dimension_ > *tria, const int level, const int index, const AccessorData *local_data)
void set_future_fe_index(const types::fe_index i) const
void distribute_local_to_global(const Vector< number > &local_source, OutputVector &global_destination) const
const FiniteElement< dimension_, space_dimension_ > & get_future_fe() const
TriaIterator< DoFCellAccessor< dimension_, space_dimension_, level_dof_access > > neighbor(const unsigned int i) const
void set_active_fe_index(const types::fe_index i) const
face_iterator face(const unsigned int i) const
void clear_future_fe_index() const
void set_dof_values(const Vector< number > &local_values, OutputVector &values) const
DoFCellAccessor(const DoFCellAccessor< dimension_, space_dimension_, level_dof_access > &)=default
~DoFCellAccessor()=default
bool future_fe_index_set() const
DoFCellAccessor< dimension_, space_dimension_, level_dof_access > & operator=(DoFCellAccessor< dimension_, space_dimension_, level_dof_access > &&)=default
types::fe_index active_fe_index() const
TriaIterator< DoFCellAccessor< dimension_, space_dimension_, level_dof_access > > parent() const
std::vector< std::unique_ptr<::internal::DoFHandlerImplementation::DoFLevel< dim > > > mg_levels
std::vector< std::vector< types::fe_index > > hp_cell_future_fe_indices
const FiniteElement< dim, spacedim > & get_fe(const types::fe_index index=0) const
std::vector< std::vector< types::fe_index > > hp_cell_active_fe_indices
std::vector< MGVertexDoFs > mg_vertex_dofs
std::vector< std::array< std::vector< types::global_dof_index >, dim+1 > > object_dof_indices
const Triangulation< dim, spacedim > & get_triangulation() const
std::vector< std::array< std::vector< offset_type >, dim+1 > > object_dof_ptr
std::unique_ptr<::internal::DoFHandlerImplementation::DoFFaces< dim > > mg_faces
bool hp_capability_enabled
bool has_hp_capabilities() const
std::array< std::vector< offset_type >, dim+1 > hp_object_fe_ptr
std::array< std::vector< types::fe_index >, dim+1 > hp_object_fe_indices
DoFInvalidAccessor(const void *parent=nullptr, const int level=-1, const int index=-1, const AccessorData *local_data=nullptr)
typename InvalidAccessor< structdim, dim, spacedim >::AccessorData AccessorData
unsigned int n_dofs_per_vertex() const
size_type n() const
size_type m() const
void compress() const
Definition index_set.h:1767
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
Definition index_set.h:1814
void import_elements(const ::Vector< Number > &vec, VectorOperation::values operation, const std::shared_ptr< const Utilities::MPI::CommunicationPatternBase > &communication_pattern={})
TriaIterator< TriaAccessor< structdim, dim, spacedim > > child(const unsigned int i) const
IteratorState::IteratorStates state() const
virtual size_type size() const override
iterator end()
iterator begin()
#define DEAL_II_ALWAYS_INLINE
Definition config.h:166
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_RESTRICT
Definition config.h:167
constexpr bool running_in_debug_mode()
Definition config.h:76
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_ASSERT_UNREACHABLE()
#define DEAL_II_NOT_IMPLEMENTED()
Point< 2 > second
Definition grid_out.cc:4640
unsigned int level
Definition grid_out.cc:4642
static ::ExceptionBase & ExcVectorNotEmpty()
#define DeclException0(Exception0)
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
static ::ExceptionBase & ExcNotActive()
#define AssertDimension(dim1, dim2)
static ::ExceptionBase & ExcMatrixDoesNotMatch()
#define AssertIndexRange(index, range)
#define DeclExceptionMsg(Exception, defaulttext)
static ::ExceptionBase & ExcInvalidObject()
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcCantCompareIterators()
static ::ExceptionBase & ExcVectorDoesNotMatch()
static ::ExceptionBase & ExcMessage(std::string arg1)
@ past_the_end
Iterator reached end of container.
Definition hp.h:115
types::fe_index get_fe_index_or_default(const DoFAccessor< structdim, dim, spacedim, level_dof_access > &cell, const types::fe_index fe_index)
void get_cell_dof_indices(const ::DoFCellAccessor< dim, spacedim, level_dof_access > &accessor, Implementation::dof_index_vector_type &dof_indices, const unsigned int fe_index)
TriaIterator< ::DoFAccessor< dim - 1, dim, spacedim, level_dof_access > > get_face(const ::DoFCellAccessor< dim, spacedim, level_dof_access > &cell, const unsigned int i, const std::integral_constant< int, 1 >)
constexpr types::global_dof_index invalid_dof_index
Definition types.h:259
constexpr types::geometric_orientation reverse_line_orientation
Definition types.h:355
constexpr types::geometric_orientation default_geometric_orientation
Definition types.h:342
constexpr types::fe_index invalid_fe_index
Definition types.h:250
STL namespace.
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
Definition types.h:30
unsigned short int fe_index
Definition types.h:70
void process_vertex_dofs(DoFHandler< dim, spacedim > &dof_handler, const unsigned int vertex_index, const types::fe_index fe_index, types::global_dof_index *&dof_indices_ptr, const DoFProcessor &dof_processor) const
void process_dofs(const DoFHandler< dim, spacedim > &dof_handler, const unsigned int obj_level, const unsigned int obj_index, const types::fe_index fe_index, const DoFMapping &mapping, const std::integral_constant< int, structdim >, types::global_dof_index *&dof_indices_ptr, const DoFProcessor &dof_processor) const
void process_dofs(const DoFHandler< dim, spacedim > &dof_handler, const unsigned int, const unsigned int obj_index, const types::fe_index fe_index, const DoFMapping &mapping, const std::integral_constant< int, structdim >, types::global_dof_index *&dof_indices_ptr, const DoFProcessor &dof_processor) const
void process_vertex_dofs(DoFHandler< dim, spacedim > &dof_handler, const unsigned int vertex_index, const types::fe_index, types::global_dof_index *&dof_indices_ptr, const DoFProcessor &dof_processor) const
static types::global_dof_index * get_array_ptr(const std::tuple<> &)
static void process_dof_indices(const ::DoFAccessor< structdim, dim, spacedim, level_dof_access > &accessor, const DoFIndicesType &const_dof_indices, const types::fe_index fe_index_, const DoFOperation &dof_operation, const DoFProcessor &dof_processor, const bool count_level_dofs)
static void get_dof_indices(const ::DoFAccessor< structdim, dim, spacedim, level_dof_access > &accessor, std::vector< types::global_dof_index > &dof_indices, const types::fe_index fe_index)
static void extract_subvector_to(const LinearAlgebra::TpetraWrappers::Vector< Number, MemorySpace > &values, const types::global_dof_index *cache_begin, const types::global_dof_index *cache_end, ForwardIterator local_values_begin)
static std::set< types::fe_index > get_active_fe_indices(const DoFHandler< dim, spacedim > &dof_handler, const unsigned int obj_level, const unsigned int obj_index, const std::integral_constant< int, structdim > &t)
static types::global_dof_index * get_array_ptr(const ArrayType &array)
static unsigned int get_array_length(const std::tuple<> &)
static unsigned int n_active_fe_indices(const DoFHandler< dim, spacedim > &dof_handler, const unsigned int obj_level, const unsigned int obj_index, const std::integral_constant< int, structdim > &)
static void set_dof_index(const DoFHandler< dim, spacedim > &dof_handler, const unsigned int obj_level, const unsigned int obj_index, const types::fe_index fe_index, const unsigned int local_index, const std::integral_constant< int, structdim > &dd, const types::global_dof_index global_index)
static void extract_subvector_to(const LinearAlgebra::EpetraWrappers::Vector &values, const types::global_dof_index *cache_begin, const types::global_dof_index *cache_end, ForwardIterator local_values_begin)
static void get_mg_dof_indices(const ::DoFAccessor< structdim, dim, spacedim, level_dof_access > &accessor, const int level, std::vector< types::global_dof_index > &dof_indices, const types::fe_index fe_index)
static bool fe_index_is_active(const DoFHandler< dim, spacedim > &dof_handler, const unsigned int obj_level, const unsigned int obj_index, const types::fe_index fe_index, const std::integral_constant< int, structdim > &)
static types::global_dof_index & get_mg_dof_index(const DoFHandler< dim, spacedim > &dof_handler, const std::unique_ptr< internal::DoFHandlerImplementation::DoFLevel< dim > > &, const std::unique_ptr< internal::DoFHandlerImplementation::DoFFaces< dim > > &mg_faces, const unsigned int obj_index, const types::fe_index fe_index, const unsigned int local_index, const std::integral_constant< int, 1 >)
boost::container::small_vector<::types::global_dof_index, 100 > dof_index_vector_type
static types::global_dof_index & get_mg_dof_index(const DoFHandler< dim, spacedim > &dof_handler, const std::unique_ptr< internal::DoFHandlerImplementation::DoFLevel< dim > > &mg_level, const std::unique_ptr< internal::DoFHandlerImplementation::DoFFaces< dim > > &, const unsigned int obj_index, const types::fe_index fe_index, const unsigned int local_index, const std::integral_constant< int, dim >)
static std::pair< unsigned int, unsigned int > process_object_range(const ::DoFAccessor< structdim, dim, spacedim, level_dof_access > accessor, const types::fe_index fe_index)
static types::global_dof_index & mg_vertex_dof_index(DoFHandler< dim, spacedim > &dof_handler, const int level, const unsigned int vertex_index, const unsigned int i)
static void set_mg_dof_indices(const ::DoFAccessor< structdim, dim, spacedim, level_dof_access > &accessor, const int level, const std::vector< types::global_dof_index > &dof_indices, const types::fe_index fe_index)
static void set_dof_indices(const ::DoFAccessor< structdim, dim, spacedim, level_dof_access > &accessor, const std::vector< types::global_dof_index > &dof_indices, const types::fe_index fe_index)
static void process_dof_index(const DoFHandler< dim, spacedim > &dof_handler, const unsigned int obj_level, const unsigned int obj_index, const types::fe_index fe_index, const unsigned int local_index, const std::integral_constant< int, structdim > &, GlobalIndexType &global_index, const DoFPProcessor &process)
static types::global_dof_index & get_mg_dof_index(const DoFHandler< 3, spacedim > &dof_handler, const std::unique_ptr< internal::DoFHandlerImplementation::DoFLevel< 3 > > &, const std::unique_ptr< internal::DoFHandlerImplementation::DoFFaces< 3 > > &mg_faces, const unsigned int obj_index, const types::fe_index fe_index, const unsigned int local_index, const std::integral_constant< int, 2 >)
static std::pair< unsigned int, unsigned int > process_object_range(const DoFHandler< dim, spacedim > &dof_handler, const unsigned int obj_level, const unsigned int obj_index, const types::fe_index fe_index, const std::integral_constant< int, structdim > &)
static void extract_subvector_to(const InputVector &values, const types::global_dof_index *cache, const types::global_dof_index *cache_end, ForwardIterator local_values_begin)
static std::vector< unsigned int > sort_indices(const types::global_dof_index *v_begin, const types::global_dof_index *v_end)
static types::fe_index nth_active_fe_index(const DoFHandler< dim, spacedim > &dof_handler, const unsigned int obj_level, const unsigned int obj_index, const unsigned int local_index, const std::integral_constant< int, structdim > &)
static void process_object(const DoFHandler< dim, spacedim > &dof_handler, const unsigned int obj_level, const unsigned int obj_index, const types::fe_index fe_index, const DoFMapping &mapping, const std::integral_constant< int, structdim > &dd, types::global_dof_index *&dof_indices_ptr, const DoFProcessor &process)
static types::global_dof_index get_dof_index(const DoFHandler< dim, spacedim > &dof_handler, const unsigned int obj_level, const unsigned int obj_index, const types::fe_index fe_index, const unsigned int local_index, const std::integral_constant< int, structdim > &dd)
static unsigned int n_dof_indices(const ::DoFAccessor< structdim, dim, spacedim, level_dof_access > &accessor, const types::fe_index fe_index_, const bool count_level_dofs)
static std::pair< unsigned int, unsigned int > process_object_range(::DoFInvalidAccessor< structdim, dim, spacedim >, const unsigned int)
static unsigned int get_array_length(const ArrayType &array)
static types::fe_index future_fe_index(const DoFCellAccessor< dim, spacedim, level_dof_access > &accessor)
static void clear_future_fe_index(const DoFCellAccessor< dim, spacedim, level_dof_access > &accessor)
static bool future_fe_index_set(const DoFCellAccessor< dim, spacedim, level_dof_access > &accessor)
static void set_active_fe_index(const DoFCellAccessor< dim, spacedim, level_dof_access > &accessor, const types::fe_index i)
static void set_future_fe_index(const DoFCellAccessor< dim, spacedim, level_dof_access > &accessor, const types::fe_index i)
static types::fe_index active_fe_index(const DoFCellAccessor< dim, spacedim, level_dof_access > &accessor)