OpenPFC  0.1.4
Phase Field Crystal simulation framework
Loading...
Searching...
No Matches
multi_index.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
32#ifndef PFC_MULTI_INDEX_HPP
33#define PFC_MULTI_INDEX_HPP
34
35#include <array>
36#include <iostream>
37#include <vector>
38
39namespace pfc {
40
51template <size_t D> class MultiIndex {
52private:
53 const std::array<int, D> m_begin;
54 const std::array<int, D> m_size;
55 const std::array<int, D> m_end;
56 const size_t m_linear_begin;
58 const size_t
59 m_linear_end;
60 const size_t m_linear_size;
61
62 std::array<int, D> calculate_end(std::array<int, D> begin,
63 std::array<int, D> size) {
64 std::array<int, D> end;
65 for (size_t i = 0; i < D; i++) end[i] = begin[i] + size[i] - 1;
66 return end;
67 }
68
69public:
77 MultiIndex(std::array<int, D> size,
78 std::array<int, D> offset = std::array<int, D>())
79 : m_begin(offset), m_size(size), m_end(calculate_end(m_begin, m_size)),
80 m_linear_begin(to_linear(m_begin)), m_linear_end(to_linear(m_end)),
81 m_linear_size(m_linear_end - m_linear_begin + 1) {}
82
83 const std::array<int, D> &get_begin() const { return m_begin; }
84 const std::array<int, D> &get_size() const { return m_size; }
85 const std::array<int, D> &get_end() const { return m_end; }
86 const size_t &get_linear_begin() const { return m_linear_begin; }
87 const size_t &get_linear_size() const { return m_linear_size; }
88 const size_t &get_linear_end() const { return m_linear_end; }
89
97 size_t to_linear(const std::array<int, D> &indices) const {
98 size_t linear_index = indices[0] - m_begin[0];
99 size_t multiplier = 1;
100 for (size_t i = 1; i < D; ++i) {
101 multiplier *= m_size[i - 1];
102 linear_index += (indices[i] - m_begin[i]) * multiplier;
103 }
104 return linear_index;
105 }
106
115 std::array<int, D> to_multi(size_t idx) const {
116 std::array<int, D> indices;
117 for (size_t i = 0; i < D; ++i) {
118 indices[i] = (idx % m_size[i]) + m_begin[i];
119 idx /= m_size[i];
120 }
121 return indices;
122 }
123
130 bool inbounds(const std::array<int, D> &indices) const {
131 for (size_t i = 0; i < D; ++i) {
132 if (indices[i] < m_begin[i] || indices[i] > m_end[i]) {
133 return false;
134 }
135 }
136 return true;
137 }
138
146 friend std::ostream &operator<<(std::ostream &os, const MultiIndex<D> &index) {
147 os << "MultiIndex set with " << D << " dimensions (indices from {";
148 for (size_t i = 0; i < D - 1; i++) os << index.m_begin[i] << ",";
149 os << index.m_begin[D - 1] << "} to {";
150 for (size_t i = 0; i < D - 1; i++) os << index.m_end[i] << ",";
151 os << index.m_end[D - 1] << "}, size {";
152 for (size_t i = 0; i < D - 1; i++) os << index.m_size[i] << ",";
153 os << index.m_size[D - 1] << "}, linear size " << index.m_linear_size << ")";
154 return os;
155 }
156
160 class Iterator {
161 private:
162 std::array<int, D> m_indices;
163 const MultiIndex &m_multi_index;
164 size_t m_linear_index;
165
166 public:
174 Iterator(std::array<int, D> indices, const MultiIndex &multi_index)
175 : m_indices(indices), m_multi_index(multi_index) {
176 m_linear_index = m_multi_index.to_linear(indices);
177 }
178
187 : m_multi_index(multi_index), m_linear_index(linear_index) {
188 m_indices = m_multi_index.to_multi(linear_index);
189 }
190
197 std::array<int, D> &operator*() { return m_indices; }
198
205 m_linear_index++;
206 for (size_t i = 0; i < D; i++) {
207 m_indices[i]++;
208 if (m_indices[i] > m_multi_index.m_end[i]) {
209 m_indices[i] = m_multi_index.m_begin[i];
210 } else {
211 break;
212 }
213 }
214 return *this;
215 }
216
223 Iterator copy(*this);
224 ++(*this);
225 return copy;
226 }
227
240 Iterator operator-(int n) const {
241 return Iterator(m_linear_index - n, m_multi_index);
242 }
243
250 bool operator!=(const Iterator &other) const {
251 return m_linear_index != other.m_linear_index;
252 }
253
260 bool operator==(const Iterator &other) const {
261 return m_linear_index == other.m_linear_index;
262 }
263
269 operator size_t() const { return m_linear_index; }
270
277 operator std::array<int, D>() const { return m_indices; }
278
284 size_t get_linear_index() const { return m_linear_index; }
285
294 friend std::ostream &operator<<(std::ostream &os, const Iterator &it) {
295 os << "{";
296 for (size_t i = 0; i < D - 1; i++) os << it.m_indices[i] << ", ";
297 os << it.m_indices[D - 1] << "}";
298 return os;
299 }
300 };
301
302 friend class Iterator;
303
309 Iterator begin() { return Iterator(m_linear_begin, *this); }
310
316 Iterator end() { return Iterator(m_linear_end + 1, *this); }
317
323 Iterator begin() const { return Iterator(m_linear_begin, *this); }
324
330 Iterator end() const { return Iterator(m_linear_end + 1, *this); }
331
339 Iterator from(std::array<int, D> from) { return Iterator(from, *this); }
340
352 Iterator from(size_t from) { return Iterator(from, *this); }
353};
354
355} // namespace pfc
356
357#endif
Iterator class for iterating over multi-dimensional indices.
Definition multi_index.hpp:160
bool operator!=(const Iterator &other) const
Compares two iterators for inequality.
Definition multi_index.hpp:250
size_t get_linear_index() const
Returns the current linear index.
Definition multi_index.hpp:284
Iterator operator++(int)
Advances the iterator to the next position (post-increment).
Definition multi_index.hpp:222
Iterator operator-(int n) const
Subtraction operator for the Iterator class.
Definition multi_index.hpp:240
Iterator & operator++()
Advances the iterator to the next position.
Definition multi_index.hpp:204
Iterator(std::array< int, D > indices, const MultiIndex &multi_index)
Constructs an Iterator object with the specified indices and MultiIndex object.
Definition multi_index.hpp:174
Iterator(int linear_index, const MultiIndex &multi_index)
Constructs an Iterator object with the specified linear index and MultiIndex object.
Definition multi_index.hpp:186
std::array< int, D > & operator*()
Dereferences the iterator to obtain the current multi-dimensional indices.
Definition multi_index.hpp:197
bool operator==(const Iterator &other) const
Compares two iterators for equality.
Definition multi_index.hpp:260
friend std::ostream & operator<<(std::ostream &os, const Iterator &it)
Outputs the current multi-dimensional indices to the specified output stream.
Definition multi_index.hpp:294
MultiIndex class for iterating over multi-dimensional indices.
Definition multi_index.hpp:51
bool inbounds(const std::array< int, D > &indices) const
Checks whether given indices are in bounds or not.
Definition multi_index.hpp:130
size_t to_linear(const std::array< int, D > &indices) const
Converts a multi-dimensional index to its corresponding linear index.
Definition multi_index.hpp:97
Iterator end()
Returns an iterator pointing to the end of the range.
Definition multi_index.hpp:316
std::array< int, D > to_multi(size_t idx) const
Converts a linear index to its corresponding multi-dimensional indices.
Definition multi_index.hpp:115
Iterator from(std::array< int, D > from)
Returns an iterator starting from the specified multi-dimensional indices.
Definition multi_index.hpp:339
Iterator begin()
Returns an iterator pointing to the beginning of the range.
Definition multi_index.hpp:309
Iterator end() const
Returns a const iterator pointing to the end of the range.
Definition multi_index.hpp:330
friend std::ostream & operator<<(std::ostream &os, const MultiIndex< D > &index)
Outputs the index to the specified output stream.
Definition multi_index.hpp:146
Iterator begin() const
Returns a const iterator pointing to the beginning of the range.
Definition multi_index.hpp:323
Iterator from(size_t from)
Returns an iterator starting from the specified linear index.
Definition multi_index.hpp:352
MultiIndex(std::array< int, D > size, std::array< int, D > offset=std::array< int, D >())
Constructs a MultiIndex object with the specified offset and size in each dimension.
Definition multi_index.hpp:77
Represents the global simulation domain (the "world").
Definition world.hpp:91
const Int3 m_size
Grid dimensions: {nx, ny, nz}.
Definition world.hpp:94