| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |   Copyright 2024 SINTEF AS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   This file is part of the Open Porous Media project (OPM). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   OPM is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  |   it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  |   the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  |   (at your option) any later version. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   OPM is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |   but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |   GNU General Public License for more details. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |   along with OPM.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2024-08-22 15:27:23 +02:00
										 |  |  | #ifndef OPM_GPUVIEW_HEADER_HPP
 | 
					
						
							|  |  |  | #define OPM_GPUVIEW_HEADER_HPP
 | 
					
						
							| 
									
										
										
										
											2024-08-07 09:54:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  | #include <dune/common/fvector.hh>
 | 
					
						
							| 
									
										
										
										
											2024-08-07 09:54:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  | #include <opm/common/ErrorMacros.hpp>
 | 
					
						
							| 
									
										
										
										
											2024-08-07 09:54:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-10 15:44:20 +02:00
										 |  |  | #include <opm/common/utility/gpuDecorators.hpp>
 | 
					
						
							| 
									
										
										
										
											2024-08-22 15:32:21 +02:00
										 |  |  | #include <opm/simulators/linalg/gpuistl/detail/safe_conversion.hpp>
 | 
					
						
							| 
									
										
										
										
											2024-08-07 09:54:59 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <stdexcept>
 | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  | #include <vector>
 | 
					
						
							| 
									
										
										
										
											2024-08-07 09:54:59 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <fmt/core.h>
 | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-22 13:52:50 +02:00
										 |  |  | namespace Opm::gpuistl | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2024-08-22 15:27:23 +02:00
										 |  |  |  * @brief The GpuView class is provides a view of some data allocated on the GPU | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  |  * Essenstially is only stores a pointer and a size. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  This class supports being used from inside a CUDA/HIP Kernel. | 
					
						
							|  |  |  |  *  Implementations are placed in this headerfile for functions that may be called | 
					
						
							|  |  |  |  *  inside a kernel to avoid expensive RDC (relocatable device code) | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2024-08-22 14:12:30 +02:00
										 |  |  |  * The view will typically provide a view into a GpuBuffer and be able to | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  |  * manipulate the data within it | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @param T Type of the data we store, typically int/float/double w/o const specifier | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  **/ | 
					
						
							|  |  |  | template <typename T> | 
					
						
							| 
									
										
										
										
											2024-08-22 15:27:23 +02:00
										 |  |  | class GpuView | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     using value_type = T; | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * @brief Default constructor that will initialize cublas and allocate 0 bytes of memory | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2024-08-22 15:27:23 +02:00
										 |  |  |     explicit GpuView() = default; | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     //TODO: we probably dont need anything like this or is it useful to have views also be able to handle things on CPU?
 | 
					
						
							|  |  |  |     /// @brief constructor based on std::vectors, this will make a view on the CPU
 | 
					
						
							|  |  |  |     /// @param data std vector to pr
 | 
					
						
							| 
									
										
										
										
											2024-08-22 15:27:23 +02:00
										 |  |  |     GpuView(std::vector<T>& data); | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * @brief operator[] to retrieve a reference to an item in the buffer | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param idx The index of the element | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     __host__ __device__ T& operator[](size_t idx){ | 
					
						
							|  |  |  | #ifndef NDEBUG
 | 
					
						
							| 
									
										
										
										
											2024-08-05 11:47:18 +02:00
										 |  |  |         assertInRange(idx); | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  | #endif
 | 
					
						
							|  |  |  |     return m_dataPtr[idx]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * @brief operator[] to retrieve a copy of an item in the buffer | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param idx The index of the element | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     __host__ __device__ T operator[](size_t idx) const { | 
					
						
							|  |  |  | #ifndef NDEBUG
 | 
					
						
							| 
									
										
										
										
											2024-08-05 11:47:18 +02:00
										 |  |  |         assertInRange(idx); | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  | #endif
 | 
					
						
							|  |  |  |     return m_dataPtr[idx]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							| 
									
										
										
										
											2024-08-22 15:27:23 +02:00
										 |  |  |      * @brief GpuView allocates new GPU memory of size numberOfElements * sizeof(T) and copies numberOfElements from | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  |      * data | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @note This assumes the data is on the CPU. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param numberOfElements number of T elements to allocate | 
					
						
							|  |  |  |      * @param dataOnHost data on host/CPU | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2024-08-22 15:27:23 +02:00
										 |  |  |     __host__ __device__ GpuView(T* dataOnHost, size_t numberOfElements) | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  |         : m_dataPtr(dataOnHost), m_numberOfElements(numberOfElements) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							| 
									
										
										
										
											2024-08-22 15:27:23 +02:00
										 |  |  |      * @brief ~GpuView calls cudaFree | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2024-08-22 15:27:23 +02:00
										 |  |  |     ~GpuView() = default; | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * @return the raw pointer to the GPU data | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     __host__ __device__ T* data(){ | 
					
						
							|  |  |  |         return m_dataPtr; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * @return the raw pointer to the GPU data | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     __host__ __device__ const T* data() const{ | 
					
						
							|  |  |  |         return m_dataPtr; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							| 
									
										
										
										
											2024-08-22 15:27:23 +02:00
										 |  |  |      * @return fetch the first element in a GpuView | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  |      */ | 
					
						
							|  |  |  |     __host__ __device__ T& front() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  | #ifndef NDEBUG
 | 
					
						
							|  |  |  |         assertHasElements(); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         return m_dataPtr[0]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							| 
									
										
										
										
											2024-08-22 15:27:23 +02:00
										 |  |  |      * @return fetch the last element in a GpuView | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  |      */ | 
					
						
							|  |  |  |     __host__ __device__ T& back() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  | #ifndef NDEBUG
 | 
					
						
							|  |  |  |         assertHasElements(); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         return m_dataPtr[m_numberOfElements-1]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							| 
									
										
										
										
											2024-08-22 15:27:23 +02:00
										 |  |  |      * @return fetch the first element in a GpuView | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  |      */ | 
					
						
							|  |  |  |     __host__ __device__ T front() const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  | #ifndef NDEBUG
 | 
					
						
							|  |  |  |         assertHasElements(); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         return m_dataPtr[0]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							| 
									
										
										
										
											2024-08-22 15:27:23 +02:00
										 |  |  |      * @return fetch the last element in a GpuView | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  |      */ | 
					
						
							|  |  |  |     __host__ __device__ T back() const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  | #ifndef NDEBUG
 | 
					
						
							|  |  |  |         assertHasElements(); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         return m_dataPtr[m_numberOfElements-1]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * @brief copyFromHost copies numberOfElements from the CPU memory dataPointer | 
					
						
							|  |  |  |      * @param dataPointer raw pointer to CPU memory | 
					
						
							|  |  |  |      * @param numberOfElements number of elements to copy | 
					
						
							|  |  |  |      * @note This does synchronous transfer. | 
					
						
							|  |  |  |      * @note assumes that this view has numberOfElements elements | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     void copyFromHost(const T* dataPointer, size_t numberOfElements); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * @brief copyFromHost copies numberOfElements to the CPU memory dataPointer | 
					
						
							|  |  |  |      * @param dataPointer raw pointer to CPU memory | 
					
						
							|  |  |  |      * @param numberOfElements number of elements to copy | 
					
						
							|  |  |  |      * @note This does synchronous transfer. | 
					
						
							|  |  |  |      * @note assumes that this view has numberOfElements elements | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     void copyToHost(T* dataPointer, size_t numberOfElements) const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * @brief copyToHost copies data from an std::vector | 
					
						
							|  |  |  |      * @param data the vector to copy from | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @note This does synchronous transfer. | 
					
						
							|  |  |  |      * @note This assumes that the size of this view is equal to the size of the input vector. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     void copyFromHost(const std::vector<T>& data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * @brief copyToHost copies data to an std::vector | 
					
						
							|  |  |  |      * @param data the vector to copy to | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @note This does synchronous transfer. | 
					
						
							|  |  |  |      * @note This assumes that the size of this view is equal to the size of the input vector. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     void copyToHost(std::vector<T>& data) const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * @brief size returns the size (number of T elements) in the vector | 
					
						
							|  |  |  |      * @return number of elements | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     __host__ __device__ size_t size() const{ | 
					
						
							|  |  |  |         return m_numberOfElements; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * @brief creates an std::vector of the same size and copies the GPU data to this std::vector | 
					
						
							|  |  |  |      * @return an std::vector containing the elements copied from the GPU. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     std::vector<T> asStdVector() const; | 
					
						
							| 
									
										
										
										
											2024-08-22 15:27:23 +02:00
										 |  |  |     /// @brief Iterator class to make GpuViews more similar to std containers
 | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  |     class iterator { | 
					
						
							|  |  |  |     public: | 
					
						
							|  |  |  |         // Iterator typedefs
 | 
					
						
							|  |  |  |         using iterator_category = std::forward_iterator_tag; | 
					
						
							|  |  |  |         using difference_type = std::ptrdiff_t; | 
					
						
							|  |  |  |         using value_type = T; | 
					
						
							|  |  |  |         using pointer = T*; | 
					
						
							|  |  |  |         using reference = T&; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /// @brief Create iterator from a pointer
 | 
					
						
							|  |  |  |         /// @param ptr provided pointer that will become an iterator
 | 
					
						
							|  |  |  |         /// @return // the created iterator object
 | 
					
						
							|  |  |  |         __host__ __device__ iterator(T* ptr) : m_ptr(ptr) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /// @brief Dereference operator
 | 
					
						
							|  |  |  |         /// @return retrieve what the iterator points at
 | 
					
						
							|  |  |  |         __host__ __device__ reference operator*() const { | 
					
						
							|  |  |  |             return *m_ptr; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /// @brief Pre-increment operator
 | 
					
						
							|  |  |  |         /// @return return the pointer after it is incremented
 | 
					
						
							|  |  |  |         __host__ __device__ iterator& operator++() { | 
					
						
							|  |  |  |             ++m_ptr; | 
					
						
							|  |  |  |             return *this; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /// @brief Post-increment operator
 | 
					
						
							|  |  |  |         /// @param no parameter, int is placeholder for c++ implementation to differentiate from pre-increment
 | 
					
						
							|  |  |  |         /// @return Iterator before it is incremented
 | 
					
						
							|  |  |  |         __host__ __device__ iterator operator++(int) { | 
					
						
							|  |  |  |             iterator tmp = *this; | 
					
						
							|  |  |  |             ++m_ptr; | 
					
						
							|  |  |  |             return tmp; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /// @brief Pre-decrement operator
 | 
					
						
							|  |  |  |         /// @return return the pointer after it is decremented
 | 
					
						
							|  |  |  |         __host__ __device__ iterator& operator--() { | 
					
						
							|  |  |  |             --m_ptr; | 
					
						
							|  |  |  |             return *this; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /// @brief Post-decrement operator
 | 
					
						
							|  |  |  |         /// @param no parameter, int is placeholder for c++ implementation to differentiate from pre-decrement
 | 
					
						
							|  |  |  |         /// @return Iterator before it is decremented
 | 
					
						
							|  |  |  |         __host__ __device__ iterator operator--(int) { | 
					
						
							|  |  |  |             iterator tmp = *this; | 
					
						
							|  |  |  |             --m_ptr; | 
					
						
							|  |  |  |             return tmp; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /// @brief Inequality comparison operator
 | 
					
						
							|  |  |  |         /// @return boolean value that is true if the pointers contains different addresses
 | 
					
						
							|  |  |  |         __host__ __device__ bool operator!=(const iterator& other) const { | 
					
						
							|  |  |  |             return !(m_ptr == other.m_ptr); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /// @brief Inequality comparison operator
 | 
					
						
							|  |  |  |         /// @return boolean value that is true if the pointers contains the same address
 | 
					
						
							|  |  |  |         __host__ __device__ bool operator==(const iterator& other) const { | 
					
						
							|  |  |  |             return m_ptr == other.m_ptr; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /// @brief subtraction operator
 | 
					
						
							|  |  |  |         /// @param other iterator to subtract
 | 
					
						
							|  |  |  |         /// @return diffptr that represents difference between the iterators
 | 
					
						
							|  |  |  |         __host__ __device__ difference_type operator-(const iterator& other) const { | 
					
						
							|  |  |  |             return std::distance(other.m_ptr, m_ptr); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /// @brief Subtraction of given number of elements from iterator
 | 
					
						
							|  |  |  |         /// @param n the number of elements to step backwards
 | 
					
						
							|  |  |  |         /// @return An iterator pointing to a location n steps behind
 | 
					
						
							|  |  |  |         __host__ __device__ iterator operator-(difference_type n) const { | 
					
						
							|  |  |  |             return iterator(m_ptr-n); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /// @brief Addition operator with diffptr
 | 
					
						
							|  |  |  |         /// @param n diffptr to add
 | 
					
						
							|  |  |  |         /// @return new iterator with diffptr added
 | 
					
						
							|  |  |  |         __host__ __device__ iterator operator+(difference_type n) const { | 
					
						
							|  |  |  |             return iterator(m_ptr + n); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /// @brief Less than comparison
 | 
					
						
							|  |  |  |         /// @param other iterator
 | 
					
						
							|  |  |  |         /// @return true if this objects iterator is less than the other iterator
 | 
					
						
							|  |  |  |         __host__ __device__ bool operator<(const iterator& other) const { | 
					
						
							|  |  |  |             return m_ptr < other.m_ptr; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /// @brief Greater than comparison
 | 
					
						
							|  |  |  |         /// @param other iterator
 | 
					
						
							|  |  |  |         /// @return true if this objects iterator is greater than than the other iterator
 | 
					
						
							|  |  |  |         __host__ __device__ bool operator>(const iterator& other) const { | 
					
						
							|  |  |  |             return m_ptr > other.m_ptr; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private: | 
					
						
							|  |  |  |         // Pointer to the current element
 | 
					
						
							|  |  |  |         T* m_ptr; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * @brief Get an iterator pointing to the first element of the buffer | 
					
						
							|  |  |  |      * @param iterator to traverse the buffer | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     __host__ __device__ iterator begin(){ | 
					
						
							|  |  |  |         return iterator(m_dataPtr); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * @brief Get a const iterator pointing to the first element of the buffer | 
					
						
							|  |  |  |      * @param iterator to traverse the buffer | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     __host__ __device__ iterator begin() const { | 
					
						
							|  |  |  |         return iterator(m_dataPtr); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * @brief Get an iterator pointing to the address after the last element of the buffer | 
					
						
							|  |  |  |      * @param iterator pointing to the first value after the end of the buffer | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     __host__ __device__ iterator end(){ | 
					
						
							|  |  |  |         return iterator(m_dataPtr + m_numberOfElements); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * @brief Get a const iterator pointing to the address after the last element of the buffer | 
					
						
							|  |  |  |      * @param iterator pointing to the first value after the end of the buffer | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     __host__ __device__ iterator end() const { | 
					
						
							|  |  |  |         return iterator(m_dataPtr + m_numberOfElements); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     T* m_dataPtr; | 
					
						
							|  |  |  |     size_t m_numberOfElements; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// @brief Helper function to assert if another view has the same size
 | 
					
						
							|  |  |  |     /// @param other view
 | 
					
						
							| 
									
										
										
										
											2024-08-22 15:27:23 +02:00
										 |  |  |     __host__ __device__ void assertSameSize(const GpuView<T>& other) const | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         assertSameSize(other.m_numberOfElements); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /// @brief Helper function to assert if the size of this view equal to a given value
 | 
					
						
							|  |  |  |     /// @param size The value to compare with the size of this view
 | 
					
						
							|  |  |  |     __host__ __device__ void assertSameSize(size_t size) const | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-09-10 15:44:20 +02:00
										 |  |  | #if OPM_IS_INSIDE_DEVICE_FUNCTION
 | 
					
						
							| 
									
										
										
										
											2024-08-07 13:31:48 +02:00
										 |  |  |         // TODO: find a better way to handle exceptions in kernels, this will possibly be printed many times
 | 
					
						
							|  |  |  |         assert(size == m_numberOfElements && "Views did not have the same size"); | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  |         if (size != m_numberOfElements) { | 
					
						
							|  |  |  |             OPM_THROW(std::invalid_argument, | 
					
						
							| 
									
										
										
										
											2024-08-07 13:31:48 +02:00
										 |  |  |                     fmt::format("Given view has {}, while this View has {}.", size, m_numberOfElements)); | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-08-07 13:31:48 +02:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// @brief Helper function to assert that the view has at least one element
 | 
					
						
							|  |  |  |     __host__ __device__ void assertHasElements() const | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-09-10 15:44:20 +02:00
										 |  |  | #if OPM_IS_INSIDE_DEVICE_FUNCTION
 | 
					
						
							| 
									
										
										
										
											2024-08-07 13:31:48 +02:00
										 |  |  |         // TODO: find a better way to handle exceptions in kernels, this will possibly be printed many times
 | 
					
						
							| 
									
										
										
										
											2024-08-07 13:35:52 +02:00
										 |  |  |         assert(m_numberOfElements > 0 && "View has 0 elements"); | 
					
						
							| 
									
										
										
										
											2024-08-07 13:31:48 +02:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  |         if (m_numberOfElements <= 0) { | 
					
						
							| 
									
										
										
										
											2024-08-07 13:35:52 +02:00
										 |  |  |             OPM_THROW(std::invalid_argument, "View has 0 elements"); | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-08-07 13:31:48 +02:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// @brief Helper function to determine if an index is within the range of valid indexes in the view
 | 
					
						
							|  |  |  |     __host__ __device__ void assertInRange(size_t idx) const | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-09-10 15:44:20 +02:00
										 |  |  | #if OPM_IS_INSIDE_DEVICE_FUNCTION
 | 
					
						
							| 
									
										
										
										
											2024-08-07 13:31:48 +02:00
										 |  |  |         // TODO: find a better way to handle exceptions in kernels, this will possibly be printed many times
 | 
					
						
							|  |  |  |         assert(idx < m_numberOfElements && "The index provided was not in the range [0, buffersize-1]"); | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  |         if (idx >= m_numberOfElements) { | 
					
						
							|  |  |  |             OPM_THROW(std::invalid_argument, | 
					
						
							|  |  |  |                     fmt::format("The index provided was not in the range [0, buffersize-1]")); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-08-07 13:31:48 +02:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-22 13:52:50 +02:00
										 |  |  | } // namespace Opm::gpuistl
 | 
					
						
							| 
									
										
										
										
											2024-08-07 09:54:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-15 13:43:46 +02:00
										 |  |  | #endif
 |