Reference documentation for deal.II version Git 8668eb52a3 2020-04-08 14:09:01 +0200
\(\newcommand{\vcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\vcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
array_view.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2004 - 2019 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 
21 #include <deal.II/base/exceptions.h>
22 #include <deal.II/base/memory_space.h>
24 #include <deal.II/base/table.h>
25 #include <deal.II/base/tensor.h>
26 
27 #include <deal.II/lac/lapack_full_matrix.h>
28 
29 #include <type_traits>
30 #include <vector>
31 
32 DEAL_II_NAMESPACE_OPEN
33 
34 
76 template <typename ElementType, typename MemorySpaceType = MemorySpace::Host>
77 class ArrayView
78 {
79 public:
85 
89  using iterator = value_type *;
90 
94  using const_iterator = const ElementType *;
95 
99  ArrayView();
100 
120  ArrayView(value_type *starting_element, const std::size_t n_elements);
121 
131  ArrayView(const ArrayView<typename std::remove_cv<value_type>::type,
132  MemorySpaceType> &view);
133 
137  explicit ArrayView(value_type &element);
138 
153  ArrayView(
154  const std::vector<typename std::remove_cv<value_type>::type> &vector);
155 
170  ArrayView(std::vector<typename std::remove_cv<value_type>::type> &vector);
171 
191  void
192  reinit(value_type *starting_element, const std::size_t n_elements);
193 
199  bool
200  operator==(
201  const ArrayView<const value_type, MemorySpaceType> &other_view) const;
202 
208  bool
209  operator==(const ArrayView<typename std::remove_cv<value_type>::type,
210  MemorySpaceType> &other_view) const;
211 
217  bool
218  operator!=(
219  const ArrayView<const value_type, MemorySpaceType> &other_view) const;
220 
226  bool
227  operator!=(const ArrayView<typename std::remove_cv<value_type>::type,
228  MemorySpaceType> &other_view) const;
229 
234  std::size_t
235  size() const;
236 
241  value_type *
242  data() const noexcept;
243 
247  iterator
248  begin() const;
249 
253  iterator
254  end() const;
255 
260  cbegin() const;
261 
266  cend() const;
267 
280  value_type &operator[](const std::size_t i) const;
281 
282 private:
288 
292  std::size_t n_elements;
293 
294  friend class ArrayView<const ElementType, MemorySpaceType>;
295 };
296 
297 
298 
299 //---------------------------------------------------------------------------
300 
301 
302 namespace internal
303 {
304  namespace ArrayViewHelper
305  {
306  template <typename MemorySpaceType>
307  inline bool
308  is_in_correct_memory_space(const void *const ptr)
309  {
310 #ifndef DEAL_II_COMPILER_CUDA_AWARE
311  (void)ptr;
312  static_assert(std::is_same<MemorySpaceType, MemorySpace::Host>::value,
313  "If the compiler doesn't understand CUDA code, "
314  "the only possible memory space is 'MemorySpace::Host'!");
315  return true;
316 #else
317  cudaPointerAttributes attributes;
318  const cudaError_t cuda_error = cudaPointerGetAttributes(&attributes, ptr);
319  if (cuda_error != cudaErrorInvalidValue)
320  {
321  AssertCuda(cuda_error);
322  if (std::is_same<MemorySpaceType, MemorySpace::Host>::value)
323  return attributes.memoryType == cudaMemoryTypeHost;
324  else
325  return attributes.memoryType == cudaMemoryTypeDevice;
326  }
327  else
328  {
329  // ignore and reset the error since host pointers produce an error
330  cudaGetLastError();
331  return std::is_same<MemorySpaceType, MemorySpace::Host>::value;
332  }
333 #endif
334  }
335  } // namespace ArrayViewHelper
336 } // namespace internal
337 
338 
339 
340 template <typename ElementType, typename MemorySpaceType>
342  : starting_element(nullptr)
343  , n_elements(0)
344 {}
345 
346 
347 
348 template <typename ElementType, typename MemorySpaceType>
351  const std::size_t n_elements)
352  : starting_element(starting_element)
353  , n_elements(n_elements)
354 {
355  Assert(
356  n_elements == 0 ||
357  internal::ArrayViewHelper::is_in_correct_memory_space<MemorySpaceType>(
358  starting_element),
359  ExcMessage("The memory space indicated by the template parameter "
360  "and the one derived from the pointer value do not match!"));
361 }
362 
363 
364 
365 template <typename ElementType, typename MemorySpaceType>
366 inline void
368  const std::size_t n_elements)
369 {
370  *this = ArrayView(starting_element, n_elements);
371 }
372 
373 
374 
375 template <typename ElementType, typename MemorySpaceType>
377  : starting_element(&element)
378  , n_elements(1)
379 {}
380 
381 
382 
383 template <typename ElementType, typename MemorySpaceType>
385  const ArrayView<typename std::remove_cv<value_type>::type, MemorySpaceType>
386  &view)
388  , n_elements(view.n_elements)
389 {}
390 
391 
392 
393 template <typename ElementType, typename MemorySpaceType>
395  const std::vector<typename std::remove_cv<value_type>::type> &vector)
396  : // use delegating constructor
397  ArrayView(vector.data(), vector.size())
398 {
399  // the following static_assert is not strictly necessary because,
400  // if we got a const std::vector reference argument but ElementType
401  // is not itself const, then the call to the forwarding constructor
402  // above will already have failed: vector.data() will have returned
403  // a const pointer, but we need a non-const pointer.
404  //
405  // nevertheless, leave the static_assert in since it provides a
406  // more descriptive error message that will simply come after the first
407  // error produced above
408  static_assert(std::is_const<value_type>::value == true,
409  "This constructor may only be called if the ArrayView "
410  "object has a const value_type. In other words, you can "
411  "only create an ArrayView to const values from a const "
412  "std::vector.");
413 }
414 
415 
416 
417 template <typename ElementType, typename MemorySpaceType>
419  std::vector<typename std::remove_cv<value_type>::type> &vector)
420  : // use delegating constructor
421  ArrayView(vector.data(), vector.size())
422 {}
423 
424 
425 
426 template <typename ElementType, typename MemorySpaceType>
427 inline bool
430 {
431  return (other_view.data() == starting_element) &&
432  (other_view.size() == n_elements);
433 }
434 
435 
436 
437 template <typename ElementType, typename MemorySpaceType>
438 inline bool
440 operator==(const ArrayView<typename std::remove_cv<value_type>::type,
441  MemorySpaceType> &other_view) const
442 {
443  return (other_view.data() == starting_element) &&
444  (other_view.size() == n_elements);
445 }
446 
447 
448 
449 template <typename ElementType, typename MemorySpaceType>
450 inline bool
453 {
454  return !(*this == other_view);
455 }
456 
457 
458 
459 template <typename ElementType, typename MemorySpaceType>
462 {
463  if (n_elements == 0)
464  return nullptr;
465  else
466  return starting_element;
467 }
468 
469 
470 
471 template <typename ElementType, typename MemorySpaceType>
472 inline bool
474 operator!=(const ArrayView<typename std::remove_cv<value_type>::type,
475  MemorySpaceType> &other_view) const
476 {
477  return !(*this == other_view);
478 }
479 
480 
481 
482 template <typename ElementType, typename MemorySpaceType>
483 inline std::size_t
485 {
486  return n_elements;
487 }
488 
489 
490 
491 template <typename ElementType, typename MemorySpaceType>
494 {
495  return starting_element;
496 }
497 
498 
499 
500 template <typename ElementType, typename MemorySpaceType>
503 {
504  return starting_element + n_elements;
505 }
506 
507 
508 
509 template <typename ElementType, typename MemorySpaceType>
512 {
513  return starting_element;
514 }
515 
516 
517 
518 template <typename ElementType, typename MemorySpaceType>
521 {
522  return starting_element + n_elements;
523 }
524 
525 
526 
527 template <typename ElementType, typename MemorySpaceType>
530 {
532  Assert(
533  (std::is_same<MemorySpaceType, MemorySpace::Host>::value),
534  ExcMessage(
535  "Accessing elements is only allowed if the data is stored in CPU memory!"));
536 
537  return *(starting_element + i);
538 }
539 
540 
541 
542 #ifndef DOXYGEN
543 namespace internal
544 {
545  namespace ArrayViewHelper
546  {
552  template <class Iterator>
553  bool
554  is_contiguous(const Iterator &first, const Iterator &last)
555  {
556  const auto n = std::distance(first, last);
557  for (typename std::decay<decltype(n)>::type i = 0; i < n; ++i)
558  if (std::addressof(*(std::next(first, i))) !=
559  std::next(std::addressof(*first), i))
560  return false;
561  return true;
562  }
563 
564 
575  template <class T>
576  constexpr bool
577  is_contiguous(T *, T *)
578  {
579  return true;
580  }
581  } // namespace ArrayViewHelper
582 } // namespace internal
583 #endif
584 
585 
586 
603 template <typename Iterator, typename MemorySpaceType = MemorySpace::Host>
604 ArrayView<typename std::remove_reference<
605  typename std::iterator_traits<Iterator>::reference>::type,
606  MemorySpaceType>
607 make_array_view(const Iterator begin, const Iterator end)
608 {
609  static_assert(
610  std::is_same<typename std::iterator_traits<Iterator>::iterator_category,
611  typename std::random_access_iterator_tag>::value,
612  "The provided iterator should be a random access iterator.");
613  Assert(begin <= end,
614  ExcMessage(
615  "The beginning of the array view should be before the end."));
616  Assert(internal::ArrayViewHelper::is_contiguous(begin, end),
617  ExcMessage("The provided range isn't contiguous in memory!"));
618  // the reference type, not the value type, knows the constness of the iterator
619  return ArrayView<typename std::remove_reference<
620  typename std::iterator_traits<Iterator>::reference>::type,
621  MemorySpaceType>(std::addressof(*begin), end - begin);
622 }
623 
624 
625 
635 template <typename ElementType, typename MemorySpaceType = MemorySpace::Host>
638 {
639  Assert(begin <= end,
640  ExcMessage(
641  "The beginning of the array view should be before the end."));
643 }
644 
645 
646 
657 template <typename Number, typename MemorySpaceType>
660 {
661  return make_array_view(array_view.cbegin(), array_view.cend());
662 }
663 
664 
665 
676 template <typename Number, typename MemorySpaceType>
679 {
680  return make_array_view(array_view.begin(), array_view.end());
681 }
682 
683 
684 
701 template <int rank, int dim, typename Number>
704 {
705  return make_array_view(tensor.begin_raw(), tensor.end_raw());
706 }
707 
708 
709 
726 template <int rank, int dim, typename Number>
727 inline ArrayView<Number>
729 {
730  return make_array_view(tensor.begin_raw(), tensor.end_raw());
731 }
732 
733 
734 
751 template <int rank, int dim, typename Number>
754 {
755  return make_array_view(tensor.begin_raw(), tensor.end_raw());
756 }
757 
758 
759 
777 template <int rank, int dim, typename Number>
778 inline ArrayView<Number>
780 {
781  return make_array_view(tensor.begin_raw(), tensor.end_raw());
782 }
783 
784 
785 
799 template <typename ElementType, int N>
801 {
802  return ArrayView<ElementType>(array, N);
803 }
804 
805 
806 
821 template <typename ElementType>
823 make_array_view(Vector<ElementType> &vector)
824 {
825  return ArrayView<ElementType>(vector.begin(), vector.size());
826 }
827 
828 
829 
844 template <typename ElementType>
846 make_array_view(const Vector<ElementType> &vector)
847 {
848  return ArrayView<const ElementType>(vector.begin(), vector.size());
849 }
850 
851 
852 
867 template <typename ElementType>
869 make_array_view(std::vector<ElementType> &vector)
870 {
871  return ArrayView<ElementType>(vector.data(), vector.size());
872 }
873 
874 
875 
890 template <typename ElementType>
892 make_array_view(const std::vector<ElementType> &vector)
893 {
894  return ArrayView<const ElementType>(vector.data(), vector.size());
895 }
896 
897 
898 
918 template <typename ElementType>
920 make_array_view(std::vector<ElementType> &vector,
921  const std::size_t starting_index,
922  const std::size_t size_of_view)
923 {
924  Assert(starting_index + size_of_view <= vector.size(),
925  ExcMessage("The starting index and size of the view you want to "
926  "create would lead to a view that extends beyond the end "
927  "of the given vector."));
928  return ArrayView<ElementType>(&vector[starting_index], size_of_view);
929 }
930 
931 
932 
952 template <typename ElementType>
954 make_array_view(const std::vector<ElementType> &vector,
955  const std::size_t starting_index,
956  const std::size_t size_of_view)
957 {
958  Assert(starting_index + size_of_view <= vector.size(),
959  ExcMessage("The starting index and size of the view you want to "
960  "create would lead to a view that extends beyond the end "
961  "of the given vector."));
962  return ArrayView<const ElementType>(&vector[starting_index], size_of_view);
963 }
964 
965 
966 
983 template <typename ElementType>
986  const typename Table<2, ElementType>::size_type row)
987 {
988  AssertIndexRange(row, table.size()[0]);
989  return ArrayView<ElementType>(&table[row][0], table.size()[1]);
990 }
991 
992 
993 
1010 template <typename ElementType>
1012 {
1013  return ArrayView<ElementType>(&table[0][0], table.n_elements());
1014 }
1015 
1016 
1017 
1034 template <typename ElementType>
1037 {
1038  return ArrayView<const ElementType>(&table[0][0], table.n_elements());
1039 }
1040 
1041 
1059 template <typename ElementType>
1062 {
1063  return ArrayView<ElementType>(&matrix(0, 0), matrix.n_elements());
1064 }
1065 
1066 
1067 
1084 template <typename ElementType>
1087 {
1088  return ArrayView<const ElementType>(&matrix(0, 0), matrix.n_elements());
1089 }
1090 
1091 
1092 
1109 template <typename ElementType>
1112  const typename Table<2, ElementType>::size_type row)
1113 {
1114  AssertIndexRange(row, table.size()[0]);
1115  return ArrayView<const ElementType>(&table[row][0], table.size()[1]);
1116 }
1117 
1118 
1119 
1139 template <typename ElementType>
1141  Table<2, ElementType> & table,
1142  const typename Table<2, ElementType>::size_type row,
1143  const typename Table<2, ElementType>::size_type starting_column,
1144  const std::size_t size_of_view)
1145 {
1146  AssertIndexRange(row, table.size()[0]);
1147  AssertIndexRange(starting_column, table.size()[1]);
1148  Assert(starting_column + size_of_view <= table.size()[1],
1149  ExcMessage("The starting index and size of the view you want to "
1150  "create would lead to a view that extends beyond the end "
1151  "of a column of the given table."));
1152  return ArrayView<ElementType>(&table[row][starting_column], size_of_view);
1153 }
1154 
1155 
1156 
1176 template <typename ElementType>
1179  const typename Table<2, ElementType>::size_type row,
1180  const typename Table<2, ElementType>::size_type starting_column,
1181  const std::size_t size_of_view)
1182 {
1183  AssertIndexRange(row, table.size()[0]);
1184  AssertIndexRange(starting_column, table.size()[1]);
1185  Assert(starting_column + size_of_view <= table.size()[1],
1186  ExcMessage("The starting index and size of the view you want to "
1187  "create would lead to a view that extends beyond the end "
1188  "of a column of the given table."));
1189  return ArrayView<const ElementType>(&table[row][starting_column],
1190  size_of_view);
1191 }
1192 
1193 
1194 
1195 /*
1196  * Create a view that doesn't allow the container it points to to be modified.
1197  * This is useful if the object passed in is not `const` already and a function
1198  * requires a view to constant memory in its signature.
1199  *
1200  * This function returns an object of type `ArrayView<const T>` where `T` is the
1201  * element type of the container.
1202  *
1203  * @relatesalso ArrayView
1204  */
1205 template <typename Container>
1206 inline auto
1207 make_const_array_view(const Container &container)
1208  -> decltype(make_array_view(container))
1209 {
1210  return make_array_view(container);
1211 }
1212 
1213 
1214 DEAL_II_NAMESPACE_CLOSE
1215 
1216 #endif
ArrayView< ElementType > make_array_view(LAPACKFullMatrix< ElementType > &matrix)
Definition: array_view.h:1061
ArrayView< const ElementType > make_array_view(const LAPACKFullMatrix< ElementType > &matrix)
Definition: array_view.h:1086
ArrayView< Number, MemorySpaceType > make_array_view(ArrayView< Number, MemorySpaceType > &array_view)
Definition: array_view.h:678
ArrayView< const Number, MemorySpaceType > make_array_view(const ArrayView< Number, MemorySpaceType > &array_view)
Definition: array_view.h:659
ArrayView< ElementType > make_array_view(ElementType(&array)[N])
Definition: array_view.h:800
const_iterator cbegin() const
Definition: array_view.h:511
ArrayView< const Number > make_array_view(const Tensor< rank, dim, Number > &tensor)
Definition: array_view.h:703
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:920
iterator end() const
Definition: array_view.h:502
#define AssertIndexRange(index, range)
Definition: exceptions.h:1649
STL namespace.
size_type n_elements() const
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:1178
bool operator==(const ArrayView< const value_type, MemorySpaceType > &other_view) const
Definition: array_view.h:429
std::size_t size() const
Definition: array_view.h:484
std::size_t n_elements
Definition: array_view.h:292
const std::conditional< std::is_const< VectorType >::value, const VectorType::value_type, VectorType::value_type >::type * const_iterator
Definition: array_view.h:94
ArrayView< Number > make_array_view(SymmetricTensor< rank, dim, Number > &tensor)
Definition: array_view.h:779
ArrayView< ElementType > make_array_view(Vector< ElementType > &vector)
Definition: array_view.h:823
static ::ExceptionBase & ExcMessage(std::string arg1)
value_type & operator[](const std::size_t i) const
Definition: array_view.h:529
void reinit(value_type *starting_element, const std::size_t n_elements)
Definition: array_view.h:367
Number * begin_raw()
std::conditional< std::is_const< VectorType >::value, const VectorType::value_type, VectorType::value_type >::type value_type
Definition: array_view.h:84
#define Assert(cond, exc)
Definition: exceptions.h:1419
#define AssertCuda(error_code)
Definition: exceptions.h:1734
Number * end_raw()
Definition: tensor.h:1252
Number * end_raw()
ArrayView< ElementType > make_array_view(Table< 2, ElementType > &table, const typename Table< 2, ElementType >::size_type row)
Definition: array_view.h:985
value_type * data() const noexcept
Definition: array_view.h:461
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:954
bool operator!=(const ArrayView< const value_type, MemorySpaceType > &other_view) const
Definition: array_view.h:452
ArrayView< const Number > make_array_view(const SymmetricTensor< rank, dim, Number > &tensor)
Definition: array_view.h:753
size_type size(const unsigned int i) const
ArrayView< const ElementType > make_array_view(const Vector< ElementType > &vector)
Definition: array_view.h:846
ArrayView< ElementType > make_array_view(std::vector< ElementType > &vector)
Definition: array_view.h:869
typename AlignedVector< T >::size_type size_type
Definition: table.h:420
ArrayView< const ElementType > make_array_view(const Table< 2, ElementType > &table, const typename Table< 2, ElementType >::size_type row)
Definition: array_view.h:1111
ArrayView< ElementType, MemorySpaceType > make_array_view(ElementType *const begin, ElementType *const end)
Definition: array_view.h:637
Number * begin_raw()
Definition: tensor.h:1232
value_type * starting_element
Definition: array_view.h:287
Definition: table.h:699
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:607
iterator begin() const
Definition: array_view.h:493
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:1140
ArrayView< Number > make_array_view(Tensor< rank, dim, Number > &tensor)
Definition: array_view.h:728
const_iterator cend() const
Definition: array_view.h:520
ArrayView< const ElementType > make_array_view(const std::vector< ElementType > &vector)
Definition: array_view.h:892
ArrayView< const ElementType > make_array_view(const Table< 2, ElementType > &table)
Definition: array_view.h:1036
ArrayView< ElementType > make_array_view(Table< 2, ElementType > &table)
Definition: array_view.h:1011