GEOSX
CRSMatrixView.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020, Lawrence Livermore National Security, LLC and LvArray contributors.
3  * All rights reserved.
4  * See the LICENSE file for details.
5  * SPDX-License-Identifier: (BSD-3-Clause)
6  */
7 
13 #pragma once
14 
15 #include "SparsityPatternView.hpp"
16 #include "arrayManipulation.hpp"
17 #include "ArraySlice.hpp"
18 
19 namespace LvArray
20 {
21 
22 namespace internal
23 {
24 
32 template< typename POLICY, typename T >
34 void atomicAdd( POLICY, T * const acc, T const & val )
35 { RAJA::atomicAdd< POLICY >( acc, val ); }
36 
46 template< typename T >
47 LVARRAY_HOST_DEVICE constexpr inline
48 void atomicAdd( RAJA::seq_atomic, T * acc, T const & val )
49 { *acc += val; }
50 
51 } // namespace internal
52 
68 template< typename T,
69  typename COL_TYPE,
70  typename INDEX_TYPE,
71  template< typename > class BUFFER_TYPE
72  >
73 class CRSMatrixView : protected SparsityPatternView< COL_TYPE, INDEX_TYPE, BUFFER_TYPE >
74 {
75 
78 
80  using typename ParentClass::INDEX_TYPE_NC;
81 
82  using typename ParentClass::SIZE_TYPE;
83 
84 public:
85  static_assert( !std::is_const< T >::value ||
86  (std::is_const< COL_TYPE >::value && std::is_const< INDEX_TYPE >::value),
87  "When T is const COL_TYPE and INDEX_TYPE must also be const." );
88 
90  using EntryType = T;
91  using typename ParentClass::ColType;
92  using typename ParentClass::IndexType;
93 
97 
103  CRSMatrixView() = default;
104 
108  CRSMatrixView( CRSMatrixView const & ) = default;
109 
113  inline
114  CRSMatrixView( CRSMatrixView && ) = default;
115 
125  LVARRAY_HOST_DEVICE constexpr inline
126  CRSMatrixView( INDEX_TYPE const nRows,
127  INDEX_TYPE const nCols,
128  BUFFER_TYPE< INDEX_TYPE > const & offsets,
129  BUFFER_TYPE< SIZE_TYPE > const & nnz,
130  BUFFER_TYPE< COL_TYPE > const & columns,
131  BUFFER_TYPE< T > const & entries ):
132  ParentClass( nRows, nCols, offsets, nnz, columns ),
133  m_entries( entries )
134  {}
135 
140  inline
141  CRSMatrixView & operator=( CRSMatrixView const & ) = default;
142 
147  inline
148  CRSMatrixView & operator=( CRSMatrixView && ) = default;
149 
153 
158  LVARRAY_HOST_DEVICE constexpr inline
160  toView() const
161  {
163  numColumns(),
164  this->m_offsets,
165  this->m_sizes,
166  this->m_values,
167  this->m_entries );
168  }
169 
173  LVARRAY_HOST_DEVICE constexpr inline
176  {
178  numColumns(),
179  this->m_offsets,
180  this->m_sizes,
181  this->m_values,
182  this->m_entries );
183  }
184 
188  LVARRAY_HOST_DEVICE constexpr inline
190  toViewConst() const
191  {
193  numColumns(),
194  this->m_offsets,
195  this->m_sizes,
196  this->m_values,
197  this->m_entries );
198  }
199 
203  LVARRAY_HOST_DEVICE constexpr inline
206  {
208  numColumns(),
209  this->m_offsets,
210  this->m_sizes,
211  this->m_values );
212  }
213 
215 
219 
221  using ParentClass::numRows;
222  using ParentClass::numColumns;
223  using ParentClass::numNonZeros;
224  using ParentClass::nonZeroCapacity;
225  using ParentClass::empty;
226 
228 
232 
238  LVARRAY_HOST_DEVICE inline
239  ArraySlice< T, 1, 0, INDEX_TYPE_NC > getEntries( INDEX_TYPE const row ) const
240  {
242  return ArraySlice< T, 1, 0, INDEX_TYPE_NC >( m_entries.data() + this->m_offsets[ row ],
243  &this->m_sizes[ row ],
244  nullptr );
245  }
246 
247  using ParentClass::getColumns;
248  using ParentClass::getOffsets;
249 
251 
255 
266  LVARRAY_HOST_DEVICE inline
267  bool insertNonZero( INDEX_TYPE const row, COL_TYPE const col, T const & entry ) const
268  { return ParentClass::insertIntoSetImpl( row, col, CallBacks( *this, row, &entry ) ); }
269 
281  LVARRAY_HOST_DEVICE inline
282  INDEX_TYPE_NC insertNonZeros( INDEX_TYPE const row,
283  COL_TYPE const * const LVARRAY_RESTRICT cols,
284  T const * const LVARRAY_RESTRICT entriesToInsert,
285  INDEX_TYPE const ncols ) const
286  { return ParentClass::insertIntoSetImpl( row, cols, cols + ncols, CallBacks( *this, row, entriesToInsert ) ); }
287 
294  LVARRAY_HOST_DEVICE inline
295  bool removeNonZero( INDEX_TYPE const row, COL_TYPE const col ) const
296  { return ParentClass::removeFromSetImpl( row, col, CallBacks( *this, row, nullptr )); }
297 
307  LVARRAY_HOST_DEVICE inline
308  INDEX_TYPE_NC removeNonZeros( INDEX_TYPE const row,
309  COL_TYPE const * const LVARRAY_RESTRICT cols,
310  INDEX_TYPE const ncols ) const
311  {
312  T * const entries = getEntries( row );
313  INDEX_TYPE const rowNNZ = numNonZeros( row );
314  INDEX_TYPE const nRemoved = ParentClass::removeFromSetImpl( row, cols, cols + ncols, CallBacks( *this, row, nullptr ) );
315 
316  arrayManipulation::destroy( entries + rowNNZ - nRemoved, nRemoved );
317 
318  return nRemoved;
319  }
320 
322 
326 
333  template< typename POLICY >
334  inline
335  void setValues( T const & value ) const
336  {
338  RAJA::forall< POLICY >( RAJA::TypedRangeSegment< INDEX_TYPE >( 0, numRows() ),
339  [view, value] LVARRAY_HOST_DEVICE ( INDEX_TYPE const row )
340  {
341  INDEX_TYPE const nnz = view.numNonZeros( row );
342  ArraySlice< T, 1, 0, INDEX_TYPE_NC > const entries = view.getEntries( row );
343 
344  for( INDEX_TYPE_NC i = 0; i < nnz; ++i )
345  { entries[ i ] = value; }
346  } );
347  }
348 
361  template< typename AtomicPolicy >
362  LVARRAY_HOST_DEVICE inline
363  void addToRow( INDEX_TYPE const row,
364  COL_TYPE const * const LVARRAY_RESTRICT cols,
365  T const * const LVARRAY_RESTRICT vals,
366  INDEX_TYPE const nCols ) const
367  {
368  INDEX_TYPE const nnz = numNonZeros( row );
369  if( nCols < nnz / 4 && nnz > 64 )
370  {
371  addToRowBinarySearch< AtomicPolicy >( row, cols, vals, nCols );
372  }
373  else
374  {
375  addToRowLinearSearch< AtomicPolicy >( row, cols, vals, nCols );
376  }
377  }
378 
391  template< typename AtomicPolicy >
392  LVARRAY_HOST_DEVICE inline
393  void addToRowBinarySearch( INDEX_TYPE const row,
394  COL_TYPE const * const LVARRAY_RESTRICT cols,
395  T const * const LVARRAY_RESTRICT vals,
396  INDEX_TYPE const nCols ) const
397  {
399 
400  INDEX_TYPE const nnz = numNonZeros( row );
401  COL_TYPE const * const columns = getColumns( row );
402  T * const entries = getEntries( row );
403 
404  INDEX_TYPE_NC curPos = 0;
405  for( INDEX_TYPE_NC i = 0; i < nCols; ++i )
406  {
407  INDEX_TYPE const pos = sortedArrayManipulation::find( columns + curPos, nnz - curPos, cols[ i ] ) + curPos;
408  LVARRAY_ASSERT_GT( nnz, pos );
409  LVARRAY_ASSERT_EQ( columns[ pos ], cols[ i ] );
410 
411  internal::atomicAdd( AtomicPolicy{}, entries + pos, vals[ i ] );
412  curPos = pos + 1;
413  }
414  }
415 
428  template< typename AtomicPolicy >
429  LVARRAY_HOST_DEVICE inline
430  void addToRowLinearSearch( INDEX_TYPE const row,
431  COL_TYPE const * const LVARRAY_RESTRICT cols,
432  T const * const LVARRAY_RESTRICT vals,
433  INDEX_TYPE const nCols ) const
434  {
436 
437  INDEX_TYPE const nnz = numNonZeros( row );
438  COL_TYPE const * const columns = getColumns( row );
439  T * const entries = getEntries( row );
440 
441  INDEX_TYPE_NC curPos = 0;
442  for( INDEX_TYPE_NC i = 0; i < nCols; ++i )
443  {
444  for( INDEX_TYPE_NC j = curPos; j < nnz; ++j )
445  {
446  if( columns[ j ] == cols[ i ] )
447  {
448  curPos = j;
449  break;
450  }
451  }
452  LVARRAY_ASSERT_EQ( columns[ curPos ], cols[ i ] );
453  internal::atomicAdd( AtomicPolicy{}, entries + curPos, vals[ i ] );
454  ++curPos;
455  }
456  }
457 
469  template< typename AtomicPolicy >
470  LVARRAY_HOST_DEVICE inline
471  void addToRowBinarySearchUnsorted( INDEX_TYPE const row,
472  COL_TYPE const * const LVARRAY_RESTRICT cols,
473  T const * const LVARRAY_RESTRICT vals,
474  INDEX_TYPE const nCols ) const
475  {
476  INDEX_TYPE const nnz = numNonZeros( row );
477  COL_TYPE const * const columns = getColumns( row );
478  T * const entries = getEntries( row );
479 
480  for( INDEX_TYPE_NC i = 0; i < nCols; ++i )
481  {
482  INDEX_TYPE const pos = sortedArrayManipulation::find( columns, nnz, cols[ i ] );
483  LVARRAY_ASSERT_GT( nnz, pos );
484  LVARRAY_ASSERT_EQ( columns[ pos ], cols[ i ] );
485 
486  internal::atomicAdd( AtomicPolicy{}, entries + pos, vals[ i ] );
487  }
488  }
489 
491 
495 
503  void move( MemorySpace const space, bool const touch=true ) const
504  {
505  ParentClass::move( space, touch );
506  m_entries.move( space, touch );
507  }
508 
510 
511 protected:
512 
517  CRSMatrixView( bool ):
518  ParentClass( true ),
519  m_entries( true )
520  {}
521 
527  template< typename U >
528  void setName( std::string const & name )
529  {
530  ParentClass::template setName< U >( name );
531  m_entries.template setName< U >( name + "/entries" );
532  }
533 
535  BUFFER_TYPE< T > m_entries;
536 
537 private:
538 
543  class CallBacks
544  {
545 public:
546 
553  LVARRAY_HOST_DEVICE inline
554  CallBacks( CRSMatrixView const & crsMV,
555  INDEX_TYPE const row, T const * const entriesToInsert ):
556  m_crsMV( crsMV ),
557  m_row( row ),
558  m_rowNNZ( crsMV.numNonZeros( row ) ),
559  m_rowCapacity( crsMV.nonZeroCapacity( row ) ),
560  m_entries( crsMV.getEntries( row ) ),
561  m_entriesToInsert( entriesToInsert )
562  {}
563 
572  LVARRAY_HOST_DEVICE inline
573  COL_TYPE * incrementSize( COL_TYPE * const curPtr, INDEX_TYPE const nToAdd ) const
574  {
575  LVARRAY_UNUSED_VARIABLE( curPtr );
576 #ifdef LVARRAY_BOUNDS_CHECK
577  LVARRAY_ERROR_IF_GT_MSG( m_rowNNZ + nToAdd, m_rowCapacity, "CRSMatrixView cannot do reallocation." );
578 #else
579  LVARRAY_DEBUG_VAR( nToAdd );
580 #endif
581  return m_crsMV.getSetValues( m_row );
582  }
583 
590  LVARRAY_HOST_DEVICE inline
591  void insert( INDEX_TYPE const insertPos ) const
592  { arrayManipulation::emplace( m_entries, m_rowNNZ, insertPos, m_entriesToInsert[0] ); }
593 
602  LVARRAY_HOST_DEVICE inline
603  void set( INDEX_TYPE const pos, INDEX_TYPE const colPos ) const
604  { new (&m_entries[ pos ]) T( m_entriesToInsert[ colPos ] ); }
605 
616  LVARRAY_HOST_DEVICE inline
617  void insert( INDEX_TYPE const nLeftToInsert,
618  INDEX_TYPE const colPos,
619  INDEX_TYPE const pos,
620  INDEX_TYPE const prevPos ) const
621  {
622  arrayManipulation::shiftUp( m_entries, prevPos, pos, nLeftToInsert );
623  new (&m_entries[pos + nLeftToInsert - 1]) T( m_entriesToInsert[colPos] );
624  }
625 
632  LVARRAY_HOST_DEVICE inline
633  void remove( INDEX_TYPE_NC removePos ) const
634  { arrayManipulation::erase( m_entries, m_rowNNZ, removePos ); }
635 
646  LVARRAY_HOST_DEVICE inline
647  void remove( INDEX_TYPE const nRemoved,
648  INDEX_TYPE const curPos,
649  INDEX_TYPE const nextPos ) const
650  { arrayManipulation::shiftDown( m_entries, nextPos, curPos + 1, nRemoved ); }
651 
652 private:
654  CRSMatrixView const & m_crsMV;
655 
657  INDEX_TYPE const m_row;
658 
660  INDEX_TYPE const m_rowNNZ;
661 
663  INDEX_TYPE const m_rowCapacity;
664 
666  T * const m_entries;
667 
669  T const * const m_entriesToInsert;
670  };
671 
672 };
673 
674 } /* namespace LvArray */
#define LVARRAY_UNUSED_VARIABLE(X)
Mark X as an unused variable, used to silence compiler warnings.
Definition: Macros.hpp:51
constexpr CRSMatrixView< T, COL_TYPE const, INDEX_TYPE const, BUFFER_TYPE > toViewConstSizes() const
#define LVARRAY_ASSERT(EXP)
Assert EXP is true with no message.
Definition: Macros.hpp:142
void addToRowBinarySearchUnsorted(INDEX_TYPE const row, COL_TYPE const *const LVARRAY_RESTRICT cols, T const *const LVARRAY_RESTRICT vals, INDEX_TYPE const nCols) const
Add to the given entries, the entries must already exist in the matrix.
This class provides a view into a compressed row storage sparsity pattern.
INDEX_TYPE_NC removeNonZeros(INDEX_TYPE const row, COL_TYPE const *const LVARRAY_RESTRICT cols, INDEX_TYPE const ncols) const
Remove non-zero entries from the given row.
#define ARRAYOFARRAYS_CHECK_BOUNDS(i)
Check that i is a valid array index.
bool isSortedUnique(ITER first, ITER const last, Compare &&comp=Compare())
constexpr CRSMatrixView< T const, COL_TYPE const, INDEX_TYPE const, BUFFER_TYPE > toViewConst() const
This class serves to provide a sliced multidimensional interface to the family of LvArray classes...
Definition: ArraySlice.hpp:89
constexpr CRSMatrixView< T, COL_TYPE, INDEX_TYPE const, BUFFER_TYPE > toView() const
INDEX_TYPE_NC insertNonZeros(INDEX_TYPE const row, COL_TYPE const *const LVARRAY_RESTRICT cols, T const *const LVARRAY_RESTRICT entriesToInsert, INDEX_TYPE const ncols) const
Insert a non-zero entries into the given row.
CRSMatrixView(bool)
Protected constructor to be used by the CRSMatrix class.
void move(MemorySpace const space, bool const touch=true) const
Move this SparsityPattern to the given memory space and touch the values, sizes and offsets...
bool insertNonZero(INDEX_TYPE const row, COL_TYPE const col, T const &entry) const
Insert a non-zero entry at the given position.
#define LVARRAY_ASSERT_GT(lhs, rhs)
Assert that one value compares greater than the other in debug builds.
Definition: Macros.hpp:355
void shiftUp(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, std::ptrdiff_t const index, std::ptrdiff_t const n)
Shift the values in the array at or above the given position up by the given amount. New uninitialized values take their place.
void setValues(T const &value) const
Set all the entries in the matrix to the given value.
std::conditional_t< CONST_SIZES, INDEX_TYPE const, INDEX_TYPE_NC > SIZE_TYPE
The type contained by the m_sizes buffer.
void destroy(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size)
Destory the values in the array.
constexpr INDEX_TYPE_NC nonZeroCapacity() const
BUFFER_TYPE< T > m_entries
Holds the entries of the matrix, of length numNonZeros().
Contains the implementation of LvArray::ArraySlice.
ArraySlice< T, 1, 0, INDEX_TYPE_NC > getEntries(INDEX_TYPE const row) const
Contains the implementation of LvArray:SparsityPatternView.
std::ptrdiff_t find(T const *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, T const &value, Compare &&comp=Compare())
void setName(std::string const &name)
Set the name to be displayed whenever the underlying Buffer&#39;s user call back is called.
void emplace(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, std::ptrdiff_t const index, ARGS &&... args)
Insert into the array constructing the new value in place.
void addToRowBinarySearch(INDEX_TYPE const row, COL_TYPE const *const LVARRAY_RESTRICT cols, T const *const LVARRAY_RESTRICT vals, INDEX_TYPE const nCols) const
Add to the given entries, the entries must already exist in the matrix.
LvArray::CRSMatrixView< T, COL_INDEX, localIndex const, LvArray::ChaiBuffer > CRSMatrixView
Alias for CRS Matrix View.
Definition: DataTypes.hpp:331
Contains functions for manipulating a contiguous array of values.
#define LVARRAY_DEBUG_VAR(X)
Mark X as an debug variable, used to silence compiler warnings.
Definition: Macros.hpp:57
MemorySpace
An enum containing the available memory spaces.
The top level namespace.
Definition: Array.hpp:24
#define LVARRAY_ERROR_IF_GT_MSG(lhs, rhs, msg)
Raise a hard error if one value compares greater than the other.
Definition: Macros.hpp:245
void addToRow(INDEX_TYPE const row, COL_TYPE const *const LVARRAY_RESTRICT cols, T const *const LVARRAY_RESTRICT vals, INDEX_TYPE const nCols) const
Add to the given entries, the entries must already exist in the matrix. The columns must be sorted...
constexpr CRSMatrixView(INDEX_TYPE const nRows, INDEX_TYPE const nCols, BUFFER_TYPE< INDEX_TYPE > const &offsets, BUFFER_TYPE< SIZE_TYPE > const &nnz, BUFFER_TYPE< COL_TYPE > const &columns, BUFFER_TYPE< T > const &entries)
Construct a new CRSMatrixView from the given buffers.
constexpr SparsityPatternView< COL_TYPE const, INDEX_TYPE const, BUFFER_TYPE > toSparsityPatternView() const &
std::remove_const_t< INDEX_TYPE > INDEX_TYPE_NC
Since INDEX_TYPE should always be const we need an alias for the non const version.
bool removeNonZero(INDEX_TYPE const row, COL_TYPE const col) const
Remove a non-zero entry at the given position.
void erase(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, std::ptrdiff_t const index, std::ptrdiff_t const n=1)
Shift the values in the array at or above the given position down by the given amount overwriting the...
void addToRowLinearSearch(INDEX_TYPE const row, COL_TYPE const *const LVARRAY_RESTRICT cols, T const *const LVARRAY_RESTRICT vals, INDEX_TYPE const nCols) const
Add to the given entries, the entries must already exist in the matrix.
std::string string
String type.
Definition: DataTypes.hpp:131
void shiftDown(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, std::ptrdiff_t const index, std::ptrdiff_t const n)
Shift the values in the array at or above the given position down by the given amount overwriting the...
#define DISABLE_HD_WARNING
Disable host device warnings.
Definition: Macros.hpp:401
void insert(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, std::ptrdiff_t const index, ITERATOR first, std::ptrdiff_t const n)
Insert the given values into the array at the given position.
typename ParentClass::INDEX_TYPE_NC INDEX_TYPE_NC
Since INDEX_TYPE should always be const we need an alias for the non const version.
real64 EntryType
The type of the entries in the matrix.
#define LVARRAY_ASSERT_EQ(lhs, rhs)
Assert that two values compare equal in debug builds.
Definition: Macros.hpp:325
#define LVARRAY_HOST_DEVICE
Mark a function for both host and device usage.
Definition: Macros.hpp:389
This class provides a view into a compressed row storage matrix.