OpenPFC  0.1.4
Phase Field Crystal simulation framework
Loading...
Searching...
No Matches
field.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
4#pragma once
5
50#include "openpfc/core/csys.hpp"
53#include <array>
54#include <cassert>
55#include <functional>
56#include <vector>
57
58namespace pfc {
59namespace field {
60
62using pfc::world::get_total_size;
63
64template <typename T> struct Field {
65 std::vector<T> m_data;
66 const World &m_world;
67
68 Field(const World &world) : m_data(get_total_size(world)), m_world(world) {
69 assert(m_data.size() > 0);
70 }
71
72 Field(const Field &) = delete;
73 Field &operator=(const Field &) = delete;
74
75 Field(Field &&) = default;
76 Field &operator=(Field &&) = delete;
77
78 T &operator[](size_t i) { return m_data[i]; }
79
80 const T &operator[](size_t i) const { return m_data[i]; }
81};
82
83template <typename T> inline Field<T> create(const World &world) {
84 return Field<T>(world);
85}
86
87template <typename T> inline const auto &get_data(const Field<T> &field) {
88 return field.m_data;
89}
90
91template <typename T> inline auto &get_data(Field<T> &field) { return field.m_data; }
92
93template <typename T> inline const auto &get_world(const Field<T> &field) {
94 return field.m_world;
95}
96
97template <typename T> Field<T> create(const World &world, std::vector<T> &&data) {
98 Field<T> f(world);
99 if (data.size() != get_total_size(world)) {
100 throw std::runtime_error("Moved-in data size mismatch.");
101 }
102 f.m_data = std::move(data);
103 return f;
104}
105
106template <typename T>
107Field<T> create(const World &world, const std::vector<T> &data) {
108 Field<T> f(world);
109 if (data.size() != get_total_size(world)) {
110 throw std::runtime_error("Copied-in data size mismatch.");
111 }
112 std::copy(data.begin(), data.end(), f.m_data.begin());
113 return f;
114}
115
116template <typename T, typename Func,
117 typename = std::enable_if_t<std::is_invocable_v<Func, Real3>>>
118Field<T> create(const World &world, Func &&func) {
119 Field<T> f(world);
120 apply(f, std::forward<Func>(func));
121 return f;
122}
123
124template <typename T, typename Func> void apply(Field<T> &f, Func &&func) {
125
126 // Static assertion to ensure func is callable with (double, double, double)
127 static_assert(std::is_invocable_v<Func, Real3>,
128 "Func must be callable with (Real3 = std::array<double, 3>)");
129
130 auto &data = get_data(f);
131 const auto &world = get_world(f);
132 const auto &cs = get_coordinate_system(world);
133
134 Int3 low = get_lower(world);
135 Int3 high = get_upper(world);
136
137 size_t idx = 0;
138 for (int k = low[2]; k <= high[2]; ++k) {
139 for (int j = low[1]; j <= high[1]; ++j) {
140 for (int i = low[0]; i <= high[0]; ++i) {
141 data[idx++] = std::invoke(func, to_coords(cs, {i, j, k}));
142 }
143 }
144 }
145}
146
147template <typename T> auto indices(const Field<T> &f) {
148 struct IndexRange {
149 size_t size;
150 struct Iterator {
151 size_t i;
152 bool operator!=(const Iterator &other) const { return i != other.i; }
153 size_t operator*() const { return i; }
154 Iterator &operator++() {
155 ++i;
156 return *this;
157 }
158 };
159 Iterator begin() const { return {0}; }
160 Iterator end() const { return {size}; }
161 };
162 return IndexRange{get_data(f).size()};
163}
164
165} // namespace field
166} // namespace pfc
Core type definitions for World parameters.
Extensible coordinate system framework.
const Real3 to_coords(const CartesianCS &cs, const Int3 &idx) noexcept
Convert grid indices to physical coordinates.
Definition csys.hpp:291
const auto & get_world(const Decomposition &decomposition) noexcept
Alias for get_global_world()
Definition decomposition.hpp:240
const auto & get_upper(const CartesianWorld &world) noexcept
Get the upper bounds of the world in a specific dimension.
Definition world_queries.hpp:168
auto create(const World< T > &world, const heffte::box3d< int > &box)
Construct a new World object from an existing one and a box.
Definition decomposition.hpp:62
const auto & get_lower(const CartesianWorld &world) noexcept
Get the lower bounds of the world.
Definition world_queries.hpp:149
const auto & get_coordinate_system(const World< T > &world) noexcept
Get the coordinate system of the world.
Definition world_queries.hpp:192
Definition field.hpp:64
Represents the global simulation domain (the "world").
Definition world.hpp:91
World class definition and unified interface.