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