Execution and fields

These types connect logical fields to host or device execution. Backend setup and support constraints belong in the GPU path decision guide; halo layout choices are explained in Halo exchange.

pfc::data::Field

template<typename T, typename MemorySpace = pfc::HostSpace>
class Field

The one owning field container: DataBuffer + Box3i + halo + geometry-by-value.

Logical indices (i, j, k) are local (0-based on the owned box). Halo cells are addressable in [-halo, n + halo) on every axis, exactly as the legacy PaddedBrick.

Template Parameters:
  • T – Element type (e.g. double, std::complex<double>).

  • MemorySpace – Placement tag (HostSpace default; CUDASpace/HIPSpace from the runtime headers). Selects the DataBuffer backend via memory_space_to_backend_t.

Public Functions

inline Field(const pfc::Domain &domain, const pfc::Box3i &owned_box, int halo_width = 0)

Construct from the global Domain, the local owned index box, and a halo width. Allocates prod(size + 2*halo) zero-initialized cells.

halo_width is both the storage padding and the default iteration halo (PaddedBrick convention). Prefer the four-argument overload when migrating unpadded LocalField face-halo layouts (storage 0, iteration n).

Throws:

std::invalid_argument – on a negative halo or an inconsistent box.

inline Field(const pfc::Domain &domain, const pfc::Box3i &owned_box, int storage_halo, int iteration_halo)

Construct with independent storage padding and iteration halo.

  • storage_halo sizes the buffer (prod(size + 2*storage_halo)).

  • iteration_halo is what halo_width() / for_each_interior report — matching LocalField’s metadata halo on an unpadded buffer.

Face-halo FD stacks use storage_halo=0 and iteration_halo=order/2. PaddedBrick-style fields use equal values for both.

inline std::size_t size() const noexcept

Total allocated cells, including halo padding.

inline std::vector<T> &vec()

Host std::vector view of the buffer (FFT / legacy APIs).

Note

HostSpace only — device-backed fields have no host std::vector primary storage.

inline pfc::field::FieldView<T> view() const noexcept

Read-only non-owning view (host space only): data + local extents + spacing + origin of the local box’s low corner.

inline pfc::field::FieldOutput<T> output() noexcept

Mutable non-owning view over the storage (host space only).

inline const pfc::Box3i &box() const noexcept

Owned (interior) index box, in global index coordinates.

inline int storage_halo() const noexcept

Storage padding width (cells added on each side of the owned box).

inline int halo_width() const noexcept

Iteration / stencil halo (LocalField-compatible).

For padded fields this equals storage_halo(). For unpadded face-halo layouts it is the metadata width used by for_each_interior and FDGradient factories, while storage stays tightly packed.

inline pfc::Int3 local_size() const noexcept

Per-axis count of owned cells (halo excluded).

inline pfc::Int3 size3() const noexcept

LocalField-compatible alias of local_size().

inline pfc::Int3 global_size() const noexcept

Global domain extents {Nx, Ny, Nz} (LocalField-compatible).

inline pfc::Int3 lower_global() const noexcept

Global index of local (0,0,0) (LocalField-compatible).

inline int padded_extent(int axis) const noexcept

Per-axis padded extent (owned + both storage-halo slabs).

inline pfc::Int3 global(int i, int j, int k) const noexcept

Global index (gi, gj, gk) of local logical (i, j, k).

inline pfc::Real3 coords(int i, int j, int k) const noexcept

Physical coordinates of local logical (i, j, k).

template<typename Fn>
inline void for_each_owned(Fn &&fn) const

Visit every owned cell in x-fastest order.

Callable may be any of (auto-detected):

  • void(int i, int j, int k)

  • void(double x, double y, double z, T value) (LocalField-compatible)

  • void(const Real3& x, T value) (LocalField-compatible)

template<typename Fn>
inline void for_each_interior(Fn &&fn) const

Iterate interior [hw, n-hw) per axis (LocalField-compatible).

Callable may be either of:

  • void(double x, double y, double z, T value)

  • void(const Real3& x, T value)

template<typename Fn>
inline void apply(Fn &&fn)

Fill every owned cell by sampling fn at its physical coords. Accepts T(double,double,double) or T(const Real3&). A host-side write, so the device copy (if any) is marked stale.

inline const Residency &residency() const noexcept

Host/device coherence state (see residency.hpp).

inline void note_device_write() noexcept

Record that a device kernel wrote the device buffer (host mirror stale).

inline void note_host_write() noexcept

Record a host-side write (device mirror stale). Public for axpy helpers.

inline void sync_to_device()

Push the host mirror to the device buffer when the device copy is stale. No-op for a host-space field. Call before a device kernel reads this field &#8212; the sync the audit-4.1 bug omitted.

template<typename Fn>
inline void with_host_view(Fn &&fn)

Bracket a host-side access. Ensures the host data is current (pulling device->host for a device field), invokes fn(T* data, std::size_t size) over the padded host buffer, then marks the host side authoritative (device copy stale).

Public Static Attributes

static constexpr bool is_host_space

True when this field’s memory space is host-accessible (no device mirror).