Fields#
- class pystencils.Field(field_name, field_type, dtype, layout, shape, strides)#
With fields one can formulate stencil-like update rules on structured grids. This Field class knows about the dimension, memory layout (strides) and optionally about the size of an array.
- Creating Fields:
The preferred method to create fields is the
fields
function. Alternatively one can use one of the static functionsField.create_generic
,Field.create_from_numpy_array
andField.create_fixed_size
. Don’t instantiate the Field directly! Fields can be created with known or unknown shapes:If you want to create a kernel with fixed loop sizes i.e. the shape of the array is already known. This is usually the case if just-in-time compilation directly from Python is done. (see
Field.create_from_numpy_array
create a more general kernel that works for variable array sizes. This can be used to create kernels beforehand for a library. (see
Field.create_generic
)
- Dimensions and Indexing:
A field has spatial and index dimensions, where the spatial dimensions come first. The interpretation is that the field has multiple cells in (usually) two or three dimensional space which are looped over. Additionally N values are stored per cell. In this case spatial_dimensions is two or three, and index_dimensions equals N. If you want to store a matrix on each point in a two dimensional grid, there are four dimensions, two spatial and two index dimensions:
len(arr.shape) == spatial_dims + index_dims
The shape of the index dimension does not have to be specified. Just use the ‘index_dimensions’ parameter. However, it is good practice to define the shape, since out of bounds accesses can be directly detected in this case. The shape can be passed with the ‘index_shape’ parameter of the field creation functions.
When accessing (indexing) a field the result is a
Field.Access
which is derived from sympy Symbol. First specify the spatial offsets in [], then in case index_dimension>0 the indices in () e.g.f[-1,0,0](7)
- Staggered Fields:
Staggered fields are used to store a value on a second grid shifted by half a cell with respect to the usual grid.
The first index dimension is used to specify the position on the staggered grid (e.g. 0 means half-way to the eastern neighbor, 1 is half-way to the northern neighbor, etc.), while additional indices can be used to store multiple values at each position.
- Example using no index dimensions:
>>> a = np.zeros([10, 10]) >>> f = Field.create_from_numpy_array("f", a, index_dimensions=0) >>> jacobi = (f[-1,0] + f[1,0] + f[0,-1] + f[0,1]) / 4
- Examples for index dimensions to create LB field and implement stream pull:
>>> from pystencils import Assignment >>> stencil = np.array([[0,0], [0,1], [0,-1]]) >>> src, dst = fields("src(3), dst(3) : double[2D]") >>> assignments = [Assignment(dst[0,0](i), src[-offset](i)) for i, offset in enumerate(stencil)];
- Parameters:
field_name (
str
) – The field’s namefield_type (
FieldType
) – The kind of the fielddtype (
str
|type
|dtype
|PsType
|DynamicType
) – Data type of the field’s entrieslayout (
tuple
[int
,...
]) – Linearization order of the field’s spatial dimensionsshape – Total shape (spatial and index) of the field
strides – Linearization strides of the field
Types of Fields#
- class pystencils.FieldType(value)#
An enumeration.
Creating Fields#
Creates pystencils fields from a string description. |
|
Creates a generic field where the field size is not fixed i.e. can be called with arrays of different sizes. |
|
Creates a field with fixed sizes i.e. can be called only with arrays of the same size and layout. |
|
Creates a field based on the layout, data type, and shape of a given numpy array. |
|
Properties#
Name and Element Type#
Dimensionality, Shape, and Memory Layout#
Accessing Field Entries#
Like neighbor, but returns the entire vector/tensor stored at offset. |
|
Call self as a function. |
|
If this field is a staggered field, it can be accessed using half-integer offsets. |
|
Like staggered_access, but returns the entire vector/tensor stored at offset. |
- class pystencils.field.Field.Access(name, *args, **kwargs)#
Class representing a relative access into a
Field
.This class behaves like a normal sympy Symbol, it is actually derived from it. One can built up sympy expressions using field accesses, solve for them, etc.
Examples
>>> vector_field_2d = fields("v(2): double[2D]") # create a 2D vector field >>> northern_neighbor_y_component = vector_field_2d[0, 1](1) >>> northern_neighbor_y_component v_N^1 >>> central_y_component = vector_field_2d(1) >>> central_y_component v_C^1 >>> central_y_component.get_shifted(1, 0) # move the existing access v_E^1 >>> central_y_component.at_index(0) # change component v_C^0
- Parameters:
name (str)