Reference documentation for deal.II version 9.4.0
\(\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\}}\)
array_view.h
Go to the documentation of this file.
1// ---------------------------------------------------------------------
2//
3// Copyright (C) 2004 - 2021 by the deal.II authors
4//
5// This file is part of the deal.II library.
6//
7// The deal.II library is free software; you can use it, redistribute
8// it, and/or modify it under the terms of the GNU Lesser General
9// Public License as published by the Free Software Foundation; either
10// version 2.1 of the License, or (at your option) any later version.
11// The full text of the license can be found in the file LICENSE.md at
12// the top level directory of deal.II.
13//
14// ---------------------------------------------------------------------
15
16#ifndef dealii_array_view_h
17#define dealii_array_view_h
18
19#include <deal.II/base/config.h>
20
24#include <deal.II/base/tensor.h>
25
26#include <type_traits>
27#include <vector>
28
30
31// Forward declaration
32template <int N, typename T>
33class Table;
34
35template <typename number>
37
38
80template <typename ElementType, typename MemorySpaceType = MemorySpace::Host>
82{
83public:
89
94
98 using const_iterator = const ElementType *;
99
104
125
135 ArrayView(const ArrayView<typename std::remove_cv<value_type>::type,
136 MemorySpaceType> &view);
137
142 explicit ArrayView(value_type &element);
143
159 const std::vector<typename std::remove_cv<value_type>::type> &vector);
160
175 ArrayView(std::vector<typename std::remove_cv<value_type>::type> &vector);
176
191 template <std::size_t N>
193
202 template <std::size_t N>
204 const std::array<typename std::remove_cv<value_type>::type, N> &vector);
205
214 template <std::size_t N>
215 ArrayView(std::array<typename std::remove_cv<value_type>::type, N> &vector);
216
236 void
238
244 bool
246 const ArrayView<const value_type, MemorySpaceType> &other_view) const;
247
253 bool
254 operator==(const ArrayView<typename std::remove_cv<value_type>::type,
255 MemorySpaceType> &other_view) const;
256
262 bool
264 const ArrayView<const value_type, MemorySpaceType> &other_view) const;
265
271 bool
272 operator!=(const ArrayView<typename std::remove_cv<value_type>::type,
273 MemorySpaceType> &other_view) const;
274
279 std::size_t
280 size() const;
281
286 value_type *
287 data() const noexcept;
288
293 begin() const;
294
299 end() const;
300
305 cbegin() const;
306
311 cend() const;
312
325 value_type &
326 operator[](const std::size_t i) const;
327
328private:
334
339
340 friend class ArrayView<const ElementType, MemorySpaceType>;
341};
342
343
344
345//---------------------------------------------------------------------------
346
347
348namespace internal
349{
350 namespace ArrayViewHelper
351 {
352 template <typename MemorySpaceType>
353 inline bool
354 is_in_correct_memory_space(const void *const ptr)
355 {
356#ifndef DEAL_II_COMPILER_CUDA_AWARE
357 (void)ptr;
358 static_assert(std::is_same<MemorySpaceType, MemorySpace::Host>::value,
359 "If the compiler doesn't understand CUDA code, "
360 "the only possible memory space is 'MemorySpace::Host'!");
361 return true;
362#else
363 cudaPointerAttributes attributes;
364 const cudaError_t cuda_error = cudaPointerGetAttributes(&attributes, ptr);
365 if (cuda_error != cudaErrorInvalidValue)
366 {
367 AssertCuda(cuda_error);
368 if (std::is_same<MemorySpaceType, MemorySpace::Host>::value)
369 return (attributes.type == cudaMemoryTypeHost) ||
370 (attributes.type == cudaMemoryTypeUnregistered);
371 else
372 return attributes.type == cudaMemoryTypeDevice;
373 }
374 else
375 {
376 // ignore and reset the error since host pointers produce an error
377 cudaGetLastError();
378 return std::is_same<MemorySpaceType, MemorySpace::Host>::value;
379 }
380#endif
381 }
382 } // namespace ArrayViewHelper
383} // namespace internal
384
385
386
387template <typename ElementType, typename MemorySpaceType>
389 : starting_element(nullptr)
390 , n_elements(0)
391{}
392
393
394
395template <typename ElementType, typename MemorySpaceType>
397 value_type * starting_element,
398 const std::size_t n_elements)
399 : starting_element(starting_element)
400 , n_elements(n_elements)
401{
402 Assert(
403 n_elements == 0 ||
404 internal::ArrayViewHelper::is_in_correct_memory_space<MemorySpaceType>(
406 ExcMessage("The memory space indicated by the template parameter "
407 "and the one derived from the pointer value do not match!"));
408}
409
410
411
412template <typename ElementType, typename MemorySpaceType>
413inline void
415 const std::size_t n_elements)
416{
417 this->starting_element = starting_element;
418 this->n_elements = n_elements;
419}
420
421
422
423template <typename ElementType, typename MemorySpaceType>
425 : starting_element(&element)
426 , n_elements(1)
427{}
428
429
430
431template <typename ElementType, typename MemorySpaceType>
433 const ArrayView<typename std::remove_cv<value_type>::type, MemorySpaceType>
434 &view)
435 : starting_element(view.starting_element)
436 , n_elements(view.n_elements)
437{}
438
439
440
441template <typename ElementType, typename MemorySpaceType>
443 const std::vector<typename std::remove_cv<value_type>::type> &vector)
444 : // use delegating constructor
445 ArrayView(vector.data(), vector.size())
446{
447 // the following static_assert is not strictly necessary because,
448 // if we got a const std::vector reference argument but ElementType
449 // is not itself const, then the call to the forwarding constructor
450 // above will already have failed: vector.data() will have returned
451 // a const pointer, but we need a non-const pointer.
452 //
453 // nevertheless, leave the static_assert in since it provides a
454 // more descriptive error message that will simply come after the first
455 // error produced above
456 static_assert(std::is_const<value_type>::value == true,
457 "This constructor may only be called if the ArrayView "
458 "object has a const value_type. In other words, you can "
459 "only create an ArrayView to const values from a const "
460 "std::vector.");
461}
462
463
464
465template <typename ElementType, typename MemorySpaceType>
467 std::vector<typename std::remove_cv<value_type>::type> &vector)
468 : // use delegating constructor
469 ArrayView(vector.data(), vector.size())
470{}
471
472
473
474template <typename ElementType, typename MemorySpaceType>
475template <std::size_t N>
477 const std::array<typename std::remove_cv<value_type>::type, N> &vector)
478 : // use delegating constructor
479 ArrayView(vector.data(), vector.size())
480{
481 // the following static_assert is not strictly necessary because,
482 // if we got a const std::array reference argument but ElementType
483 // is not itself const, then the call to the forwarding constructor
484 // above will already have failed: vector.data() will have returned
485 // a const pointer, but we need a non-const pointer.
486 //
487 // nevertheless, leave the static_assert in since it provides a
488 // more descriptive error message that will simply come after the first
489 // error produced above
490 static_assert(std::is_const<value_type>::value == true,
491 "This constructor may only be called if the ArrayView "
492 "object has a const value_type. In other words, you can "
493 "only create an ArrayView to const values from a const "
494 "std::array.");
495}
496
497
498
499template <typename ElementType, typename MemorySpaceType>
500template <std::size_t N>
502 ElementType (&array)[N])
503 : ArrayView(&array[0], N)
504{}
505
506
507
508template <typename ElementType, typename MemorySpaceType>
509template <std::size_t N>
511 std::array<typename std::remove_cv<value_type>::type, N> &vector)
512 : // use delegating constructor
513 ArrayView(vector.data(), vector.size())
514{}
515
516
517
518template <typename ElementType, typename MemorySpaceType>
519inline bool
521 const ArrayView<const value_type, MemorySpaceType> &other_view) const
522{
523 return (other_view.data() == starting_element) &&
524 (other_view.size() == n_elements);
525}
526
527
528
529template <typename ElementType, typename MemorySpaceType>
530inline bool
532 const ArrayView<typename std::remove_cv<value_type>::type, MemorySpaceType>
533 &other_view) const
534{
535 return (other_view.data() == starting_element) &&
536 (other_view.size() == n_elements);
537}
538
539
540
541template <typename ElementType, typename MemorySpaceType>
542inline bool
544 const ArrayView<const value_type, MemorySpaceType> &other_view) const
545{
546 return !(*this == other_view);
547}
548
549
550
551template <typename ElementType, typename MemorySpaceType>
554{
555 if (n_elements == 0)
556 return nullptr;
557 else
558 return starting_element;
559}
560
561
562
563template <typename ElementType, typename MemorySpaceType>
564inline bool
566 const ArrayView<typename std::remove_cv<value_type>::type, MemorySpaceType>
567 &other_view) const
568{
569 return !(*this == other_view);
570}
571
572
573
574template <typename ElementType, typename MemorySpaceType>
575inline std::size_t
577{
578 return n_elements;
579}
580
581
582
583template <typename ElementType, typename MemorySpaceType>
586{
587 return starting_element;
588}
589
590
591
592template <typename ElementType, typename MemorySpaceType>
595{
596 return starting_element + n_elements;
597}
598
599
600
601template <typename ElementType, typename MemorySpaceType>
604{
605 return starting_element;
606}
607
608
609
610template <typename ElementType, typename MemorySpaceType>
613{
614 return starting_element + n_elements;
615}
616
617
618
619template <typename ElementType, typename MemorySpaceType>
622{
623 AssertIndexRange(i, n_elements);
624 Assert(
625 (std::is_same<MemorySpaceType, MemorySpace::Host>::value),
627 "Accessing elements is only allowed if the data is stored in CPU memory!"));
628
629 return *(starting_element + i);
630}
631
632
633
634#ifndef DOXYGEN
635namespace internal
636{
637 namespace ArrayViewHelper
638 {
644 template <class Iterator>
645 bool
646 is_contiguous(const Iterator &first, const Iterator &last)
647 {
648 const auto n = std::distance(first, last);
649 for (typename std::decay<decltype(n)>::type i = 0; i < n; ++i)
650 if (std::addressof(*(std::next(first, i))) !=
651 std::next(std::addressof(*first), i))
652 return false;
653 return true;
654 }
655
656
667 template <class T>
668 constexpr bool
669 is_contiguous(T *, T *)
670 {
671 return true;
672 }
673 } // namespace ArrayViewHelper
674} // namespace internal
675#endif
676
677
678
695template <typename Iterator, typename MemorySpaceType = MemorySpace::Host>
696ArrayView<typename std::remove_reference<
697 typename std::iterator_traits<Iterator>::reference>::type,
698 MemorySpaceType>
699make_array_view(const Iterator begin, const Iterator end)
700{
701 static_assert(
702 std::is_same<typename std::iterator_traits<Iterator>::iterator_category,
703 typename std::random_access_iterator_tag>::value,
704 "The provided iterator should be a random access iterator.");
705 Assert(begin <= end,
707 "The beginning of the array view should be before the end."));
708 Assert(internal::ArrayViewHelper::is_contiguous(begin, end),
709 ExcMessage("The provided range isn't contiguous in memory!"));
710 // the reference type, not the value type, knows the constness of the iterator
711 return ArrayView<typename std::remove_reference<
712 typename std::iterator_traits<Iterator>::reference>::type,
713 MemorySpaceType>(std::addressof(*begin), end - begin);
714}
715
716
717
727template <typename ElementType, typename MemorySpaceType = MemorySpace::Host>
730{
731 Assert(begin <= end,
733 "The beginning of the array view should be before the end."));
735}
736
737
738
749template <typename Number, typename MemorySpaceType>
752{
753 return make_array_view(array_view.cbegin(), array_view.cend());
754}
755
756
757
768template <typename Number, typename MemorySpaceType>
771{
772 return make_array_view(array_view.begin(), array_view.end());
773}
774
775
776
798template <int rank, int dim, typename Number>
799DEAL_II_DEPRECATED_EARLY inline ArrayView<const Number>
801{
802 return make_array_view(tensor.begin_raw(), tensor.end_raw());
803}
804
805
806
828template <int rank, int dim, typename Number>
829DEAL_II_DEPRECATED_EARLY inline ArrayView<Number>
831{
832 return make_array_view(tensor.begin_raw(), tensor.end_raw());
833}
834
835
836
858template <int rank, int dim, typename Number>
859DEAL_II_DEPRECATED_EARLY inline ArrayView<const Number>
861{
862 return make_array_view(tensor.begin_raw(), tensor.end_raw());
863}
864
865
866
889template <int rank, int dim, typename Number>
890DEAL_II_DEPRECATED_EARLY inline ArrayView<Number>
892{
893 return make_array_view(tensor.begin_raw(), tensor.end_raw());
894}
895
896
897
911template <typename ElementType, int N>
913{
914 return ArrayView<ElementType>(array, N);
915}
916
917
918
933template <typename ElementType>
936{
937 return ArrayView<ElementType>(vector.begin(), vector.size());
938}
939
940
941
956template <typename ElementType>
959{
960 return ArrayView<const ElementType>(vector.begin(), vector.size());
961}
962
963
964
979template <typename ElementType>
981make_array_view(std::vector<ElementType> &vector)
982{
983 return ArrayView<ElementType>(vector.data(), vector.size());
984}
985
986
987
1002template <typename ElementType>
1004make_array_view(const std::vector<ElementType> &vector)
1005{
1006 return ArrayView<const ElementType>(vector.data(), vector.size());
1007}
1008
1009
1010
1030template <typename ElementType>
1032make_array_view(std::vector<ElementType> &vector,
1033 const std::size_t starting_index,
1034 const std::size_t size_of_view)
1035{
1036 Assert(starting_index + size_of_view <= vector.size(),
1037 ExcMessage("The starting index and size of the view you want to "
1038 "create would lead to a view that extends beyond the end "
1039 "of the given vector."));
1040 return ArrayView<ElementType>(&vector[starting_index], size_of_view);
1041}
1042
1043
1044
1064template <typename ElementType>
1066make_array_view(const std::vector<ElementType> &vector,
1067 const std::size_t starting_index,
1068 const std::size_t size_of_view)
1069{
1070 Assert(starting_index + size_of_view <= vector.size(),
1071 ExcMessage("The starting index and size of the view you want to "
1072 "create would lead to a view that extends beyond the end "
1073 "of the given vector."));
1074 return ArrayView<const ElementType>(&vector[starting_index], size_of_view);
1075}
1076
1077
1078
1095template <typename ElementType>
1098 const typename Table<2, ElementType>::size_type row)
1099{
1100 AssertIndexRange(row, table.size()[0]);
1101 return ArrayView<ElementType>(&table[row][0], table.size()[1]);
1102}
1103
1104
1105
1122template <typename ElementType>
1125{
1126 return ArrayView<ElementType>(&table[0][0], table.n_elements());
1127}
1128
1129
1130
1147template <typename ElementType>
1150{
1151 return ArrayView<const ElementType>(&table[0][0], table.n_elements());
1152}
1153
1154
1172template <typename ElementType>
1175{
1176 return ArrayView<ElementType>(&matrix(0, 0), matrix.n_elements());
1177}
1178
1179
1180
1197template <typename ElementType>
1200{
1201 return ArrayView<const ElementType>(&matrix(0, 0), matrix.n_elements());
1202}
1203
1204
1205
1222template <typename ElementType>
1225 const typename Table<2, ElementType>::size_type row)
1226{
1227 AssertIndexRange(row, table.size()[0]);
1228 return ArrayView<const ElementType>(&table[row][0], table.size()[1]);
1229}
1230
1231
1232
1252template <typename ElementType>
1255 const typename Table<2, ElementType>::size_type row,
1256 const typename Table<2, ElementType>::size_type starting_column,
1257 const std::size_t size_of_view)
1258{
1259 AssertIndexRange(row, table.size()[0]);
1260 AssertIndexRange(starting_column, table.size()[1]);
1261 Assert(starting_column + size_of_view <= table.size()[1],
1262 ExcMessage("The starting index and size of the view you want to "
1263 "create would lead to a view that extends beyond the end "
1264 "of a column of the given table."));
1265 return ArrayView<ElementType>(&table[row][starting_column], size_of_view);
1266}
1267
1268
1269
1289template <typename ElementType>
1292 const typename Table<2, ElementType>::size_type row,
1293 const typename Table<2, ElementType>::size_type starting_column,
1294 const std::size_t size_of_view)
1295{
1296 AssertIndexRange(row, table.size()[0]);
1297 AssertIndexRange(starting_column, table.size()[1]);
1298 Assert(starting_column + size_of_view <= table.size()[1],
1299 ExcMessage("The starting index and size of the view you want to "
1300 "create would lead to a view that extends beyond the end "
1301 "of a column of the given table."));
1302 return ArrayView<const ElementType>(&table[row][starting_column],
1303 size_of_view);
1304}
1305
1306
1307
1308/*
1309 * Create a view that doesn't allow the container it points to to be modified.
1310 * This is useful if the object passed in is not `const` already and a function
1311 * requires a view to constant memory in its signature.
1312 *
1313 * This function returns an object of type `ArrayView<const T>` where `T` is the
1314 * element type of the container.
1315 *
1316 * @relatesalso ArrayView
1317 */
1318template <typename Container>
1319inline auto
1320make_const_array_view(const Container &container)
1321 -> decltype(make_array_view(container))
1322{
1323 return make_array_view(container);
1324}
1325
1326
1328
1329#endif
auto make_const_array_view(const Container &container) -> decltype(make_array_view(container))
Definition: array_view.h:1320
ArrayView< const ElementType > make_array_view(const Vector< ElementType > &vector)
Definition: array_view.h:958
ArrayView(value_type &element)
Definition: array_view.h:424
iterator begin() const
Definition: array_view.h:585
ArrayView(const ArrayView< typename std::remove_cv< value_type >::type, MemorySpaceType > &view)
Definition: array_view.h:432
ArrayView< Number, MemorySpaceType > make_array_view(ArrayView< Number, MemorySpaceType > &array_view)
Definition: array_view.h:770
ArrayView< typename std::remove_reference< typename std::iterator_traits< Iterator >::reference >::type, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
Definition: array_view.h:699
value_type * iterator
Definition: array_view.h:93
ArrayView< Number > make_array_view(SymmetricTensor< rank, dim, Number > &tensor)
Definition: array_view.h:891
value_type & operator[](const std::size_t i) const
Definition: array_view.h:621
ArrayView< const ElementType > make_array_view(const LAPACKFullMatrix< ElementType > &matrix)
Definition: array_view.h:1199
ArrayView< const Number > make_array_view(const Tensor< rank, dim, Number > &tensor)
Definition: array_view.h:800
ArrayView< const Number > make_array_view(const SymmetricTensor< rank, dim, Number > &tensor)
Definition: array_view.h:860
ArrayView< ElementType > make_array_view(LAPACKFullMatrix< ElementType > &matrix)
Definition: array_view.h:1174
ArrayView< ElementType > make_array_view(ElementType(&array)[N])
Definition: array_view.h:912
ArrayView< ElementType, MemorySpaceType > make_array_view(ElementType *const begin, ElementType *const end)
Definition: array_view.h:729
bool operator!=(const ArrayView< typename std::remove_cv< value_type >::type, MemorySpaceType > &other_view) const
Definition: array_view.h:565
const_iterator cend() const
Definition: array_view.h:612
iterator end() const
Definition: array_view.h:594
ArrayView< const ElementType > make_array_view(const std::vector< ElementType > &vector, const std::size_t starting_index, const std::size_t size_of_view)
Definition: array_view.h:1066
ArrayView< const ElementType > make_array_view(const Table< 2, ElementType > &table)
Definition: array_view.h:1149
ArrayView< const ElementType > make_array_view(const Table< 2, ElementType > &table, const typename Table< 2, ElementType >::size_type row, const typename Table< 2, ElementType >::size_type starting_column, const std::size_t size_of_view)
Definition: array_view.h:1291
ArrayView(const std::array< typename std::remove_cv< value_type >::type, N > &vector)
Definition: array_view.h:476
ArrayView< ElementType > make_array_view(std::vector< ElementType > &vector)
Definition: array_view.h:981
ArrayView(std::vector< typename std::remove_cv< value_type >::type > &vector)
Definition: array_view.h:466
bool operator==(const ArrayView< const value_type, MemorySpaceType > &other_view) const
Definition: array_view.h:520
ArrayView< ElementType > make_array_view(std::vector< ElementType > &vector, const std::size_t starting_index, const std::size_t size_of_view)
Definition: array_view.h:1032
bool operator!=(const ArrayView< const value_type, MemorySpaceType > &other_view) const
Definition: array_view.h:543
const_iterator cbegin() const
Definition: array_view.h:603
ArrayView(const std::vector< typename std::remove_cv< value_type >::type > &vector)
Definition: array_view.h:442
ArrayView(value_type(&array)[N])
Definition: array_view.h:501
ArrayView< Number > make_array_view(Tensor< rank, dim, Number > &tensor)
Definition: array_view.h:830
value_type * data() const noexcept
Definition: array_view.h:553
ArrayView< ElementType > make_array_view(Table< 2, ElementType > &table, const typename Table< 2, ElementType >::size_type row, const typename Table< 2, ElementType >::size_type starting_column, const std::size_t size_of_view)
Definition: array_view.h:1254
void reinit(value_type *starting_element, const std::size_t n_elements)
Definition: array_view.h:414
ArrayView< ElementType > make_array_view(Table< 2, ElementType > &table)
Definition: array_view.h:1124
value_type * starting_element
Definition: array_view.h:333
std::size_t size() const
Definition: array_view.h:576
bool operator==(const ArrayView< typename std::remove_cv< value_type >::type, MemorySpaceType > &other_view) const
Definition: array_view.h:531
ElementType value_type
Definition: array_view.h:88
ArrayView(value_type *starting_element, const std::size_t n_elements)
Definition: array_view.h:396
std::size_t n_elements
Definition: array_view.h:338
ArrayView< const Number, MemorySpaceType > make_array_view(const ArrayView< Number, MemorySpaceType > &array_view)
Definition: array_view.h:751
ArrayView< const ElementType > make_array_view(const Table< 2, ElementType > &table, const typename Table< 2, ElementType >::size_type row)
Definition: array_view.h:1224
const ElementType * const_iterator
Definition: array_view.h:98
ArrayView< ElementType > make_array_view(Vector< ElementType > &vector)
Definition: array_view.h:935
ArrayView< ElementType > make_array_view(Table< 2, ElementType > &table, const typename Table< 2, ElementType >::size_type row)
Definition: array_view.h:1097
ArrayView< const ElementType > make_array_view(const std::vector< ElementType > &vector)
Definition: array_view.h:1004
ArrayView(std::array< typename std::remove_cv< value_type >::type, N > &vector)
Definition: array_view.h:510
Number * begin_raw()
Number * end_raw()
Definition: tensor.h:503
Number * begin_raw()
Number * end_raw()
Definition: vector.h:109
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:442
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:443
Point< 2 > first
Definition: grid_out.cc:4603
#define Assert(cond, exc)
Definition: exceptions.h:1473
#define AssertIndexRange(index, range)
Definition: exceptions.h:1732
#define AssertCuda(error_code)
Definition: exceptions.h:1816
static ::ExceptionBase & ExcMessage(std::string arg1)
size_type size() const
iterator begin()
@ matrix
Contents is actually a matrix.
static const char T
static const char N
VectorType::value_type * end(VectorType &V)
VectorType::value_type * begin(VectorType &V)
bool is_in_correct_memory_space(const void *const ptr)
Definition: array_view.h:354
STL namespace.