OpenPFC  0.1.4
Phase Field Crystal simulation framework
Loading...
Searching...
No Matches
array.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2025 VTT Technical Research Centre of Finland Ltd
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
33#ifndef PFC_ARRAY_HPP
34#define PFC_ARRAY_HPP
35
37#include "fft.hpp"
38#include "multi_index.hpp"
40#include "utils/show.hpp"
41#include "utils/typename.hpp"
42#include <algorithm>
43#include <array>
44#include <cmath>
45#include <complex>
46#include <functional>
47#include <type_traits>
48#include <typeinfo>
49#include <vector>
50
51namespace pfc {
52
53template <typename T, size_t D> class Array {
54
55private:
56 const MultiIndex<D> index;
57 std::vector<T> data;
58
65 Array(const FFT &fft, std::true_type)
66 : index(get_outbox(fft).size, get_outbox(fft).low) {}
67
74 Array(const FFT &fft, std::false_type)
75 : index(get_inbox(fft).size, get_inbox(fft).low) {}
76
77 // Custom type trait to check if a type is complex
78 template <typename U> struct is_complex : std::false_type {};
79 template <typename U> struct is_complex<std::complex<U>> : std::true_type {};
80
81public:
89 Array(const std::array<int, D> &dimensions,
90 const std::array<int, D> &offsets = {0})
91 : index(dimensions, offsets) {
92 data.resize(index.get_linear_size());
93 }
94
104 Array(const Decomposition &decomp) : Array(decomp, is_complex<T>()) {
105 data.resize(index.get_linear_size());
106 }
107
108 typename std::vector<T>::iterator begin() { return data.begin(); }
109 typename std::vector<T>::iterator end() { return data.end(); }
110 typename std::vector<T>::const_iterator begin() const { return data.begin(); }
111 typename std::vector<T>::const_iterator end() const { return data.end(); }
112
118 const MultiIndex<D> &get_index() const { return index; }
119
125 std::vector<T> &get_data() { return data; }
126
127 T &operator[](const std::array<int, D> &indices) {
128 return operator[](index.to_linear(indices));
129 }
130
131 T &operator[](int idx) { return data.operator[](idx); }
132
133 T &operator()(const std::array<int, D> &indices) { return operator[](indices); }
134
140 std::array<int, D> get_size() const { return index.get_size(); }
141
147 std::array<int, D> get_offset() const { return index.get_offset(); }
148
156 bool inbounds(const std::array<int, D> &indices) {
157 return index.inbounds(indices);
158 }
159
167 template <typename Func> void apply(Func &&func) {
168 static_assert(
169 std::is_convertible_v<std::invoke_result_t<Func, std::array<int, D>>, T>,
170 "Func must be invocable with std::array<int, D> and return a type "
171 "convertible to T");
172 auto it = index.begin();
173 for (T &element : get_data())
174 element = std::invoke(std::forward<Func>(func), *(it++));
175 }
176
182 operator std::vector<T> &() { return data; }
183
184 void set_data(const std::vector<T> &new_data) {
185 if (new_data.size() != index.get_linear_size()) {
186 throw std::runtime_error("Dimension mismatch, set_data failed");
187 }
188 this->data = std::move(new_data);
189 }
190
198 friend std::ostream &operator<<(std::ostream &os, const Array<T, D> &array) {
199 const MultiIndex<D> &index = array.get_index();
200 os << "Array<" << TypeName<T>::get() << "," << D
201 << ">(begin = " << utils::array_to_string(index.get_begin())
202 << ", end = " << utils::array_to_string(index.get_end())
203 << ", size = " << utils::array_to_string(index.get_size())
204 << ", linear_size = " << index.get_linear_size() << ")";
205 return os;
206 }
207};
208
209template <typename T, size_t D> void show(Array<T, D> &array) {
210 utils::show(array.get_data(), array.get_index().get_size(),
211 array.get_index().get_begin());
212}
213
214} // namespace pfc
215
216#endif
Convert std::array to string representation.
Definition array.hpp:53
friend std::ostream & operator<<(std::ostream &os, const Array< T, D > &array)
Outputs the array to the specified output stream.
Definition array.hpp:198
std::array< int, D > get_size() const
Get the size object.
Definition array.hpp:140
bool inbounds(const std::array< int, D > &indices)
Checks if the specified indices are in bounds.
Definition array.hpp:156
const MultiIndex< D > & get_index() const
Get the index object.
Definition array.hpp:118
std::array< int, D > get_offset() const
Get the offset object.
Definition array.hpp:147
std::vector< T > & get_data()
Get the data object.
Definition array.hpp:125
Array(const Decomposition &decomp)
Constructs an Array object from Decomposition object. Array dimension and offset depends from the typ...
Definition array.hpp:104
Array(const std::array< int, D > &dimensions, const std::array< int, D > &offsets={0})
Constructs an Array object with the specified dimensions and offsets.
Definition array.hpp:89
void apply(Func &&func)
Applies the specified function to each element of the array.
Definition array.hpp:167
Domain decomposition for parallel MPI simulations.
Fast Fourier Transform interface for spectral methods.
Multi-dimensional indexing utilities.
Pretty-print 3D arrays to console.
Definition typename.hpp:48
Describes a static, pure partitioning of the global simulation domain into local subdomains.
Definition decomposition.hpp:182
FFT class for distributed-memory parallel Fourier transforms.
Definition fft.hpp:248
Represents the global simulation domain (the "world").
Definition world.hpp:91
Get human-readable type names at runtime.