# Field¶

class 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 functions `Field.create_generic`, `Field.create_from_numpy_array` and `Field.create_fixed_size`. Don’t instantiate the Field directly! Fields can be created with known or unknown shapes:

1. 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`

2. 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)];
```
static create_generic(field_name, spatial_dimensions, dtype=<class 'numpy.float64'>, index_dimensions=0, layout='numpy', index_shape=None, field_type=<FieldType.GENERIC: 0>)

Creates a generic field where the field size is not fixed i.e. can be called with arrays of different sizes

Parameters
• field_name – symbolic name for the field

• dtype – numpy data type of the array the kernel is called with later

• spatial_dimensions – see documentation of Field

• index_dimensions – see documentation of Field

• layout – tuple specifying the loop ordering of the spatial dimensions e.g. (2, 1, 0 ) means that the outer loop loops over dimension 2, the second outer over dimension 1, and the inner loop over dimension 0. Also allowed: the strings ‘numpy’ (0,1,..d) or ‘reverse_numpy’ (d, …, 1, 0)

• index_shape – optional shape of the index dimensions i.e. maximum values allowed for each index dimension, has to be a list or tuple

• field_type – besides the normal GENERIC fields, there are INDEXED fields that store indices of the domain that should be iterated over, BUFFER fields that are used to generate communication packing/unpacking kernels, and STAGGERED fields, which store values half-way to the next cell

Return type

`Field`

static create_from_numpy_array(field_name, array, index_dimensions=0, field_type=<FieldType.GENERIC: 0>)

Creates a field based on the layout, data type, and shape of a given numpy array.

Kernels created for these kind of fields can only be called with arrays of the same layout, shape and type.

Parameters
Return type

`Field`

static create_fixed_size(field_name, shape, index_dimensions=0, dtype=<class 'numpy.float64'>, layout='numpy', strides=None, field_type=<FieldType.GENERIC: 0>)

Creates a field with fixed sizes i.e. can be called only with arrays of the same size and layout

Parameters
Return type

`Field`

neighbor_vector(offset)

Like neighbor, but returns the entire vector/tensor stored at offset.

`interpolated_access` is similar to `Field.absolute_access()` except that it allows non-integer offsets and automatic handling of out-of-bound accesses.

Parameters
• offset (`Tuple`) – Tuple of spatial coordinates (can be floats)

• interpolation_mode – One of `pystencils.interpolation_astnodes.InterpolationMode`

• address_mode – How boundaries are handled can be ‘border’, ‘wrap’, ‘mirror’, ‘clamp’

• allow_textures – Allow implementation by texture accesses on GPUs

staggered_access(offset, index=None)

If this field is a staggered field, it can be accessed using half-integer offsets. For example, an offset of `(0, sp.Rational(1,2))` or `"E"` corresponds to the staggered point to the east of the cell center, i.e. half-way to the eastern-next cell. If the field stores more than one value per staggered point (e.g. a vector or a tensor), the index (integer or tuple of integers) refers to which of these values to access.

staggered_vector_access(offset)

Like staggered_access, but returns the entire vector/tensor stored at offset.

class 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
```
property field: pystencils.field.Field

Field that the Access points to

Return type

`Field`

property offsets: Tuple

Spatial offset as tuple

Return type

`Tuple`

property required_ghost_layers: int

Largest spatial distance that is accessed.

Return type

`int`

property nr_of_coordinates
property offset_name: str

Spatial offset as string, East-West for x, North-South for y and Top-Bottom for z coordinate.

Example

```>>> f = fields("f: double[2D]")
>>> f[1, 1].offset_name  # north-east
'NE'
```
Return type

`str`

property index

Value of index coordinates as tuple.

neighbor(coord_id, offset)

Returns a new Access with changed spatial coordinates.

Parameters

Example

```>>> f = fields('f: [2D]')
>>> f[0,0].neighbor(coord_id=1, offset=-1)
f_S
```
Return type

`Access`

get_shifted(*shift)

Returns a new Access with changed spatial coordinates

Example

```>>> f = fields("f: [2D]")
>>> f[0,0].get_shifted(1, 1)
f_NE
```
Return type

`Access`

at_index(*idx_tuple)

Returns new Access with changed index.

Example

```>>> f = fields("f(9): [2D]")
>>> f(0).at_index(8)
f_C^8
```
Return type

`Access`

property is_absolute_access: bool

Indicates if a field access is relative to the loop counters (this is the default) or absolute

Return type

`bool`

Returns a set of fields that the access depends on.

Return type
fields(description=None, index_dimensions=0, layout=None, field_type=<FieldType.GENERIC: 0>, **kwargs)

Creates pystencils fields from a string description.

Examples

Create a 2D scalar and vector field:
```>>> s, v = fields("s, v(2): double[2D]")
>>> assert s.spatial_dimensions == 2 and s.index_dimensions == 0
>>> assert (v.spatial_dimensions, v.index_dimensions, v.index_shape) == (2, 1, (2,))
```
Create an integer field of shape (10, 20):
```>>> f = fields("f : int32[10, 20]")
>>> f.has_fixed_shape, f.shape
(True, (10, 20))
```
Numpy arrays can be used as template for shape and data type of field:
```>>> arr_s, arr_v = np.zeros([20, 20]), np.zeros([20, 20, 2])
>>> s, v = fields("s, v(2)", s=arr_s, v=arr_v)
>>> assert s.index_dimensions == 0 and s.dtype.numpy_dtype == arr_s.dtype
>>> assert v.index_shape == (2,)
```
Format string can be left out, field names are taken from keyword arguments.
```>>> fields(f1=arr_s, f2=arr_s)
[f1: double[20,20], f2: double[20,20]]
```
The keyword names `index_dimension` and `layout` have special meaning, don’t use them for field names
```>>> f = fields(f=arr_v, index_dimensions=1)
>>> assert f.index_dimensions == 1
>>> f = fields("pdfs(19) : float32[3D]", layout='fzyx')
>>> f.layout
(2, 1, 0)
```
class FieldType(value)

An enumeration.
{"ft_lang_label":"__label__en","ft_lang_prob":0.6749393,"math_prob":0.94788677,"size":9266,"snap":"2021-43-2021-49","text_gpt3_token_len":2343,"char_repetition_ratio":0.14726841,"word_repetition_ratio":0.037861917,"special_character_ratio":0.26742932,"punctuation_ratio":0.15852205,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.9814208,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2021-10-16T11:41:17Z\",\"WARC-Record-ID\":\"<urn:uuid:d3914b7a-8f2e-4dbb-a055-5c06a45e622e>\",\"Content-Length\":\"53037\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:1155e15d-0b5f-4084-a028-c6a1e3ee75bc>\",\"WARC-Concurrent-To\":\"<urn:uuid:cf349882-6a2e-44c6-8b72-584e4daed411>\",\"WARC-IP-Address\":\"131.188.39.6\",\"WARC-Target-URI\":\"https://pycodegen.pages.i10git.cs.fau.de/pystencils/sphinx/field.html\",\"WARC-Payload-Digest\":\"sha1:BC6RKRLXNGPWAUTPUVAKFAB4ZXJSAHBE\",\"WARC-Block-Digest\":\"sha1:NEXQZURSWY5CB3N3NOQ67E6A5VSV6PON\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2021/CC-MAIN-2021-43/CC-MAIN-2021-43_segments_1634323584567.81_warc_CC-MAIN-20211016105157-20211016135157-00649.warc.gz\"}"}