51#ifndef PFC_DISCRETE_FIELD_HPP
52#define PFC_DISCRETE_FIELD_HPP
259 const std::array<double, D> m_origin;
260 const std::array<double, D>
262 const std::array<double, D> m_coords_low;
263 const std::array<double, D> m_coords_high;
269 std::array<double, D> calculate_coords_low(
const std::array<int, D> &offset) {
271 for (
size_t i = 0;
i < D;
i++)
280 std::array<double, D> calculate_coords_high(
const std::array<int, D> &offset,
281 const std::array<int, D> &size) {
283 for (
size_t i = 0;
i < D;
i++)
329 const std::array<int, D> &
offsets,
330 const std::array<double, D> &
origin,
334 m_coords_low(calculate_coords_low(
offsets)),
335 m_coords_high(calculate_coords_high(
offsets, dimensions)) {}
363 const std::array<double, D> &
get_origin()
const {
return m_origin; }
364 const std::array<double, D> &get_discretization()
const {
365 return m_discretization;
367 const std::array<double, D> &get_coords_low()
const {
return m_coords_low; }
368 const std::array<double, D> &get_coords_high()
const {
return m_coords_high; }
370 Array<T, D> &get_array() {
return m_array; }
371 const Array<T, D> &get_array()
const {
return m_array; }
372 const MultiIndex<D> &get_index() {
return get_array().get_index(); }
373 const MultiIndex<D> &get_index()
const {
return get_array().get_index(); }
374 std::vector<T> &get_data() {
return get_array().get_data(); }
382 T &
operator[](
const std::array<int, D> &indices) {
return get_array()[indices]; }
398 std::array<double, D>
400 std::array<double, D> coordinates;
401 for (
size_t i = 0;
i < D; ++
i) {
402 coordinates[
i] = m_origin[
i] + indices[
i] * m_discretization[
i];
415 std::array<int, D> indices;
416 for (
size_t i = 0;
i < D; ++
i) {
417 indices[
i] =
static_cast<int>(
418 std::round((coordinates[
i] - m_origin[
i]) / m_discretization[
i]));
430 for (
size_t i = 0;
i < D;
i++) {
431 if (m_coords_low[
i] >
coords[
i] ||
coords[
i] >= m_coords_high[
i])
return false;
458 [[deprecated(
"Use pfc::interpolate(field, coords) free function instead")]] T &
464 using FunctionND = std::function<T(std::array<double, D>)>;
465 using Function1D = std::function<T(
double)>;
466 using Function2D = std::function<T(
double,
double)>;
467 using Function3D = std::function<T(
double,
double,
double)>;
480 std::is_convertible_v<
481 std::invoke_result_t<FunctionND, std::array<double, D>>, T>,
482 "Func must be invocable with std::array<double, D> and return a type "
485 for (T &
element : get_data()) {
486 element = std::invoke(std::forward<FunctionND>(
func),
503 for (T &
element : get_data()) {
521 for (T &
element : get_data()) {
577 for (T &
element : get_data()) {
589 operator std::vector<T> &() {
return get_data(); }
590 operator std::vector<T> &()
const {
return get_data(); }
597 const std::array<int, D> &
get_size()
const {
return get_index().get_size(); }
599 const std::array<int, D> &get_offset()
const {
return get_index().get_begin(); }
601 void set_data(
const std::vector<T> &data) { get_array().set_data(data); }
615 <<
">(begin = " << utils::array_to_string(index.get_begin())
616 <<
", end = " << utils::array_to_string(index.get_end())
617 <<
", size = " << utils::array_to_string(index.get_size())
618 <<
", linear_size = " << index.get_linear_size()
619 <<
", origin = " << utils::array_to_string(field.get_origin())
620 <<
", discretization = " << utils::array_to_string(field.get_discretization())
621 <<
", coords_low = " << utils::array_to_string(field.get_coords_low())
622 <<
", coords_high = " << utils::array_to_string(field.get_coords_high());
690template <
typename T,
size_t D>
691inline T &interpolate(DiscreteField<T, D> &field,
692 const std::array<double, D> &coordinates) {
693 return field.get_array()[field.map_coordinates_to_indices(coordinates)];
723template <
typename T,
size_t D>
724inline const T &interpolate(
const DiscreteField<T, D> &field,
725 const std::array<double, D> &coordinates) {
728 return const_cast<DiscreteField<T, D> &
>(field)
729 .get_array()[field.map_coordinates_to_indices(coordinates)];
739template <
typename T,
size_t D,
typename Function>
741 field.apply(std::forward<Function>(
func));
744template <
typename T,
size_t D>
void show(DiscreteField<T, D> &field) {
745 utils::show(field.get_array().get_data(), field.get_index().get_size(),
746 field.get_index().get_begin());
Multi-dimensional array container for field data.
Definition discrete_field.hpp:256
const std::array< double, D > & get_origin() const
Constructs a DiscreteField from an Decomposition object.
Definition discrete_field.hpp:363
std::array< int, D > map_coordinates_to_indices(const std::array< double, D > &coordinates) const
Maps coordinates to indices in the field.
Definition discrete_field.hpp:414
friend std::ostream & operator<<(std::ostream &os, const DiscreteField< T, D > &field)
Outputs the discrete field to the specified output stream.
Definition discrete_field.hpp:610
T & operator[](const std::array< int, D > &indices)
Returns the element at the specified index.
Definition discrete_field.hpp:382
T & interpolate(const std::array< double, D > &coordinates)
Interpolate field value at physical coordinates (nearest-neighbor)
Definition discrete_field.hpp:459
bool inbounds(const std::array< double, D > &coords)
Checks if the given coordinates are within the bounds of the field.
Definition discrete_field.hpp:429
const std::array< int, D > & get_size() const
Get the size of the field.
Definition discrete_field.hpp:597
void apply(Function1D &&func)
Applies the given 1D function to each element of the field.
Definition discrete_field.hpp:501
std::array< double, D > map_indices_to_coordinates(const std::array< int, D > &indices) const
Maps indices to coordinates in the field.
Definition discrete_field.hpp:399
void apply(FunctionND &&func)
Applies the given function to each element of the field.
Definition discrete_field.hpp:478
void apply(Function2D &&func)
Applies the given 2D function to each element of the field.
Definition discrete_field.hpp:519
T & operator[](size_t idx)
Returns the element at the specified index.
Definition discrete_field.hpp:390
Mathematical and physical constants.
Pretty-print 3D arrays to console.
Definition typename.hpp:48
Represents the global simulation domain (the "world").
Definition world.hpp:91
World class definition and unified interface.