Skip to content

Commit e8c5f26

Browse files
committed
Merge branch 'combine_1_13_further' of https://github.com/C2SM/icon4py into combine_1_13_further
2 parents 7f8a6e0 + 2a7a46e commit e8c5f26

24 files changed

Lines changed: 1430 additions & 364 deletions

File tree

model/common/src/icon4py/model/common/grid/geometry.py

Lines changed: 236 additions & 75 deletions
Large diffs are not rendered by default.

model/common/src/icon4py/model/common/grid/geometry_attributes.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,6 @@
5050
EDGE_LENGTH: Final[str] = "edge_length"
5151
DUAL_EDGE_LENGTH: Final[str] = "length_of_dual_edge"
5252

53-
EDGE_TANGENT_X: Final[str] = "x_component_of_edge_tangential_unit_vector"
54-
EDGE_TANGENT_Y: Final[str] = "y_component_of_edge_tangential_unit_vector"
55-
EDGE_TANGENT_Z: Final[str] = "z_component_of_edge_tangential_unit_vector"
5653
EDGE_TANGENT_VERTEX_U: Final[str] = "eastward_component_of_edge_tangent_on_vertex"
5754
EDGE_TANGENT_VERTEX_V: Final[str] = "northward_component_of_edge_tangent_on_vertex"
5855
EDGE_TANGENT_CELL_U: Final[str] = "eastward_component_of_edge_tangent_on_cell"
@@ -63,6 +60,9 @@
6360
EDGE_NORMAL_Z: Final[str] = "z_component_of_edge_normal_unit_vector"
6461
EDGE_NORMAL_U: Final[str] = "eastward_component_of_edge_normal"
6562
EDGE_NORMAL_V: Final[str] = "northward_component_of_edge_normal"
63+
EDGE_TANGENT_X: Final[str] = "x_component_of_edge_tangential_unit_vector"
64+
EDGE_TANGENT_Y: Final[str] = "y_component_of_edge_tangential_unit_vector"
65+
EDGE_TANGENT_Z: Final[str] = "z_component_of_edge_tangential_unit_vector"
6666
EDGE_DUAL_U: Final[str] = "eastward_component_of_edge_tangent"
6767
EDGE_DUAL_V: Final[str] = "northward_component_of_edge_tangent"
6868
EDGE_NORMAL_VERTEX_U: Final[str] = "eastward_component_of_edge_normal_on_vertex"

model/common/src/icon4py/model/common/grid/geometry_stencils.py

Lines changed: 264 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
from types import ModuleType
1010

11+
import gt4py.next.typing as gtx_typing
1112
import numpy as np
1213
from gt4py import next as gtx
1314
from gt4py.next import sin, where
@@ -17,12 +18,14 @@
1718
from icon4py.model.common.math.helpers import (
1819
arc_length_on_edges,
1920
cross_product_on_edges,
21+
diff_on_edges_torus,
22+
distance_on_edges_torus,
2023
geographical_to_cartesian_on_edges,
2124
geographical_to_cartesian_on_vertices,
2225
normalize_cartesian_vector_on_edges,
2326
zonal_and_meridional_components_on_edges,
2427
)
25-
from icon4py.model.common.utils import data_allocation as alloc
28+
from icon4py.model.common.utils import data_allocation as data_alloc
2629

2730

2831
@gtx.field_operator(grid_type=gtx.GridType.UNSTRUCTURED)
@@ -56,6 +59,51 @@ def cartesian_coordinates_of_edge_tangent(
5659
return normalize_cartesian_vector_on_edges(x, y, z)
5760

5861

62+
@gtx.field_operator(grid_type=gtx.GridType.UNSTRUCTURED)
63+
def cartesian_coordinates_of_edge_tangent_torus(
64+
vertex_x: fa.VertexField[ta.wpfloat],
65+
vertex_y: fa.VertexField[ta.wpfloat],
66+
edge_orientation: fa.EdgeField[ta.wpfloat],
67+
domain_length: ta.wpfloat,
68+
domain_height: ta.wpfloat,
69+
) -> tuple[
70+
fa.EdgeField[ta.wpfloat],
71+
fa.EdgeField[ta.wpfloat],
72+
fa.EdgeField[ta.wpfloat],
73+
]:
74+
"""
75+
Compute normalized cartesian vector tangential to an edge on a torus grid.
76+
77+
This is done by taking the difference between the two vertices adjacent to the edge
78+
t = d(v1, v2)
79+
80+
Args:
81+
vertex_x: x coordinates of vertices
82+
vertex_y: y coordinates of vertices
83+
edge_orientation: encoding of the edge orientation: (-1, +1) depending on whether the
84+
edge is directed from first to second neighbor of vice versa.
85+
Returns:
86+
x: x coordinate of normalized tangent vector
87+
y: y coordinate of normalized tangent vector
88+
z: z coordinate of normalized tangent vector
89+
"""
90+
xdiff, ydiff = diff_on_edges_torus(
91+
vertex_x(E2V[0]),
92+
vertex_x(E2V[1]),
93+
vertex_y(E2V[0]),
94+
vertex_y(E2V[1]),
95+
domain_length,
96+
domain_height,
97+
)
98+
x = edge_orientation * xdiff
99+
y = edge_orientation * ydiff
100+
z = 0.0 * x
101+
# TODO(msimberg): This should use something like numpy.zeros_like if and
102+
# when that becomes available in gt4py.
103+
104+
return normalize_cartesian_vector_on_edges(x, y, z)
105+
106+
59107
@gtx.field_operator
60108
def cartesian_coordinates_of_edge_normal(
61109
edge_lat: fa.EdgeField[ta.wpfloat],
@@ -93,6 +141,32 @@ def cartesian_coordinates_of_edge_normal(
93141
return normalize_cartesian_vector_on_edges(x, y, z)
94142

95143

144+
@gtx.field_operator
145+
def cartesian_coordinates_of_edge_normal_torus(
146+
edge_tangent_x: fa.EdgeField[ta.wpfloat],
147+
edge_tangent_y: fa.EdgeField[ta.wpfloat],
148+
) -> tuple[
149+
fa.EdgeField[ta.wpfloat],
150+
fa.EdgeField[ta.wpfloat],
151+
fa.EdgeField[ta.wpfloat],
152+
]:
153+
"""
154+
Compute the normal to the edge tangent vector on a torus grid.
155+
156+
Args:
157+
edge_tangent_x: x coordinate of the tangent
158+
edge_tangent_y: y coordinate of the tangent
159+
Returns:
160+
edge_normal_x: x coordinate of the normal
161+
edge_normal_y: y coordinate of the normal
162+
edge_normal_z: y coordinate of the normal
163+
"""
164+
z = 0.0 * edge_tangent_x
165+
# TODO(msimberg): This should use something like numpy.zeros_like if and
166+
# when that becomes available in gt4py.
167+
return normalize_cartesian_vector_on_edges(-edge_tangent_y, edge_tangent_x, z)
168+
169+
96170
@gtx.field_operator
97171
def cartesian_coordinates_edge_tangent_and_normal(
98172
vertex_lat: fa.VertexField[ta.wpfloat],
@@ -123,6 +197,59 @@ def cartesian_coordinates_edge_tangent_and_normal(
123197
return tangent_x, tangent_y, tangent_z, normal_x, normal_y, normal_z
124198

125199

200+
@gtx.field_operator
201+
def cartesian_coordinates_edge_tangent_and_normal_torus(
202+
vertex_x: fa.VertexField[ta.wpfloat],
203+
vertex_y: fa.VertexField[ta.wpfloat],
204+
edge_x: fa.EdgeField[ta.wpfloat],
205+
edge_y: fa.EdgeField[ta.wpfloat],
206+
edge_orientation: fa.EdgeField[ta.wpfloat],
207+
domain_length: ta.wpfloat,
208+
domain_height: ta.wpfloat,
209+
) -> tuple[
210+
fa.EdgeField[ta.wpfloat],
211+
fa.EdgeField[ta.wpfloat],
212+
fa.EdgeField[ta.wpfloat],
213+
fa.EdgeField[ta.wpfloat],
214+
fa.EdgeField[ta.wpfloat],
215+
fa.EdgeField[ta.wpfloat],
216+
fa.EdgeField[ta.wpfloat],
217+
fa.EdgeField[ta.wpfloat],
218+
fa.EdgeField[ta.wpfloat],
219+
fa.EdgeField[ta.wpfloat],
220+
]:
221+
"""Compute normalized cartesian vectors of edge tangent and edge normal."""
222+
tangent_x, tangent_y, tangent_z = cartesian_coordinates_of_edge_tangent_torus(
223+
vertex_x,
224+
vertex_y,
225+
edge_orientation,
226+
domain_length,
227+
domain_height,
228+
)
229+
tangent_u = tangent_x
230+
tangent_v = tangent_y
231+
232+
normal_x, normal_y, normal_z = cartesian_coordinates_of_edge_normal_torus(
233+
tangent_x,
234+
tangent_y,
235+
)
236+
normal_u = normal_x
237+
normal_v = normal_y
238+
239+
return (
240+
tangent_x,
241+
tangent_y,
242+
tangent_z,
243+
tangent_u,
244+
tangent_v,
245+
normal_x,
246+
normal_y,
247+
normal_z,
248+
normal_u,
249+
normal_v,
250+
)
251+
252+
126253
@gtx.program(grid_type=gtx.GridType.UNSTRUCTURED)
127254
def compute_cartesian_coordinates_of_edge_tangent_and_normal(
128255
vertex_lat: fa.VertexField[ta.wpfloat],
@@ -150,6 +277,52 @@ def compute_cartesian_coordinates_of_edge_tangent_and_normal(
150277
)
151278

152279

280+
@gtx.program(grid_type=gtx.GridType.UNSTRUCTURED)
281+
def compute_cartesian_coordinates_of_edge_tangent_and_normal_torus(
282+
vertex_x: fa.VertexField[ta.wpfloat],
283+
vertex_y: fa.VertexField[ta.wpfloat],
284+
edge_x: fa.EdgeField[ta.wpfloat],
285+
edge_y: fa.EdgeField[ta.wpfloat],
286+
edge_orientation: fa.EdgeField[ta.wpfloat],
287+
tangent_x: fa.EdgeField[ta.wpfloat],
288+
tangent_y: fa.EdgeField[ta.wpfloat],
289+
tangent_z: fa.EdgeField[ta.wpfloat],
290+
tangent_u: fa.EdgeField[ta.wpfloat],
291+
tangent_v: fa.EdgeField[ta.wpfloat],
292+
normal_x: fa.EdgeField[ta.wpfloat],
293+
normal_y: fa.EdgeField[ta.wpfloat],
294+
normal_z: fa.EdgeField[ta.wpfloat],
295+
normal_u: fa.EdgeField[ta.wpfloat],
296+
normal_v: fa.EdgeField[ta.wpfloat],
297+
domain_length: ta.wpfloat,
298+
domain_height: ta.wpfloat,
299+
horizontal_start: gtx.int32,
300+
horizontal_end: gtx.int32,
301+
):
302+
cartesian_coordinates_edge_tangent_and_normal_torus(
303+
vertex_x,
304+
vertex_y,
305+
edge_x,
306+
edge_y,
307+
edge_orientation,
308+
domain_length,
309+
domain_height,
310+
out=(
311+
tangent_x,
312+
tangent_y,
313+
tangent_z,
314+
tangent_u,
315+
tangent_v,
316+
normal_x,
317+
normal_y,
318+
normal_z,
319+
normal_u,
320+
normal_v,
321+
),
322+
domain={dims.EdgeDim: (horizontal_start, horizontal_end)},
323+
)
324+
325+
153326
@gtx.field_operator(grid_type=gtx.GridType.UNSTRUCTURED)
154327
def zonal_and_meridional_component_of_edge_field_at_vertex(
155328
vertex_lat: fa.VertexField[ta.wpfloat],
@@ -377,14 +550,14 @@ def arc_distance_of_far_edges_in_diamond(
377550
378551
Neighboring edges of an edge span up a diamond with 4 edges (E2C2E) and 4 vertices (E2C2V). Here we compute the
379552
arc length between the two vertices in this diamond that are not directly connected to the edge:
380-
between d(v1, v3)
381-
v1-------v4
553+
between d(v2, v3)
554+
v2-------v1
382555
| /|
383556
| / |
384557
| e |
385558
| / |
386559
|/ |
387-
v2 ------v3
560+
v0 ------v3
388561
389562
390563
@@ -398,16 +571,47 @@ def arc_distance_of_far_edges_in_diamond(
398571
399572
"""
400573
x, y, z = geographical_to_cartesian_on_vertices(vertex_lat, vertex_lon)
401-
x2 = x(E2C2V[2])
402-
x3 = x(E2C2V[3])
403-
y2 = y(E2C2V[2])
404-
y3 = y(E2C2V[3])
405-
z2 = z(E2C2V[2])
406-
z3 = z(E2C2V[3])
407-
# (xi, yi, zi) are normalized by construction
574+
return arc_length_on_edges(
575+
x(E2C2V[2]),
576+
x(E2C2V[3]),
577+
y(E2C2V[2]),
578+
y(E2C2V[3]),
579+
z(E2C2V[2]),
580+
z(E2C2V[3]),
581+
radius,
582+
)
408583

409-
far_vertex_vertex_length = arc_length_on_edges(x2, x3, y2, y3, z2, z3, radius)
410-
return far_vertex_vertex_length
584+
585+
@gtx.field_operator
586+
def distance_of_far_edges_in_diamond_torus(
587+
vertex_x: fa.VertexField[ta.wpfloat],
588+
vertex_y: fa.VertexField[ta.wpfloat],
589+
domain_length: ta.wpfloat,
590+
domain_height: ta.wpfloat,
591+
) -> fa.EdgeField[ta.wpfloat]:
592+
"""
593+
Compute the distance between the "far" vertices of an edge on a torus grid.
594+
595+
See arc_distance_of_far_edges_in_diamond for details.
596+
597+
Args:
598+
vertex_x: x coordinate of vertices
599+
vertex_y: y coordinate of vertices
600+
domain_length: length of the domain
601+
domain_height: height of the domain
602+
603+
Returns:
604+
distance between the "far" vertices in the diamond.
605+
606+
"""
607+
return distance_on_edges_torus(
608+
vertex_x(E2C2V[2]),
609+
vertex_x(E2C2V[3]),
610+
vertex_y(E2C2V[2]),
611+
vertex_y(E2C2V[3]),
612+
domain_length,
613+
domain_height,
614+
)
411615

412616

413617
@gtx.field_operator
@@ -502,6 +706,26 @@ def compute_arc_distance_of_far_edges_in_diamond(
502706
)
503707

504708

709+
@gtx.program(grid_type=gtx.GridType.UNSTRUCTURED)
710+
def compute_distance_of_far_edges_in_diamond_torus(
711+
vertex_x: fa.VertexField[ta.wpfloat],
712+
vertex_y: fa.VertexField[ta.wpfloat],
713+
domain_length: ta.wpfloat,
714+
domain_height: ta.wpfloat,
715+
far_vertex_distance: fa.EdgeField[ta.wpfloat],
716+
horizontal_start: gtx.int32,
717+
horizontal_end: gtx.int32,
718+
):
719+
distance_of_far_edges_in_diamond_torus(
720+
vertex_x,
721+
vertex_y,
722+
domain_length,
723+
domain_height,
724+
out=far_vertex_distance,
725+
domain={dims.EdgeDim: (horizontal_start, horizontal_end)},
726+
)
727+
728+
505729
@gtx.field_operator
506730
def edge_area(
507731
owner_mask: fa.EdgeField[bool],
@@ -557,6 +781,29 @@ def coriolis_parameter_on_edges(
557781
return 2.0 * angular_velocity * sin(edge_center_lat)
558782

559783

784+
def coriolis_parameter_on_edges_torus(
785+
coriolis_coefficient: float,
786+
num_edges: int,
787+
backend: gtx_typing.Backend,
788+
) -> fa.EdgeField[ta.wpfloat]:
789+
"""
790+
Create a coriolis parameter field on edges for a torus grid.
791+
Args:
792+
coriolis_coefficient: coriolis coefficient
793+
794+
Returns:
795+
coriolis parameter
796+
"""
797+
xp = data_alloc.import_array_ns(backend)
798+
coriolis_parameter = gtx.as_field(
799+
(dims.EdgeDim,),
800+
coriolis_coefficient * xp.ones(num_edges),
801+
dtype=ta.wpfloat,
802+
allocator=backend,
803+
)
804+
return coriolis_parameter
805+
806+
560807
@gtx.program(grid_type=gtx.GridType.UNSTRUCTURED)
561808
def compute_coriolis_parameter_on_edges(
562809
edge_center_lat: fa.EdgeField[ta.wpfloat],
@@ -574,11 +821,11 @@ def compute_coriolis_parameter_on_edges(
574821

575822

576823
def compute_primal_cart_normal(
577-
primal_cart_normal_x: alloc.NDArray,
578-
primal_cart_normal_y: alloc.NDArray,
579-
primal_cart_normal_z: alloc.NDArray,
824+
primal_cart_normal_x: data_alloc.NDArray,
825+
primal_cart_normal_y: data_alloc.NDArray,
826+
primal_cart_normal_z: data_alloc.NDArray,
580827
array_ns: ModuleType = np,
581-
) -> alloc.NDArray:
828+
) -> data_alloc.NDArray:
582829
primal_cart_normal = array_ns.transpose(
583830
array_ns.stack(
584831
(

0 commit comments

Comments
 (0)