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