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