Skip to content

Commit

Permalink
update exercises
Browse files Browse the repository at this point in the history
  • Loading branch information
havogt committed Nov 22, 2023
1 parent 467ddab commit 32bd37a
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 77 deletions.
1 change: 0 additions & 1 deletion docs/user/next/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
*.py
*.ipynb
43 changes: 22 additions & 21 deletions docs/user/next/exercises/1_simple_addition.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,50 +15,51 @@ kernelspec:
# 1. Simple Addition

```{code-cell} ipython3
from helpers import *
import gt4py.next as gtx
import numpy as np
from helpers import random_field_new
```

Next we implement the stencil and a numpy reference version, in order to verify them against each other.

```{code-cell} ipython3
def addition_numpy(
a: np.array, b: np.array,
) -> np.array:
C = gtx.Dimension("C")
n_cells = 42
```

```{code-cell} ipython3
def addition_numpy(a: np.array, b: np.array) -> np.array:
c = a + b
return c
```

```{code-cell} ipython3
@gtx.field_operator
def addition(
a: gtx.Field[[C], float],
b: gtx.Field[[C], float],
a: gtx.Field[[C], float], b: gtx.Field[[C], float]
) -> gtx.Field[[C], float]:
c = a
return c
return a + b
```

```{code-cell} ipython3
def test_mo_nh_diffusion_stencil_06():
def test_addition():
domain = gtx.domain({C:n_cells})
a = random_field((n_cells), C)
b = random_field((n_cells), C)
c_numpy = addition_numpy(
a.asnumpy(), b.asnumpy()
)
a = random_field_new(domain)
b = random_field_new(domain)
c = zero_field((n_cells), C)
c_numpy = addition_numpy(a.asnumpy(), b.asnumpy())
c = gtx.zeros(domain)
addition(a, b, out=c, offset_provider={})
addition(
a, b, out=c, offset_provider={}
)
assert np.allclose(c.asnumpy(), c_numpy)
print("Test successful!")
```

```{code-cell} ipython3
test_mo_nh_diffusion_stencil_06()
test_addition()
```
29 changes: 24 additions & 5 deletions docs/user/next/exercises/3_divergence_exercise.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,12 @@ def divergence_numpy(
A: np.array,
edge_orientation: np.array,
) -> np.array:
uv_div = np.sum((u[c2e]*nx[c2e] + v[c2e]*ny[c2e]) * L[c2e] * edge_orientation, axis=1) / A
uv_div = (
np.sum(
(u[c2e] * nx[c2e] + v[c2e] * ny[c2e]) * L[c2e] * edge_orientation, axis=1
)
/ A
)
return uv_div
```

Expand All @@ -63,7 +68,13 @@ def divergence(
A: gtx.Field[[C], float],
edge_orientation: gtx.Field[[C, C2EDim], float],
) -> gtx.Field[[C], float]:
uv_div = neighbor_sum((u(C2E)*nx(C2E) + v(C2E)*ny(C2E)) * L(C2E) * edge_orientation, axis=C2EDim) / A
uv_div = (
neighbor_sum(
(u(C2E) * nx(C2E) + v(C2E) * ny(C2E)) * L(C2E) * edge_orientation,
axis=C2EDim,
)
/ A
)
return uv_div
```

Expand All @@ -88,14 +99,22 @@ def test_divergence():
edge_orientation.asnumpy(),
)

c2e_connectivity = gtx.NeighborTableOffsetProvider(c2e_table, C, E, 3)
c2e_connectivity = gtx.NeighborTableOffsetProvider(c2e_table, C, E, 3, has_skip_values=False)

divergence_gt4py = zero_field((n_cells), C)

divergence(
u, v, nx, ny, L, A, edge_orientation, out = divergence_gt4py, offset_provider = {C2E.value: c2e_connectivity}
u,
v,
nx,
ny,
L,
A,
edge_orientation,
out=divergence_gt4py,
offset_provider={C2E.value: c2e_connectivity},
)

assert np.allclose(divergence_gt4py.asnumpy(), divergence_ref)
```

Expand Down
20 changes: 12 additions & 8 deletions docs/user/next/exercises/4_gradient_exercise.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,9 @@ def gradient_numpy(
ny: np.array,
L: np.array,
A: np.array,
edge_orientation: np.array,
edge_orientation: np.array,
) -> gtx.tuple[np.array, np.array]:
# edge_orientation = np.expand_dims(edge_orientation, axis=-1)
# edge_orientation = np.expand_dims(edge_orientation, axis=-1)
f_x = np.sum(f[c2e] * nx[c2e] * L[c2e] * edge_orientation, axis=1) / A
f_y = np.sum(f[c2e] * ny[c2e] * L[c2e] * edge_orientation, axis=1) / A
return f_x, f_y
Expand All @@ -57,9 +56,8 @@ def gradient(
ny: gtx.Field[[E], float],
L: gtx.Field[[E], float],
A: gtx.Field[[C], float],
edge_orientation: gtx.Field[[C, C2EDim], float],
edge_orientation: gtx.Field[[C, C2EDim], float],
) -> gtx.tuple[gtx.Field[[C], float], gtx.Field[[C], float]]:
f_x = A
f_y = A
return f_x, f_y
Expand Down Expand Up @@ -89,11 +87,17 @@ def test_gradient():
gradient_gt4py_x = zero_field((n_cells), C)
gradient_gt4py_y = zero_field((n_cells), C)
gradient(
f, nx, ny, L, A, edge_orientation, out = (gradient_gt4py_x, gradient_gt4py_y), offset_provider = {C2E.value: c2e_connectivity}
f,
nx,
ny,
L,
A,
edge_orientation,
out=(gradient_gt4py_x, gradient_gt4py_y),
offset_provider={C2E.value: c2e_connectivity},
)
assert np.allclose(gradient_gt4py_x.asnumpy(), gradient_numpy_x)
assert np.allclose(gradient_gt4py_y.asnumpy(), gradient_numpy_y)
```
Expand Down
47 changes: 24 additions & 23 deletions docs/user/next/exercises/8_scan_operator.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,17 @@ kernelspec:
import numpy as np
import gt4py.next as gtx
from gt4py.next.iterator.embedded import MutableLocatedField
from gt4py.next import neighbor_sum, where
from gt4py.next import Dimension, DimensionKind, FieldOffset
from gt4py.next import Dimension, DimensionKind, FieldOffset, neighbor_sum, where
from gt4py.next.iterator.embedded import MutableLocatedField
from gt4py.next.program_processors.runners import roundtrip
```

```{code-cell} ipython3
def random_field(
sizes, *dims, low: float = -1.0, high: float = 1.0
) -> MutableLocatedField:
return gtx.as_field([*dims],
np.random.default_rng().uniform(
low=low, high=high, size=sizes
)
return gtx.as_field(
[*dims], np.random.default_rng().uniform(low=low, high=high, size=sizes)
)
```

Expand Down Expand Up @@ -145,13 +142,12 @@ def toy_microphyiscs_numpy(qc, qr, autoconversion_rate=0.1, sedimentaion_constan
sedimentation_flux = 0.0
for cell, k in np.ndindex(qc.shape):
# Autoconversion: Cloud Drops -> Rain Drops
autoconversion_tendency = qc[cell, k] * autoconversion_rate
qc[cell, k] -= autoconversion_tendency
qr[cell, k] += autoconversion_tendency
## Apply sedimentation flux from level above
qr[cell, k] += sedimentation_flux
Expand All @@ -161,8 +157,9 @@ def toy_microphyiscs_numpy(qc, qr, autoconversion_rate=0.1, sedimentaion_constan

```{code-cell} ipython3
@gtx.scan_operator(axis=KDim, forward=True, init=(0.0, 0.0, 0.0))
def _graupel_toy_scan(state: tuple[float, float, float], qc_in: float, qr_in: float) -> tuple[float, float, float]:
def _graupel_toy_scan(
state: tuple[float, float, float], qc_in: float, qr_in: float
) -> tuple[float, float, float]:
autoconversion_rate = 0.1
sedimentaion_constant = 0.05
Expand All @@ -173,7 +170,7 @@ def _graupel_toy_scan(state: tuple[float, float, float], qc_in: float, qr_in: fl
autoconv_t = qc_in * autoconversion_rate
qc = qc_in - autoconv_t
qr = qr_in + autoconv_t
## Add sedimentation flux from level above
qr = qr + sedimentation_flux
Expand All @@ -185,9 +182,13 @@ def _graupel_toy_scan(state: tuple[float, float, float], qc_in: float, qr_in: fl

```{code-cell} ipython3
@gtx.field_operator(backend=roundtrip.executor)
def graupel_toy_scan(qc: gtx.Field[[CellDim, KDim], float], qr: gtx.Field[[CellDim, KDim], float]
) -> tuple[gtx.Field[[CellDim, KDim], float], gtx.Field[[CellDim, KDim], float], gtx.Field[[CellDim, KDim], float]]:
def graupel_toy_scan(
qc: gtx.Field[[CellDim, KDim], float], qr: gtx.Field[[CellDim, KDim], float]
) -> tuple[
gtx.Field[[CellDim, KDim], float],
gtx.Field[[CellDim, KDim], float],
gtx.Field[[CellDim, KDim], float],
]:
qc, qr, _ = _graupel_toy_scan(qc, qr)
return qc, qr, _
Expand All @@ -198,17 +199,17 @@ def test_scan_operator():
qc = random_field((n_cells, n_levels), CellDim, KDim)
qr = random_field((n_cells, n_levels), CellDim, KDim)
qd = random_field((n_cells, n_levels), CellDim, KDim)
#Initialize Numpy fields from GT4Py fields
# Initialize Numpy fields from GT4Py fields
qc_numpy = qc.asnumpy().copy()
qr_numpy = qr.asnumpy().copy()
#Execute the Numpy version of scheme
# Execute the Numpy version of scheme
toy_microphyiscs_numpy(qc_numpy, qr_numpy)
#Execute the GT4Py version of scheme
# Execute the GT4Py version of scheme
graupel_toy_scan(qc, qr, out=(qc, qr, qd), offset_provider={})
# Compare results
assert np.allclose(qc.asnumpy(), qc_numpy)
assert np.allclose(qr.asnumpy(), qr_numpy)
Expand Down
38 changes: 19 additions & 19 deletions docs/user/next/exercises/helpers.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import numpy as np

import gt4py.next as gtx
from gt4py.next.iterator.embedded import MutableLocatedField
from gt4py.next.iterator.embedded import MutableLocatedField
from gt4py.next import neighbor_sum, where
from gt4py.next import Dimension, DimensionKind, FieldOffset
from gt4py.next.program_processors.runners import roundtrip


def random_mask(
sizes,
*dims,
dtype = None,
dtype=None,
) -> MutableLocatedField:
arr = np.full(shape=sizes, fill_value=False).flatten()
arr[: int(arr.size * 0.5)] = True
Expand All @@ -19,27 +20,26 @@ def random_mask(
arr = arr.astype(dtype)
return gtx.as_field([*dims], (arr))

def random_field(
sizes, *dims, low: float = -1.0, high: float = 1.0
) -> MutableLocatedField:
return gtx.as_field([*dims],
np.random.default_rng().uniform(
low=low, high=high, size=sizes
)
)

def zero_field(
sizes, *dims: Dimension, dtype=float
def random_field(sizes, *dims, low: float = -1.0, high: float = 1.0) -> MutableLocatedField:
return gtx.as_field([*dims], np.random.default_rng().uniform(low=low, high=high, size=sizes))


def random_field_new(
domain: gtx.Domain, low: float = -1.0, high: float = 1.0
) -> MutableLocatedField:
return gtx.as_field([*dims],
np.zeros(shape=sizes, dtype=dtype)
return gtx.as_field(
domain, np.random.default_rng().uniform(low=low, high=high, size=domain.shape)
)

def constant_field(
value, sizes, *dims, dtype=float
) -> MutableLocatedField:
return gtx.as_field([*dims],
value * np.ones(shape=sizes), dtype=dtype)

def zero_field(sizes, *dims: Dimension, dtype=float) -> MutableLocatedField:
return gtx.as_field([*dims], np.zeros(shape=sizes, dtype=dtype))


def constant_field(value, sizes, *dims, dtype=float) -> MutableLocatedField:
return gtx.as_field([*dims], value * np.ones(shape=sizes), dtype=dtype)


# For simplicity we use a triangulated donut in the horizontal.

Expand Down

0 comments on commit 32bd37a

Please sign in to comment.