Skip to content

Commit

Permalink
[doc] Update field.md (Fields advanced) (taichi-dev#6867)
Browse files Browse the repository at this point in the history
Issue: #

### Brief Summary

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Olinaaaloompa <106292061+Olinaaaloompa@users.noreply.github.com>
  • Loading branch information
3 people authored and quadpixels committed May 13, 2023
1 parent 0e8d856 commit 808b1ad
Showing 1 changed file with 18 additions and 24 deletions.
42 changes: 18 additions & 24 deletions docs/lang/articles/basic/field.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@ 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.

:::note
A 0D (zero-dimensional) field contains *only one* element.
:::
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.

## Scalar fields

Expand Down Expand Up @@ -62,21 +58,20 @@ 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 +87,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 similarly defined.

:::caution WARNING

Expand All @@ -101,9 +96,9 @@ Taichi only supports fields of dimensions &le; 8.
:::


### Access elements in a scalar field
### Accessing elements in a scalar field

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 +122,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 `i`-th element of our defined field.

```python
for i in range(9):
Expand All @@ -142,10 +137,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 `i-th, j-th` element of our defined field.

```python
for i, j in f_2d:
Expand Down Expand Up @@ -192,7 +184,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 Down Expand Up @@ -263,11 +255,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

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 +298,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 @@ -320,7 +314,7 @@ To access the `p`-th component of the 0D vector field `x = ti.Vector.field(n=3,

## Matrix fields

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, which is a 3 x 2 matrix. We can use a matrix field to represent this tensor.

### Declaration

Expand All @@ -331,11 +325,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

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 `i-th, j-th` element of the matrix field `tensor_field`:

`mat = tensor_field[i, j]`

Expand Down Expand Up @@ -372,14 +366,14 @@ 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:

- Not recommended:
`ti.Matrix.field(64, 32, dtype=ti.f32, shape=(3, 2))`
Expand Down Expand Up @@ -425,7 +419,7 @@ particle = ti.types.struct(
particle_field = particle.field(shape=(n,))
```

### Access elements in a struct field
### Accessing elements in a struct field

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

0 comments on commit 808b1ad

Please sign in to comment.