Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[doc] Update field.md (Fields advanced) #6867

Merged
merged 14 commits into from
Jan 13, 2023
55 changes: 25 additions & 30 deletions docs/lang/articles/basic/field.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,9 @@ sidebar_position: 1

The term _field_ is borrowed from mathematics and physics. If you already know [scalar field](https://en.wikipedia.org/wiki/Scalar_field) (for example heat field), or vector field (for example [gravitational field](https://en.wikipedia.org/wiki/Gravitational_field)), then it is easy for you to understand fields in Taichi.

Fields in Taichi are the _global_ data containers, which can be accessed from both the Python scope and the Taichi scope. Just like an ndarray in NumPy or a tensor in PyTorch, a field in Taichi is defined as a multi-dimensional array of elements, and elements in a field can be a scalar, a vector, a matrix, or a struct.
Fields in Taichi are the _global_ data containers, which can be accessed from both the Python scope and the Taichi scope. Just like an ndarray in NumPy or a tensor in PyTorch, a field in Taichi is defined as a multi-dimensional array of elements, and elements in a field can be a Scalar, a Vector, a Matrix, or a Struct.

:::note
A 0D (zero-dimensional) field contains *only one* element.
:::

## Scalar fields
## Scalar Fields
Olinaaaloompa marked this conversation as resolved.
Show resolved Hide resolved

Scalar fields refer to the fields that store scalars and are the most basic fields.

Expand Down Expand Up @@ -48,7 +44,7 @@ The simplest way to declare a scalar field is to call `ti.field(dtype, shape)`,
```python
f_1d = ti.field(ti.i32, shape=9) # A 1D field of length 9
```

Over here we are defining a
vai9er marked this conversation as resolved.
Show resolved Hide resolved
An illustration of `f_1d`:

```
Expand All @@ -62,21 +58,21 @@ The simplest way to declare a scalar field is to call `ti.field(dtype, shape)`,
There is little difference between a 0D field and a 1D field of length 1 except for their indexing rules. You *must* use `None` as the index to access a 0D field and `0` as the index to access a 1D field of length 1:

```python
# f1 and f2 are basically interchangeable

f1 = ti.field(int, shape=())
f2 = ti.field(int, shape=1)

f1[None] = 1 # Use None to access a 0D field
f2[0] = 1 # Use 0 to access a 1D field of length 1
```

- When declaring a 2D scalar field, you need to set its two dimensions (numbers of rows and columns) respectively. For example, the following code snippet defines a 2D scalar field in the shape (3, 6) (three rows and six columns):
- When declaring a 2D scalar field, you need to set its two dimensions (numbers of rows and columns) respectively. For example, the following code snippet defines a 2D scalar field with the shape (3, 6) (three rows and six columns):

```python
f_2d = ti.field(int, shape=(3, 6)) # A 2D field in the shape (3, 6)
```

An illustration of `f_2d`:
Here is an illustration of `f_2d`:

```
f_2d.shape[1]
Expand All @@ -92,7 +88,7 @@ The simplest way to declare a scalar field is to call `ti.field(dtype, shape)`,
└ └───┴───┴───┴───┴───┴───┘ ┘
```

Scalar fields of higher dimensions can be similarily defined.
Scalar Fields of higher dimensions can be similarily defined.
Olinaaaloompa marked this conversation as resolved.
Show resolved Hide resolved

:::caution WARNING

Expand All @@ -101,9 +97,9 @@ Taichi only supports fields of dimensions ≤ 8.
:::


### Access elements in a scalar field
### Accessing Elements in a Scalar Field
Olinaaaloompa marked this conversation as resolved.
Show resolved Hide resolved

Once a field is declared, Taichi automatically initializes its elements with the value zero.
Once a field is declared, Taichi automatically initializes its elements to zero.

To access an element in a scalar field, you need to explicitly specify the element's index.

Expand All @@ -127,7 +123,7 @@ When accessing a 0D field `x`, use `x[None] = 0`, *not* `x = 0`.
f_0d.shape=()
```

- To access an element in a 1D field, use index `i`, which is an integer in the range `[0, f_1d.shape[0])`:
- To access an element in a 1D field, use index `i` to get the ith element of our defined field.
Olinaaaloompa marked this conversation as resolved.
Show resolved Hide resolved

```python
for i in range(9):
Expand All @@ -142,10 +138,7 @@ When accessing a 0D field `x`, use `x[None] = 0`, *not* `x = 0`.
└───┴───┴───┴───┴───┴───┴───┴───┴───┘
```

- To access an element in a 2D field, use index `(i, j)`, which is an integer pair.

- `i` in the range `[0, f_2d.shape[0])`
- `j` in the range `[0, f_2d.shape[1])`:
- To access an element in a 2D field, use index `(i, j)`, which is an integer pair to get the ith jth element of our defined field.
Olinaaaloompa marked this conversation as resolved.
Show resolved Hide resolved

```python
for i, j in f_2d:
Expand Down Expand Up @@ -192,7 +185,7 @@ while gui.running:

:::caution WARNING

Taichi fields do not support slicing. Neither of the following usage is correct:
Taichi fields do not support slicing. Neither of the following usages are correct:

```python
for x in f_2d[0]: # Error! You tried to access its first row,but it is not supported
Expand All @@ -206,7 +199,7 @@ f_2d[0][3:] = [4, 5, 6] # Error! You tried to access a slice of the first row,
:::


### Fill a scalar field with a given value
### Fill a Scalar Field with a Given Value
Olinaaaloompa marked this conversation as resolved.
Show resolved Hide resolved

To set all elements in a scalar field to a given value, call `field.fill()`:

Expand All @@ -228,7 +221,7 @@ f_1d.shape # (9,)
f_3d.dtype # f32
```

## Vector fields
## Vector Fields
Olinaaaloompa marked this conversation as resolved.
Show resolved Hide resolved

As the name suggests, vector fields are the fields whose elements are vectors. What a vector represents depends on the scenario of your program. For example, a vector may stand for the (R, G, B) triple of a pixel, the position of a particle, or the gravitational field in space.

Expand Down Expand Up @@ -263,11 +256,12 @@ The following code snippet declares a `300x300x300` vector field `volumetric_fie

```python
box_size = (300, 300, 300) # A 300x300x300 grid in a 3D space

# Declares a 300x300x300 vector field, whose vector dimension is n=3
volumetric_field = ti.Vector.field(n=3, dtype=ti.f32, shape=box_size)
```

### Access elements in a vector field
### Accessing Elements in a Vector Field
Olinaaaloompa marked this conversation as resolved.
Show resolved Hide resolved

Accessing a vector field is similar to accessing a multi-dimensional array: You use an index operator `[]` to access an element in the field. The only difference is that, to access a specific component of an element (vector in this case), you need an *extra* index operator `[]`:

Expand Down Expand Up @@ -305,6 +299,7 @@ vec_field = ti.Vector.field(n, dtype=float, shape=(w,h))
def fill_vector():
for i,j in vec_field:
for k in ti.static(range(n)):

#ti.static unrolls the inner loops
vec_field[i,j][k] = ti.random()

Expand All @@ -318,9 +313,9 @@ To access the `p`-th component of the 0D vector field `x = ti.Vector.field(n=3,
`x[None][p]` (0 &le; p < n).
:::

## Matrix fields
## Matrix Fields
Olinaaaloompa marked this conversation as resolved.
Show resolved Hide resolved

As the name suggests, matrix fields are the fields whose elements are matrices. In continuum mechanics, at each infinitesimal point in a 3D material exists a strain and stress tensor. The strain and stress tensor is a 3 x 2 matrix. Then, you can use a matrix field to represent such a tensor field.
As the name suggests, matrix fields are the fields whose elements are matrices. In continuum mechanics, at each infinitesimal point in a 3D material exists a `strain` and `stress` tensor. The strain and stress tensor is a 3 x 2 matrix. We can use a Matrix Field to represent this tensor.
Olinaaaloompa marked this conversation as resolved.
Show resolved Hide resolved

### Declaration

Expand All @@ -331,11 +326,11 @@ The following code snippet declares a tensor field:
tensor_field = ti.Matrix.field(n=3, m=2, dtype=ti.f32, shape=(300, 400, 500))
```

### Access elements in a matrix field
### Accessing Elements in a Matrix Field
Olinaaaloompa marked this conversation as resolved.
Show resolved Hide resolved

Accessing a matrix field is similar to accessing a vector field: You use an index operator `[]` for field indexing and a second index operator `[]` for matrix indexing.

- To access the `i, j` element of the matrix field `tensor_field`:
- To access the `ith, jth` element of the matrix field `tensor_field`:
Olinaaaloompa marked this conversation as resolved.
Show resolved Hide resolved

`mat = tensor_field[i, j]`

Expand Down Expand Up @@ -372,21 +367,21 @@ def test():
# a[i][1, 2] = 1
```

Operating on larger matrices (for example `32x128`) can lead to longer compilation time and poorer performance. For performance reasons, it is recommended that you keep your matrices small:
Operating on larger matrices (for example `32x128`) can lead to longer compilation time and poor performance. For performance reasons, it is recommended that you keep your matrices small:

- `2x1`, `3x3`, and `4x4` matrices work fine.
- `32x6` is a bit too large.

**Workaround:**

When declaring a matrix field, leave large dimensions to the fields, rather than to the matrices. If you have a `3x2` field of `64x32` matrices:
When declaring a matrix field, leave large dimensions to the Fields, rather than to the matrices. If you have a `3x2` field of `64x32` matrices:
Olinaaaloompa marked this conversation as resolved.
Show resolved Hide resolved

- Not recommended:
`ti.Matrix.field(64, 32, dtype=ti.f32, shape=(3, 2))`
- Recommended:
`ti.Matrix.field(3, 2, dtype=ti.f32, shape=(64, 32))`

## Struct fields
## Struct Fields
Olinaaaloompa marked this conversation as resolved.
Show resolved Hide resolved

Struct fields are fields that store user-defined structs. Members of a struct element can be:

Expand Down Expand Up @@ -425,7 +420,7 @@ particle = ti.types.struct(
particle_field = particle.field(shape=(n,))
```

### Access elements in a struct field
### Access Elements in a Struct Field
Olinaaaloompa marked this conversation as resolved.
Show resolved Hide resolved

You can access a member of an element in a struct field in either of the following ways: index-first or name-first.

Expand Down