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

Implementations for as_offset #1143

Merged
merged 37 commits into from
Mar 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
63a3875
Implementations for as_offset
Jan 27, 2023
e3e8497
Some polishing and cleanup
Jan 27, 2023
08dee1c
further refactoring
Jan 27, 2023
2de8042
Edits for pre-commit and test
Jan 27, 2023
6878ea5
Edis for offset¨
Jan 30, 2023
53702e0
Test edit
Jan 30, 2023
f28690e
Remoed error message
Jan 30, 2023
96b2b53
Edits
Jan 31, 2023
1a59a39
Clean-up
Jan 31, 2023
2ca5685
Merge branch 'functional' into as_offset_builtin
nfarabullini Jan 31, 2023
7489156
Preliminary edits
Feb 1, 2023
c5262ca
Merge branch 'functional' of https://github.com/GridTools/gt4py into …
Feb 1, 2023
7940452
Edits following change of syntax
Feb 1, 2023
f0b9470
Edit to embedded
Feb 1, 2023
61c2413
Cleanup
Feb 1, 2023
f66a6c0
Small edit
Feb 1, 2023
6917dc3
Edit to embedded
Feb 1, 2023
6658d4d
Edit to getter
Feb 1, 2023
54c97db
cleanup
Feb 1, 2023
e380f11
Edits for test
Feb 2, 2023
2f7e19d
clean
Feb 2, 2023
0caa514
Edit to test name
Feb 2, 2023
2855632
Edit import
Feb 2, 2023
358cbe6
Edit for test
Feb 2, 2023
cba682e
Small edit to test
Feb 6, 2023
d6c8387
Module for as_offset builtin
Feb 7, 2023
3b689a9
Edits for pre-commit
Feb 7, 2023
886c3f0
reverted some changes after merge
Feb 8, 2023
1c87907
rebase off of origin
Feb 8, 2023
a78922a
Error edits following review
Feb 10, 2023
bfadc35
Merge branch 'main' of https://github.com/GridTools/gt4py into as_off…
Feb 23, 2023
4746aa2
Ran pre-commit
Feb 23, 2023
5f3111d
Merge branch 'main' of https://github.com/GridTools/gt4py into as_off…
Feb 27, 2023
6d2d353
Ran pre-commit
Feb 27, 2023
0adde48
Update tests/next_tests/ffront_tests/test_type_deduction.py
nfarabullini Mar 6, 2023
797c0f1
Merge branch 'main' into as_offset_builtin
nfarabullini Mar 6, 2023
098aeb1
Ran pre-commit
Mar 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions src/gt4py/next/ffront/experimental.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# GT4Py - GridTools Framework
#
# Copyright (c) 2014-2023, ETH Zurich
# All rights reserved.
#
# This file is part of the GT4Py project and the GridTools framework.
# GT4Py is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or any later
# version. See the LICENSE.txt file at the top-level directory of this
# distribution for a copy of the license or check <https://www.gnu.org/licenses/>.
#
# SPDX-License-Identifier: GPL-3.0-or-later

from dataclasses import dataclass

from gt4py.next.type_system import type_specifications as ts


@dataclass
class BuiltInFunction:
__gt_type: ts.FunctionType

def __call__(self, *args, **kwargs):
"""Act as an empty place holder for the built in function."""

def __gt_type__(self):
return self.__gt_type
Comment on lines +20 to +28
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be in a ffront/common.py or something?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if I move it to commonI get this error:

    dim: func_common.Dimension
E   AttributeError: partially initialized module 'gt4py.next.common' has no attribute 'Dimension' (most likely due to a circular import)



as_offset = BuiltInFunction(
ts.FunctionType(
args=[
ts.DeferredType(constraint=ts.OffsetType),
ts.DeferredType(constraint=ts.FieldType),
],
kwargs={},
returns=ts.DeferredType(constraint=ts.OffsetType),
)
)
2 changes: 2 additions & 0 deletions src/gt4py/next/ffront/fbuiltins.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from numpy import float32, float64, int32, int64

from gt4py.next.common import Dimension, DimensionKind, Field
from gt4py.next.ffront.experimental import as_offset # noqa F401
from gt4py.next.iterator import runtime
from gt4py.next.type_system import type_specifications as ts

Expand Down Expand Up @@ -192,6 +193,7 @@ def __gt_type__(self):
"broadcast",
"where",
"astype",
"as_offset",
] + MATH_BUILTIN_NAMES

BUILTIN_NAMES = TYPE_BUILTIN_NAMES + FUN_BUILTIN_NAMES
Expand Down
29 changes: 29 additions & 0 deletions src/gt4py/next/ffront/foast_passes/type_deduction.py
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,35 @@ def _visit_astype(self, node: foast.Call, **kwargs) -> foast.Call:
location=node.location,
)

def _visit_as_offset(self, node: foast.Call, **kwargs) -> foast.Call:
arg_0 = node.args[0].type
arg_1 = node.args[1].type
assert isinstance(arg_0, ts.OffsetType)
assert isinstance(arg_1, ts.FieldType)
if not type_info.is_integral(arg_1):
raise FieldOperatorTypeDeductionError.from_foast_node(
node,
msg=f"Incompatible argument in call to `{node.func.id}`. "
f"Excepted integer for offset field dtype, but got {arg_1.dtype}"
f"{node.location}",
)

if arg_0.source not in arg_1.dims:
raise FieldOperatorTypeDeductionError.from_foast_node(
node,
msg=f"Incompatible argument in call to `{node.func.id}`. "
f"{arg_0.source} not in list of offset field dimensions {arg_1.dims}. "
f"{node.location}",
)

return foast.Call(
func=node.func,
args=node.args,
kwargs=node.kwargs,
type=arg_0,
location=node.location,
)

def _visit_where(self, node: foast.Call, **kwargs) -> foast.Call:
mask_type = cast(ts.FieldType, node.args[0].type)
true_branch_type = node.args[1].type
Expand Down
15 changes: 12 additions & 3 deletions src/gt4py/next/ffront/foast_to_itir.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,10 +357,19 @@ def visit_Compare(self, node: foast.Compare, **kwargs) -> itir.FunCall:
def _visit_shift(self, node: foast.Call, **kwargs) -> itir.FunCall:
match node.args[0]:
case foast.Subscript(value=foast.Name(id=offset_name), index=int(offset_index)):
return im.shift_(offset_name, offset_index)(self.visit(node.func, **kwargs))
shift_offset = im.shift_(offset_name, offset_index)
case foast.Name(id=offset_name):
return im.shift_(offset_name)(self.visit(node.func, **kwargs))
raise FieldOperatorLoweringError("Unexpected shift arguments!")
shift_offset = im.shift_(offset_name)
case foast.Call(func=foast.Name(id="as_offset")):
func_args = node.args[0]
offset_dim = func_args.args[0]
assert isinstance(offset_dim, foast.Name)
shift_offset = im.shift_(
offset_dim.id, im.deref_(self.visit(func_args.args[1], **kwargs))
)
case _:
raise FieldOperatorLoweringError("Unexpected shift arguments!")
return shift_offset(self.visit(node.func, **kwargs))

def _make_reduction_expr(
self,
Expand Down
49 changes: 46 additions & 3 deletions tests/next_tests/ffront_tests/test_execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,21 @@
import pytest as pytest

from gt4py.next.ffront.decorator import field_operator, program, scan_operator
from gt4py.next.ffront.experimental import as_offset
from gt4py.next.ffront.fbuiltins import (
Dimension,
Field,
FieldOffset,
astype,
broadcast,
float32,
float64,
int32,
int64,
max_over,
min_over,
neighbor_sum,
where,
)
from gt4py.next.ffront.foast_passes.type_deduction import FieldOperatorTypeDeductionError
from gt4py.next.iterator.builtins import float32
from gt4py.next.iterator.embedded import (
NeighborTableOffsetProvider,
index_field,
Expand Down Expand Up @@ -336,6 +335,50 @@ def astype_fieldop_float(b: Field[[IDim], int64]) -> Field[[IDim], int32]:
assert np.allclose(c_int32.array(), out_int_32)


def test_offset_field(fieldview_backend):
a_I_arr = np.random.randn(size, size).astype("float64")
a_I_float = np_as_located_field(IDim, KDim)(a_I_arr)
a_I_float_1 = np_as_located_field(IDim, KDim)(
np.append(np.insert(a_I_arr, size, 0, axis=1), [np.array([0] * (size + 1))], axis=0)
)
offset_field_arr = np.asarray(np.ones((size - 1, size - 1)), dtype=int64)
offset_field_comp = np.append(
np.insert(offset_field_arr, size - 1, 0, axis=1), [np.array([0] * size)], axis=0
)
offset_field = np_as_located_field(IDim, KDim)(offset_field_comp)
out_I_float = np_as_located_field(IDim, KDim)(np.zeros((size, size), dtype=float64))
out_I_float_1 = np_as_located_field(IDim, KDim)(np.zeros((size, size), dtype=float64))

@field_operator(backend=fieldview_backend)
def offset_index_field_fo(
a: Field[[IDim, KDim], float64],
offset_field: Field[[IDim, KDim], int64],
) -> Field[[IDim, KDim], float64]:
a_i = a(as_offset(Ioff, offset_field))
a_i_k = a_i(as_offset(Koff, offset_field))
return a_i_k

offset_index_field_fo(
a_I_float,
offset_field,
out=out_I_float,
offset_provider={"Ioff": IDim, "Koff": KDim},
)

@field_operator(backend=fieldview_backend)
def offset_index_int_fo(a: Field[[IDim, KDim], float64]) -> Field[[IDim, KDim], float64]:
a_i = a(Ioff[1])
a_i_k = a_i(Koff[1])
return a_i_k

offset_index_int_fo(
a_I_float_1, out=out_I_float_1, offset_provider={"Ioff": IDim, "Koff": KDim}
)
assert np.allclose(
out_I_float.array()[: size - 1, : size - 1], out_I_float_1.array()[: size - 1, : size - 1]
)


def test_nested_tuple_return(fieldview_backend):
a_I_float = np_as_located_field(IDim)(np.random.randn(size).astype("float64"))
b_I_float = np_as_located_field(IDim)(np.random.randn(size).astype("float64"))
Expand Down
31 changes: 31 additions & 0 deletions tests/next_tests/ffront_tests/test_type_deduction.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import gt4py.next.ffront.type_specifications
from gt4py.next.common import DimensionKind, GTTypeError
from gt4py.next.ffront.experimental import as_offset
from gt4py.next.ffront.fbuiltins import (
Dimension,
Field,
Expand Down Expand Up @@ -684,3 +685,33 @@ def return_undefined():

with pytest.raises(FieldOperatorTypeDeductionError, match="Undeclared symbol"):
_ = FieldOperatorParser.apply_to_function(return_undefined)


def test_as_offset_dim():
ADim = Dimension("ADim")
BDim = Dimension("BDim")
Boff = FieldOffset("Boff", source=BDim, target=(BDim,))

def as_offset_dim(a: Field[[ADim, BDim], float], b: Field[[ADim], int]):
return a(as_offset(Boff, b))

with pytest.raises(
FieldOperatorTypeDeductionError,
match=f"not in list of offset field dimensions",
):
_ = FieldOperatorParser.apply_to_function(as_offset_dim)


def test_as_offset_dtype():
ADim = Dimension("ADim")
BDim = Dimension("BDim")
Boff = FieldOffset("Boff", source=BDim, target=(BDim,))

def as_offset_dtype(a: Field[[ADim, BDim], float], b: Field[[BDim], float]):
return a(as_offset(Boff, b))

with pytest.raises(
FieldOperatorTypeDeductionError,
match=f"Excepted integer for offset field dtype",
):
_ = FieldOperatorParser.apply_to_function(as_offset_dtype)