NeoN
A framework for CFD software
Loading...
Searching...
No Matches
array.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: MIT
2// SPDX-FileCopyrightText: 2025 NeoN authors
3
4#pragma once
5
6#include <Kokkos_Core.hpp>
7
8#include "NeoN/core/error.hpp"
11#include "NeoN/core/view.hpp"
13
14#include <variant>
15#include <vector>
16
17
18namespace NeoN
19{
20
27template<typename ValueType>
28class Array
29{
30
31public:
32
33 using ArrayValueType = ValueType;
34
40 Array(const Executor& exec, localIdx size) : size_(size), data_(nullptr), exec_(exec)
41 {
42 void* ptr = nullptr;
43 std::visit(
44 [&ptr, size](const auto& concreteExec)
45 { ptr = concreteExec.alloc(static_cast<size_t>(size) * sizeof(ValueType)); },
46 exec_
47 );
48 data_ = static_cast<ValueType*>(ptr);
49 }
50
59 const Executor& exec,
60 const ValueType* in,
62 Executor hostExec = SerialExecutor()
63 )
64 : size_(size), data_(nullptr), exec_(exec)
65 {
66 void* ptr = nullptr;
67 std::visit(
68 [&ptr, size](const auto& concreteExec)
69 { ptr = concreteExec.alloc(static_cast<size_t>(size) * sizeof(ValueType)); },
70 exec_
71 );
72 data_ = static_cast<ValueType*>(ptr);
73 std::visit(detail::deepCopyVisitor<ValueType>(size_, in, data_), hostExec, exec_);
74 }
75
76
83 Array(const Executor& exec, localIdx size, ValueType value)
84 : size_(size), data_(nullptr), exec_(exec)
85 {
86 void* ptr = nullptr;
87 std::visit(
88 [&ptr, size](const auto& execu)
89 { ptr = execu.alloc(static_cast<size_t>(size) * sizeof(ValueType)); },
90 exec_
91 );
92 data_ = static_cast<ValueType*>(ptr);
93 NeoN::fill(*this, value);
94 }
95
101 Array(const Executor& exec, std::vector<ValueType> in)
102 : Array(exec, in.data(), static_cast<localIdx>(in.size()))
103 {}
104
105
112 : Array(exec, in.data(), in.size(), in.exec())
113 {}
114
119 Array(const Array<ValueType>& rhs) : Array(rhs.exec(), rhs.data(), rhs.size(), rhs.exec()) {}
120
121
126 Array(Array<ValueType>&& rhs) noexcept : size_(rhs.size_), data_(rhs.data_), exec_(rhs.exec_)
127 {
128 rhs.data_ = nullptr;
129 rhs.size_ = 0;
130 };
131
136 {
137 std::visit([this](const auto& exec) { exec.free(data_); }, exec_);
138 data_ = nullptr;
139 }
140
146 template<typename func>
147 void apply(func f)
148 {
149 map(*this, f);
150 }
151
157 [[nodiscard]] Array<ValueType> copyToExecutor(Executor dstExec) const
158 {
159 if (dstExec == exec_) return *this;
160
161 Array<ValueType> result(dstExec, size_);
162 std::visit(detail::deepCopyVisitor(size_, data_, result.data()), exec_, dstExec);
163
164 return result;
165 }
166
171 [[nodiscard]] Array<ValueType> copyToHost() const { return copyToExecutor(SerialExecutor()); }
172
182 {
184 result.size() == size_, "Parsed Array size not the same as current field size"
185 );
186 result = copyToExecutor(SerialExecutor());
187 }
188
189 // ensures no return of device address on host --> invalid memory access
190 Array& operator[](const localIdx i) = delete;
191
192 // ensures no return of device address on host --> invalid memory access
193 const Array& operator[](const localIdx i) const = delete;
194
199 void operator=(const ValueType& rhs)
200 {
201 NF_ERROR_EXIT("Not implemented");
202 fill(*this, rhs);
203 }
204
212 {
213 NF_ASSERT(exec_ == rhs.exec_, "Executors are not the same");
214 if (this->size() != rhs.size())
215 {
216 this->resize(rhs.size());
217 }
218 setContainer(*this, rhs.view());
219 }
220
225 void resize(const localIdx size)
226 {
227 void* ptr = nullptr;
228 if (!empty())
229 {
230 std::visit(
231 [this, &ptr, size](const auto& exec)
232 { ptr = exec.realloc(this->data_, static_cast<size_t>(size) * sizeof(ValueType)); },
233 exec_
234 );
235 }
236 else
237 {
238 std::visit(
239 [&ptr, size](const auto& exec)
240 { ptr = exec.alloc(static_cast<size_t>(size) * sizeof(ValueType)); },
241 exec_
242 );
243 }
244 data_ = static_cast<ValueType*>(ptr);
245 size_ = size;
246 }
247
252 [[nodiscard]] inline ValueType* data() { return data_; }
253
258 [[nodiscard]] inline const ValueType* data() const { return data_; }
259
264 [[nodiscard]] inline const Executor& exec() const { return exec_; }
265
270 [[nodiscard]] inline localIdx size() const { return size_; }
271
276 [[nodiscard]] inline label ssize() const { return static_cast<label>(size_); }
277
282 [[nodiscard]] inline bool empty() const { return size() == 0; }
283
284 // return of a temporary --> invalid memory access
285 View<ValueType> view() && = delete;
286
287 // return of a temporary --> invalid memory access
288 View<const ValueType> view() const&& = delete;
289
294 [[nodiscard]] inline View<ValueType> view() &
295 {
296 return View<ValueType>(data_, static_cast<size_t>(size_));
297 }
298
303 [[nodiscard]] inline View<const ValueType> view() const&
304 {
305 return View<const ValueType>(data_, static_cast<size_t>(size_));
306 }
307
308 // return of a temporary --> invalid memory access
309 [[nodiscard]] View<ValueType> view(std::pair<localIdx, localIdx> range) && = delete;
310
311 // return of a temporary --> invalid memory access
312 [[nodiscard]] View<const ValueType> view(std::pair<localIdx, localIdx> range) const&& = delete;
313
318 [[nodiscard]] inline View<ValueType> view(std::pair<localIdx, localIdx> range) &
319 {
320 return View<ValueType>(
321 data_ + range.first, static_cast<size_t>(range.second - range.first)
322 );
323 }
324
329 [[nodiscard]] inline View<const ValueType> view(std::pair<localIdx, localIdx> range) const&
330 {
332 data_ + range.first, static_cast<size_t>(range.second - range.first)
333 );
334 }
335
340 [[nodiscard]] inline std::pair<localIdx, localIdx> range() const { return {0, size()}; }
341
342private:
343
344 localIdx size_ {0};
345 ValueType* data_ {nullptr};
346 const Executor exec_;
347
352 void validateOtherArray(const Array<ValueType>& rhs) const
353 {
354 NF_DEBUG_ASSERT(size() == rhs.size(), "Arrays are not the same size.");
355 NF_DEBUG_ASSERT(exec() == rhs.exec(), "Executors are not the same.");
356 }
357};
358
359} // namespace NeoN
A class to contain the data and executors for a field and define some basic operations.
Definition array.hpp:29
Array(const Executor &exec, localIdx size, ValueType value)
Create a Array with a given size on an executor and uniform value.
Definition array.hpp:83
const ValueType * data() const
Direct access to the underlying field data.
Definition array.hpp:258
View< ValueType > view() &&=delete
Array< ValueType > copyToHost() const
Returns a copy of the field back to the host.
Definition array.hpp:171
void copyToHost(Array< ValueType > &result)
Copies the data (from anywhere) to a parsed host field.
Definition array.hpp:181
View< ValueType > view(std::pair< localIdx, localIdx > range) &
Gets a sub view of the field as a view.
Definition array.hpp:318
std::pair< localIdx, localIdx > range() const
Gets the range of the field.
Definition array.hpp:340
Array(Array< ValueType > &&rhs) noexcept
Move constructor, moves the data from the parsed field to the new field.
Definition array.hpp:126
Array(const Executor &exec, localIdx size)
Create an uninitialized Array with a given size on an executor.
Definition array.hpp:40
Array< ValueType > copyToExecutor(Executor dstExec) const
Copies the data to a new field on a specific executor.
Definition array.hpp:157
View< const ValueType > view() const &
Gets the field as a view.
Definition array.hpp:303
label ssize() const
Gets the size of the field.
Definition array.hpp:276
void operator=(const ValueType &rhs)
Assignment operator, Sets the field values to that of the passed value.
Definition array.hpp:199
const Array & operator[](const localIdx i) const =delete
View< const ValueType > view(std::pair< localIdx, localIdx > range) const &
Gets a sub view of the field as a view.
Definition array.hpp:329
ValueType ArrayValueType
Definition array.hpp:33
localIdx size() const
Gets the size of the field.
Definition array.hpp:270
bool empty() const
Checks if the field is empty.
Definition array.hpp:282
const Executor & exec() const
Gets the executor associated with the field.
Definition array.hpp:264
View< const ValueType > view() const &&=delete
Array(const Executor &exec, std::vector< ValueType > in)
Create a Array from a given Array of values on an executor.
Definition array.hpp:101
Array & operator[](const localIdx i)=delete
~Array()
Destroy the Array object.
Definition array.hpp:135
Array(const Executor &exec, const Array< ValueType > &in)
Create a Array as a copy of a Array on a specified executor.
Definition array.hpp:111
Array(const Array< ValueType > &rhs)
Copy constructor, creates a new field with the same size and data as the parsed field.
Definition array.hpp:119
Array(const Executor &exec, const ValueType *in, localIdx size, Executor hostExec=SerialExecutor())
Create a Array with a given size from existing memory on an executor.
Definition array.hpp:58
View< ValueType > view(std::pair< localIdx, localIdx > range) &&=delete
void operator=(const Array< ValueType > &rhs)
Assignment operator, Sets the field values to that of the parsed field.
Definition array.hpp:211
View< const ValueType > view(std::pair< localIdx, localIdx > range) const &&=delete
void resize(const localIdx size)
Resizes the field to a new size.
Definition array.hpp:225
void apply(func f)
applies a functor, transformation, to the field
Definition array.hpp:147
ValueType * data()
Direct access to the underlying field data.
Definition array.hpp:252
Reference executor for serial CPU execution.
#define NF_ERROR_EXIT(message)
Macro for printing an error message and aborting the program.
Definition error.hpp:108
#define NF_ASSERT(condition, message)
Macro for asserting a condition and printing an error message if the condition is false.
Definition error.hpp:142
#define NF_DEBUG_ASSERT(condition, message)
Macro for asserting a condition and printing an error message if the condition is false (only in debu...
Definition error.hpp:211
auto deepCopyVisitor(localIdx ssize, const ValueType *srcPtr, ValueType *dstPtr)
A helper function to simplify the common pattern of copying between and to executor.
Definition array.hpp:19
int32_t localIdx
Definition label.hpp:30
void map(ContType< ValueType > &cont, const Inner inner, std::pair< localIdx, localIdx > range={0, 0})
Map a field using a specific executor.
std::variant< SerialExecutor, CPUExecutor, GPUExecutor > Executor
Definition executor.hpp:16
void setContainer(ContType< ValueType > &cont, const View< const std::type_identity_t< ValueType > > view, std::pair< localIdx, localIdx > range={0, 0})
Set the container with a view of values using a specific executor.
void fill(ContType< ValueType > &cont, const std::type_identity_t< ValueType > value, std::pair< localIdx, localIdx > range={0, 0})
Fill the field with a vector value using a specific executor.
int32_t label
Definition label.hpp:24