Skip to main content

Field Views

C++: phynexis::fields::{FieldViewBase, ScalarFieldView, Vec3FieldView, Vec4FieldView, Vec6FieldView, VecNFieldView, VecXFieldView} Python: phynexis.fields Headers: src/fields/views/*.hpp

Field views are non-owning wrappers over existing scalar/vector fields. They provide a unified, type-safe interface for reading and writing field data without copying memory. Views are commonly used for SOA (Structure of Arrays) access patterns — e.g., treating three scalar fields x, y, z as a single vector field.

All view types inherit from FieldViewBase.

Type Summary

Python ClassC++ TypeElement / Component Type
FieldViewBaseFieldViewBase— (abstract)
ScalarFieldView (alias FieldView)ScalarFieldView<Double>float
Int32FieldView (alias Idx32FieldView)ScalarFieldView<Int32>int (32-bit)
Int64FieldView (alias Idx64FieldView)ScalarFieldView<Int64>int (64-bit)
BoolFieldViewScalarFieldView<bool>bool
Vec3dFieldVec3FieldView<Double>float
Vec3iFieldVec3FieldView<Int32>int (32-bit)
Vec4dField (alias QuaternionField)Vec4FieldView<Double>float
Vec6dFieldVec6FieldView<Double>float
VecNdFieldVecNFieldView<Double>float
VecXdFieldViewVecXFieldView<Double>float
VecXiFieldViewVecXFieldView<Int32>int (32-bit)

Common API (FieldViewBase)

All views share the following methods.

is_valid()

Returns True if the view references valid (non-null) underlying fields.

__bool__()

Same as is_valid(). Allows if view: syntax.

size() / __len__()

Returns the number of elements (rows) in the view.

empty()

Returns True if size() == 0.

get_name(delimiter)

Returns the base name of the view. For compound views (Vec3, Vec4, etc.), this strips the component suffix using the given delimiter.

Parameters:

ParameterTypeDefaultDescription
delimiterstr"."Delimiter used to split component names

Known issue: The delimiter default is not automatically supplied from Python. Pass it explicitly: view.get_name(".").

get_field_names()

Returns a list[str] of the underlying field names.

ScalarFieldView

Single-field view. Wraps one Field<T> and provides direct element access.

Constructors

SignatureDescription
ScalarFieldView()Empty (invalid) view.
ScalarFieldView(field)View over a ScalarField (or FieldBase).

Example:

import phynexis
F = phynexis.fields

fm = F.FieldManager()
h = fm.create_field(F.FieldMeta("temp", F.FieldType.Scalar, F.ValueType.Double))
f = fm.get_field(h)

view = F.ScalarFieldView(f)
print(view.size(), view.is_valid()) # 0 True

# Element access
view.resize(3)
view[0] = 1.0
view[1] = 2.0
print(view[0], view[1]) # 1.0 2.0

field_ptr()

Returns the underlying Field<T>* pointer.

field_ref()

Returns a reference to the underlying field. Same as dereferencing field_ptr().

data()

Returns a pointer to the raw data buffer. Unsafe from Python — use __getitem__ / __setitem__ instead.

__getitem__(idx) / __setitem__(idx, value)

Direct element read/write. No bounds checking; use with caution.

__getattr__(name)

Forwards unknown attribute access to the underlying field object. Allows calling field methods through the view.

Vec3FieldView

View over three scalar fields interpreted as (x, y, z) components.

Constructors

SignatureDescription
Vec3dField(x, y, z)View over three ScalarField (or FieldBase) objects.
Vec3iField(x, y, z)View over three Int32Field objects.

Example:

import phynexis
F = phynexis.fields

fm = F.FieldManager()
hx = fm.create_field(F.FieldMeta("pos.x", F.FieldType.Scalar, F.ValueType.Double))
hy = fm.create_field(F.FieldMeta("pos.y", F.FieldType.Scalar, F.ValueType.Double))
hz = fm.create_field(F.FieldMeta("pos.z", F.FieldType.Scalar, F.ValueType.Double))

x = fm.get_field(hx)
y = fm.get_field(hy)
z = fm.get_field(hz)

for f in [x, y, z]:
f.resize(3)

v3 = F.Vec3dField(x, y, z)
print(v3.size()) # 3
print(v3.get_name(".")) # "pos"

# Component access (returns ScalarFieldView)
print(v3.x().size()) # 3

# Indexed component access (returns scalar value)
print(v3.x(0)) # 0.0 (default-initialized)

# __getitem__ returns Vec3d (Double version only)
v3.x()[0] = 1.0
v3.y()[0] = 2.0
v3.z()[0] = 3.0
print(v3[0]) # Vec3d(1.0, 2.0, 3.0)

Component Access

MethodReturnsDescription
x()ScalarFieldViewView over the x-component field
y()ScalarFieldViewView over the y-component field
z()ScalarFieldViewView over the z-component field
x(i)float / intValue of x at index i
y(i)float / intValue of y at index i
z(i)float / intValue of z at index i

Vec4FieldView

View over four scalar fields interpreted as (w, x, y, z) components. Exposed as Vec4dField and aliased as QuaternionField.

Constructors

SignatureDescription
Vec4dField(w, x, y, z)View over four ScalarField (or FieldBase) objects.

Component Access

MethodReturnsDescription
w()ScalarFieldViewView over the w-component field
x()ScalarFieldViewView over the x-component field
y()ScalarFieldViewView over the y-component field
z()ScalarFieldViewView over the z-component field
w(i)floatValue of w at index i
x(i)floatValue of x at index i
y(i)floatValue of y at index i
z(i)floatValue of z at index i

Vec6FieldView

View over six scalar fields interpreted as symmetric tensor components (xx, yy, zz, xy, xz, yz).

Constructors

SignatureDescription
Vec6dField(xx, yy, zz, xy, xz, yz)View over six ScalarField (or FieldBase) objects.

Component Access

MethodReturnsDescription
xx()ScalarFieldViewView over the xx-component field
yy()ScalarFieldViewView over the yy-component field
zz()ScalarFieldViewView over the zz-component field
xy()ScalarFieldViewView over the xy-component field
xz()ScalarFieldViewView over the xz-component field
yz()ScalarFieldViewView over the yz-component field

Note: Indexed component access (xx(i), etc.) is not bound in Python.

VecNFieldView

View over N scalar fields of arbitrary dimension. Unlike Vec3/Vec4/Vec6, the dimension is determined at runtime by the number of fields passed.

Constructors

SignatureDescription
VecNdField()Empty (invalid) view.

Note: Constructors taking a field list (VecX<FieldBase*>) are not bound in Python because VecX<FieldBase*> is not exposed. Create views through FieldManager layouts or C++ APIs instead.

__getitem__(index)

Returns a ScalarFieldView over the field at the given index.

VecXFieldView

View over a VecXField<T> (ragged/jagged array field). Provides row-level access.

Constructors

SignatureDescription
VecXdFieldView(field)View over a VecXdField.
VecXiFieldView(field)View over a VecXiField.

__call__(i, j)

Access element at row i, column j. Returns a mutable reference.

vxf = F.VecXdField(3)
vxf.push_back(0, 1.0)
vxf.push_back(0, 2.0)

view = F.VecXdFieldView(vxf)
print(view(0, 0)) # 1.0
print(view(0, 1)) # 2.0

row_size(i)

Returns the number of elements in row i.

row_capacity(i)

Returns the allocated capacity of row i.

get_total_elements()

Returns the total number of stored elements across all rows.

__getitem__(i)

Returns a VecXFieldRowView<T> for row i.

Known Issues

get_name() requires explicit delimiter argument

The C++ default argument delimiter = "." is not propagated through pybind11. Always pass a delimiter string:

name = view.get_name(".") # OK
name = view.get_name() # TypeError

Status: noted

LinkedFieldRowView.data() may segfault

Iterating a LinkedFieldRowView returned from LinkedFieldView.get_targets() or get_sources() can crash. The underlying C++ RowView is a proxy type whose lifetime rules are not fully captured by the Python binding.

Workaround: Access individual elements by index instead of calling .data().

Status: noted

VecNFieldView list constructor not exposed

VecNdField(fields: list[FieldBase]) is not available because VecX<FieldBase*> is not registered with pybind11.

Workaround: Use default constructor; practical construction requires C++-side BoundLayout or FieldManager integration.

Status: noted

Vec6FieldView indexed accessors not bound

xx(i), yy(i), etc. are not exposed in Python. Use the component view (v6.xx()) and then index the ScalarFieldView.

Workaround:

v6.xx()[i] # instead of v6.xx(i)

Status: noted