bloqade-core 0.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ from .dialects.filled import _interface as filled
2
+ from .dialects.grid import _interface as grid
3
+
4
+ __all__ = [
5
+ "grid",
6
+ "filled",
7
+ ]
File without changes
@@ -0,0 +1,9 @@
1
+ from ._dialect import dialect as dialect
2
+ from ._interface import (
3
+ fill as fill,
4
+ get_parent as get_parent,
5
+ vacate as vacate,
6
+ )
7
+ from .concrete import FilledGridMethods as FilledGridMethods
8
+ from .stmts import Fill as Fill, GetParent as GetParent, Vacate as Vacate
9
+ from .types import FilledGrid as FilledGrid, FilledGridType as FilledGridType
@@ -0,0 +1,3 @@
1
+ from kirin import ir
2
+
3
+ dialect = ir.Dialect("geometry.filled")
@@ -0,0 +1,62 @@
1
+ from typing import Any, TypeVar
2
+
3
+ from kirin.dialects import ilist
4
+ from kirin.lowering import wraps as _wraps
5
+
6
+ from bloqade.geometry.dialects import grid
7
+
8
+ from .stmts import Fill, GetParent, Vacate
9
+ from .types import FilledGrid
10
+
11
+ Nx = TypeVar("Nx")
12
+ Ny = TypeVar("Ny")
13
+
14
+
15
+ @_wraps(Vacate)
16
+ def vacate(
17
+ zone: grid.Grid[Nx, Ny],
18
+ vacancies: ilist.IList[tuple[int, int], Any] | list[tuple[int, int]],
19
+ ) -> FilledGrid[Nx, Ny]:
20
+ """Create a FilledGrid by vacating specified positions from a grid.
21
+
22
+ Args:
23
+ zone: The original grid from which positions will be vacated.
24
+ vacancies: An IList or list of (x_index, y_index) tuples indicating positions to vacate
25
+
26
+ Returns:
27
+ A FilledGrid with the specified vacancies.
28
+
29
+ """
30
+ ...
31
+
32
+
33
+ @_wraps(Fill)
34
+ def fill(
35
+ zone: grid.Grid[Nx, Ny],
36
+ filled: ilist.IList[tuple[int, int], Any] | list[tuple[int, int]],
37
+ ) -> FilledGrid[Nx, Ny]:
38
+ """Create a FilledGrid by filling specified positions in a grid.
39
+
40
+ Args:
41
+ zone: The original grid in which positions will be filled.
42
+ filled: An IList or list of (x_index, y_index) tuples indicating positions to fill
43
+
44
+ Returns:
45
+ A FilledGrid with the specified positions filled.
46
+
47
+ """
48
+ ...
49
+
50
+
51
+ @_wraps(GetParent)
52
+ def get_parent(filled_grid: FilledGrid[Nx, Ny]) -> grid.Grid[Nx, Ny]:
53
+ """Retrieve the parent grid of a FilledGrid.
54
+
55
+ Args:
56
+ filled_grid: The FilledGrid whose parent grid is to be retrieved.
57
+
58
+ Returns:
59
+ The parent grid of the provided FilledGrid.
60
+
61
+ """
62
+ ...
@@ -0,0 +1,43 @@
1
+ from kirin.dialects import ilist
2
+ from kirin.interp import (
3
+ Frame,
4
+ Interpreter,
5
+ MethodTable,
6
+ impl,
7
+ )
8
+
9
+ from bloqade.geometry.dialects.grid.types import Grid
10
+
11
+ from . import stmts
12
+ from ._dialect import dialect
13
+ from .types import FilledGrid
14
+
15
+
16
+ @dialect.register
17
+ class FilledGridMethods(MethodTable):
18
+ @impl(stmts.Vacate)
19
+ def vacate(self, interp: Interpreter, frame: Frame, stmt: stmts.Vacate):
20
+ zone = frame.get_casted(stmt.zone, Grid)
21
+ vacancies_val = frame.get(stmt.vacancies)
22
+ vacancies = (
23
+ vacancies_val
24
+ if isinstance(vacancies_val, ilist.IList)
25
+ else ilist.IList(vacancies_val)
26
+ )
27
+ return (FilledGrid.vacate(zone, vacancies),)
28
+
29
+ @impl(stmts.Fill)
30
+ def fill(self, interp: Interpreter, frame: Frame, stmt: stmts.Fill):
31
+ zone = frame.get_casted(stmt.zone, Grid)
32
+ filled_val = frame.get(stmt.filled)
33
+ filled = (
34
+ filled_val
35
+ if isinstance(filled_val, ilist.IList)
36
+ else ilist.IList(filled_val)
37
+ )
38
+ return (FilledGrid.fill(zone, filled),)
39
+
40
+ @impl(stmts.GetParent)
41
+ def get_parent(self, interp: Interpreter, frame: Frame, stmt: stmts.GetParent):
42
+ filled_grid = frame.get_casted(stmt.filled_grid, FilledGrid)
43
+ return (filled_grid.parent,)
@@ -0,0 +1,43 @@
1
+ from kirin import decl, ir, lowering, types
2
+ from kirin.decl import info
3
+ from kirin.dialects import ilist
4
+
5
+ from bloqade.geometry.dialects import grid
6
+
7
+ from ._dialect import dialect
8
+ from .types import FilledGridType
9
+
10
+ NumVacant = types.TypeVar("NumVacant")
11
+ Nx = types.TypeVar("Nx")
12
+ Ny = types.TypeVar("Ny")
13
+
14
+
15
+ @decl.statement(dialect=dialect)
16
+ class Vacate(ir.Statement):
17
+ traits = frozenset({ir.Pure(), lowering.FromPythonCall()})
18
+
19
+ zone: ir.SSAValue = info.argument(grid.GridType[Nx, Ny])
20
+ vacancies: ir.SSAValue = info.argument(
21
+ ilist.IListType[types.Tuple[types.Int, types.Int], NumVacant]
22
+ )
23
+ result: ir.ResultValue = info.result(FilledGridType[Nx, Ny])
24
+
25
+
26
+ @decl.statement(dialect=dialect)
27
+ class Fill(ir.Statement):
28
+ traits = frozenset({ir.Pure(), lowering.FromPythonCall()})
29
+
30
+ zone: ir.SSAValue = info.argument(grid.GridType[Nx, Ny])
31
+ filled: ir.SSAValue = info.argument(
32
+ ilist.IListType[types.Tuple[types.Int, types.Int], NumVacant]
33
+ )
34
+ result: ir.ResultValue = info.result(FilledGridType[Nx, Ny])
35
+
36
+
37
+ @decl.statement(dialect=dialect)
38
+ class GetParent(ir.Statement):
39
+ name = "get_parent"
40
+ traits = frozenset({ir.Pure(), lowering.FromPythonCall()})
41
+
42
+ filled_grid: ir.SSAValue = info.argument(FilledGridType[Nx, Ny])
43
+ result: ir.ResultValue = info.result(grid.GridType[Nx, Ny])
@@ -0,0 +1,170 @@
1
+ from dataclasses import dataclass, field
2
+ from functools import cached_property
3
+ from itertools import product
4
+ from typing import Any, Iterable, Sequence, TypeVar
5
+
6
+ from kirin import types
7
+ from kirin.dialects import ilist
8
+ from kirin.serialization.base.deserializer import Deserializer
9
+ from kirin.serialization.base.serializer import Serializer
10
+ from kirin.serialization.core.serializationunit import SerializationUnit
11
+
12
+ from bloqade.geometry.dialects import grid
13
+
14
+ from ._dialect import dialect
15
+
16
+ NumX = TypeVar("NumX")
17
+ NumY = TypeVar("NumY")
18
+
19
+
20
+ @dataclass(eq=False)
21
+ @dialect.register
22
+ class FilledGrid(grid.Grid[NumX, NumY]):
23
+ name = "filled_grid"
24
+
25
+ x_spacing: tuple[float, ...] = field(init=False)
26
+ y_spacing: tuple[float, ...] = field(init=False)
27
+ x_init: float | None = field(init=False)
28
+ y_init: float | None = field(init=False)
29
+
30
+ parent: grid.Grid[NumX, NumY]
31
+ vacancies: frozenset[tuple[int, int]]
32
+
33
+ def __post_init__(self):
34
+ self.x_spacing = self.parent.x_spacing
35
+ self.y_spacing = self.parent.y_spacing
36
+ self.x_init = self.parent.x_init
37
+ self.y_init = self.parent.y_init
38
+
39
+ self.type = types.Generic(
40
+ FilledGrid,
41
+ types.Literal(len(self.x_spacing) + 1),
42
+ types.Literal(len(self.y_spacing) + 1),
43
+ )
44
+
45
+ def __hash__(self):
46
+ return hash((self.parent, self.vacancies))
47
+
48
+ def __eq__(self, other: Any) -> bool:
49
+ return (
50
+ isinstance(other, FilledGrid)
51
+ and self.parent == other.parent
52
+ and self.vacancies == other.vacancies
53
+ )
54
+
55
+ def is_equal(self, other: Any) -> bool:
56
+ return self == other
57
+
58
+ @cached_property
59
+ def positions(self) -> ilist.IList[tuple[float, float], Any]:
60
+ positions = tuple(
61
+ (x, y)
62
+ for (ix, x), (iy, y) in product(
63
+ enumerate(self.x_positions), enumerate(self.y_positions)
64
+ )
65
+ if (ix, iy) not in self.vacancies
66
+ )
67
+
68
+ return ilist.IList(positions)
69
+
70
+ @classmethod
71
+ def fill(
72
+ cls, grid_obj: grid.Grid[NumX, NumY], filled: Sequence[tuple[int, int]]
73
+ ) -> "FilledGrid[NumX, NumY]":
74
+ num_x, num_y = grid_obj.shape
75
+
76
+ if isinstance(grid_obj, FilledGrid):
77
+ vacancies = grid_obj.vacancies
78
+ parent = grid_obj.parent
79
+ else:
80
+ vacancies = frozenset(product(range(num_x), range(num_y)))
81
+ parent = grid_obj
82
+
83
+ vacancies = vacancies - frozenset(filled)
84
+
85
+ return cls(parent=parent, vacancies=vacancies)
86
+
87
+ @classmethod
88
+ def vacate(
89
+ cls, grid_obj: grid.Grid[NumX, NumY], vacancies: Iterable[tuple[int, int]]
90
+ ) -> "FilledGrid[NumX, NumY]":
91
+
92
+ if isinstance(grid_obj, FilledGrid):
93
+ input_vacancies = grid_obj.vacancies
94
+ parent = grid_obj.parent
95
+ else:
96
+ input_vacancies = frozenset()
97
+ parent = grid_obj
98
+
99
+ input_vacancies = input_vacancies.union(vacancies)
100
+
101
+ return cls(parent=parent, vacancies=input_vacancies)
102
+
103
+ def get_view( # type: ignore
104
+ self, x_indices: ilist.IList[int, Any], y_indices: ilist.IList[int, Any]
105
+ ):
106
+ remapping_x = {ix: i for i, ix in enumerate(x_indices)}
107
+ remapping_y = {iy: i for i, iy in enumerate(y_indices)}
108
+ return FilledGrid(
109
+ parent=self.parent.get_view(x_indices, y_indices),
110
+ vacancies=frozenset(
111
+ (remapping_x[x], remapping_y[y])
112
+ for x, y in self.vacancies
113
+ if x in remapping_x and y in remapping_y
114
+ ),
115
+ )
116
+
117
+ def shift(self, x_shift: float, y_shift: float):
118
+ return FilledGrid(
119
+ parent=self.parent.shift(x_shift, y_shift),
120
+ vacancies=self.vacancies,
121
+ )
122
+
123
+ def scale(self, x_scale: float, y_scale: float):
124
+ return FilledGrid(
125
+ parent=self.parent.scale(x_scale, y_scale),
126
+ vacancies=self.vacancies,
127
+ )
128
+
129
+ def repeat(self, x_times: int, y_times: int, x_gap: float, y_gap: float):
130
+ new_parent = self.parent.repeat(x_times, y_times, x_gap, y_gap)
131
+ x_dim, y_dim = self.shape
132
+ vacancies = frozenset(
133
+ (x + x_dim * i, y + y_dim * j)
134
+ for i, j, (x, y) in product(range(x_times), range(y_times), self.vacancies)
135
+ )
136
+ return FilledGrid.vacate(new_parent, vacancies)
137
+
138
+ def row_x_pos(self, row_index: int):
139
+ x_vacancies = {x for x, y in self.vacancies if y == row_index}
140
+ return ilist.IList(
141
+ [x for i, x in enumerate(self.parent.x_positions) if i not in x_vacancies]
142
+ )
143
+
144
+ def col_y_pos(self, column_index: int):
145
+ y_vacancies = {y for x, y in self.vacancies if x == column_index}
146
+ return ilist.IList(
147
+ [y for i, y in enumerate(self.y_positions) if i not in y_vacancies]
148
+ )
149
+
150
+ def serialize(self, serializer: "Serializer") -> "SerializationUnit":
151
+ return SerializationUnit(
152
+ kind="filled_grid",
153
+ module_name=dialect.name,
154
+ class_name=FilledGrid.__name__,
155
+ data={
156
+ "parent": serializer.serialize_attribute(self.parent),
157
+ "vacancies": serializer.serialize(self.vacancies),
158
+ },
159
+ )
160
+
161
+ @classmethod
162
+ def deserialize(
163
+ cls, serUnit: "SerializationUnit", deserializer: "Deserializer"
164
+ ) -> "FilledGrid":
165
+ parent = deserializer.deserialize(serUnit.data["parent"])
166
+ vacancies = deserializer.deserialize(serUnit.data["vacancies"])
167
+ return FilledGrid(parent=parent, vacancies=vacancies)
168
+
169
+
170
+ FilledGridType = types.Generic(FilledGrid, types.TypeVar("NumX"), types.TypeVar("NumY"))
@@ -0,0 +1,39 @@
1
+ from ._dialect import dialect as dialect
2
+ from ._interface import (
3
+ col_ypos as col_ypos,
4
+ from_positions as from_positions,
5
+ get as get,
6
+ get_xpos as get_xpos,
7
+ get_ypos as get_ypos,
8
+ new as new,
9
+ positions as positions,
10
+ repeat as repeat,
11
+ row_xpos as row_xpos,
12
+ scale as scale,
13
+ shape as shape,
14
+ shift as shift,
15
+ sub_grid as sub_grid,
16
+ x_bounds as x_bounds,
17
+ y_bounds as y_bounds,
18
+ )
19
+ from ._typeinfer import TypeInferMethods as TypeInferMethods
20
+ from .concrete import GridInterpreter as GridInterpreter
21
+ from .stmts import (
22
+ FromPositions as FromPositions,
23
+ FromRanges as FromRanges,
24
+ Get as Get,
25
+ GetSubGrid as GetSubGrid,
26
+ GetXBounds as GetXBounds,
27
+ GetXPos as GetXPos,
28
+ GetYBounds as GetYBounds,
29
+ GetYPos as GetYPos,
30
+ New as New,
31
+ Positions as Positions,
32
+ Repeat as Repeat,
33
+ Scale as Scale,
34
+ Shape as Shape,
35
+ Shift as Shift,
36
+ ShiftSubgridX as ShiftSubgridX,
37
+ ShiftSubgridY as ShiftSubgridY,
38
+ )
39
+ from .types import Grid as Grid, GridType as GridType
@@ -0,0 +1,3 @@
1
+ from kirin.ir import Dialect
2
+
3
+ dialect = Dialect(name="grid")
@@ -0,0 +1,309 @@
1
+ import typing
2
+
3
+ from kirin.dialects import ilist
4
+ from kirin.lowering import wraps as _wraps
5
+
6
+ from .stmts import (
7
+ ColYPos,
8
+ FromPositions,
9
+ Get,
10
+ GetSubGrid,
11
+ GetXBounds,
12
+ GetXPos,
13
+ GetYBounds,
14
+ GetYPos,
15
+ New,
16
+ Positions,
17
+ Repeat,
18
+ RowXPos,
19
+ Scale,
20
+ Shape,
21
+ Shift,
22
+ ShiftSubgridX,
23
+ ShiftSubgridY,
24
+ )
25
+ from .types import Grid
26
+
27
+
28
+ @_wraps(New)
29
+ def new(
30
+ x_spacing: ilist.IList[float, typing.Any] | list[float],
31
+ y_spacing: ilist.IList[float, typing.Any] | list[float],
32
+ x_init: float,
33
+ y_init: float,
34
+ ) -> Grid[typing.Any, typing.Any]:
35
+ """
36
+ Create a new grid with the given spacing and initial position.
37
+
38
+ Args:
39
+ x_spacing (IList[float] | list[float]): The spacing in the x direction.
40
+ y_spacing (IList[float] | list[float]): The spacing in the y direction.
41
+ x_init (float): The initial position in the x direction.
42
+ y_init (float): The initial position in the y direction.
43
+
44
+ Returns:
45
+ Grid: A new grid object.
46
+ """
47
+ ...
48
+
49
+
50
+ Nx = typing.TypeVar("Nx")
51
+ Ny = typing.TypeVar("Ny")
52
+
53
+
54
+ @typing.overload
55
+ def from_positions(
56
+ x_positions: ilist.IList[float, Nx], y_positions: ilist.IList[float, Ny]
57
+ ) -> Grid[Nx, Ny]: ...
58
+ @typing.overload
59
+ def from_positions(
60
+ x_positions: ilist.IList[float, Nx], y_positions: list[float]
61
+ ) -> Grid[Nx, typing.Any]: ...
62
+ @typing.overload
63
+ def from_positions(
64
+ x_positions: list[float], y_positions: ilist.IList[float, Ny]
65
+ ) -> Grid[typing.Any, Ny]: ...
66
+ @typing.overload
67
+ def from_positions(
68
+ x_positions: list[float], y_positions: list[float]
69
+ ) -> Grid[typing.Any, typing.Any]: ...
70
+ @_wraps(FromPositions)
71
+ def from_positions(x_positions, y_positions):
72
+ """Construct a grid from the given x and y positions.
73
+
74
+ Args:
75
+ x_positions (IList[float] | list[float]): A list or ilist of floats representing the x-coordinates of grid points.
76
+ y_positions (IList[float] | list[float]): A list or ilist of floats representing the y-coordinates of grid points.
77
+
78
+ Returns:
79
+ Grid: a grid object
80
+ """
81
+
82
+
83
+ @_wraps(Get)
84
+ def get(grid: Grid, idx: tuple[int, int]) -> tuple[float, float]:
85
+ """Get the coordinate (x, y) of a grid at the given index.
86
+
87
+ Args:
88
+ grid (Grid): a grid object
89
+ idx (tuple[int, int]): a tuple of (x, y) indices
90
+ Returns:
91
+ tuple[float, float]: a tuple of (x, y) positions
92
+ tuple[None, None]: if the grid has no initial x or y position
93
+ """
94
+ ...
95
+
96
+
97
+ @_wraps(GetXPos)
98
+ def get_xpos(grid: Grid[Nx, typing.Any]) -> ilist.IList[float, Nx]:
99
+ """Get the x positions of a grid.
100
+
101
+ Args:
102
+ grid: a grid object
103
+ Returns:
104
+ ilist.IList[float, typing.Any]: a list of x positions
105
+ """
106
+ ...
107
+
108
+
109
+ @_wraps(GetYPos)
110
+ def get_ypos(grid: Grid[typing.Any, Ny]) -> ilist.IList[float, Ny]:
111
+ """Get the y positions of a grid.
112
+
113
+ Args:
114
+ grid: a grid object
115
+ Returns:
116
+ ilist.IList[float, typing.Any]: a list of y positions
117
+ """
118
+ ...
119
+
120
+
121
+ @typing.overload
122
+ def sub_grid(
123
+ grid: Grid, x_indices: ilist.IList[int, Nx], y_indices: ilist.IList[int, Ny]
124
+ ) -> Grid[Nx, Ny]: ...
125
+ @typing.overload
126
+ def sub_grid(
127
+ grid: Grid, x_indices: ilist.IList[int, Nx], y_indices: list[int]
128
+ ) -> Grid[Nx, typing.Any]: ...
129
+ @typing.overload
130
+ def sub_grid(
131
+ grid: Grid, x_indices: list[int], y_indices: ilist.IList[int, Ny]
132
+ ) -> Grid[typing.Any, Ny]: ...
133
+ @typing.overload
134
+ def sub_grid(
135
+ grid: Grid, x_indices: list[int], y_indices: list[int]
136
+ ) -> Grid[typing.Any, typing.Any]: ...
137
+ @_wraps(GetSubGrid)
138
+ def sub_grid(grid, x_indices, y_indices):
139
+ """Get a subgrid from the given grid.
140
+
141
+ Args:
142
+ grid (Grid): a grid object
143
+ x_indices: a list/ilist of x indices
144
+ y_indices: a list/ilist of y indices
145
+ Returns:
146
+ Grid: a subgrid object
147
+ """
148
+ ...
149
+
150
+
151
+ @_wraps(GetXBounds)
152
+ def x_bounds(grid: Grid[typing.Any, typing.Any]) -> tuple[float, float]:
153
+ """Get the x bounds of a grid.
154
+
155
+ Args:
156
+ grid (Grid): a grid object
157
+ Returns:
158
+ tuple[float, float]: a tuple of (min_x, max_x)
159
+ """
160
+ ...
161
+
162
+
163
+ @_wraps(GetYBounds)
164
+ def y_bounds(grid: Grid[typing.Any, typing.Any]) -> tuple[float, float]:
165
+ """Get the y bounds of a grid.
166
+
167
+ Args:
168
+ grid (Grid): a grid object
169
+ Returns:
170
+ tuple[float, float]: a tuple of (min_y, max_y)
171
+ tuple[None, None]: if the grid has no initial y position
172
+ """
173
+ ...
174
+
175
+
176
+ @_wraps(Positions)
177
+ def positions(
178
+ grid: Grid[typing.Any, typing.Any],
179
+ ) -> ilist.IList[tuple[float, float], typing.Any]:
180
+ """Get the positions of a grid as a list of (x, y) tuples.
181
+
182
+ Args:
183
+ grid (Grid): a grid object
184
+
185
+ Returns:
186
+ ilist.IList[tuple[float, float], typing.Any]: a list of (x, y) tuples representing the positions of the grid points
187
+
188
+ """
189
+ ...
190
+
191
+
192
+ @_wraps(Repeat)
193
+ def repeat(
194
+ grid: Grid, x_times: int, y_times: int, x_spacing: float, y_spacing: float
195
+ ) -> Grid:
196
+ """Repeat a grid in the x and y directions.
197
+
198
+ Args:
199
+ grid (Grid): a grid object
200
+ x_times (int): number of times to repeat in the x direction
201
+ y_times (int): number of times to repeat in the y direction
202
+ x_spacing (float): spacing in the x direction
203
+ y_spacing (float): spacing in the y direction
204
+ Returns:
205
+ Grid: a new grid object with the repeated pattern
206
+ """
207
+ ...
208
+
209
+
210
+ @_wraps(Scale)
211
+ def scale(grid: Grid[Nx, Ny], x_scale: float, y_scale: float) -> Grid[Nx, Ny]:
212
+ """Scale a grid in the x and y directions.
213
+
214
+ Args:
215
+ grid (Grid): a grid object
216
+ x_scale (float): scaling factor in the x direction
217
+ y_scale (float): scaling factor in the y direction
218
+ Returns:
219
+ Grid: a new grid object that has been scaled
220
+ """
221
+ ...
222
+
223
+
224
+ @_wraps(Shift)
225
+ def shift(grid: Grid[Nx, Ny], x_shift: float, y_shift: float) -> Grid[Nx, Ny]:
226
+ """Shift a grid in the x and y directions.
227
+
228
+ Args:
229
+ grid (Grid): a grid object
230
+ x_shift (float): shift in the x direction
231
+ y_shift (float): shift in the y direction
232
+ Returns:
233
+ Grid: a new grid object that has been shifted
234
+ """
235
+ ...
236
+
237
+
238
+ @_wraps(ShiftSubgridX)
239
+ def shift_subgrid_x(
240
+ grid: Grid[Nx, Ny], x_indices: ilist.IList[int, typing.Any], x_shift: float
241
+ ) -> Grid[Nx, Ny]:
242
+ """Shift a sub grid of grid in the x directions.
243
+
244
+ Args:
245
+ grid (Grid): a grid object
246
+ x_indices (ilist.IList[int, typing.Any]): a list/ilist of x indices to shift
247
+ x_shift (float): shift in the x direction
248
+ Returns:
249
+ Grid: a new grid object that has been shifted
250
+ """
251
+ ...
252
+
253
+
254
+ @_wraps(ShiftSubgridY)
255
+ def shift_subgrid_y(
256
+ grid: Grid[Nx, Ny], y_indices: ilist.IList[int, typing.Any], y_shift: float
257
+ ) -> Grid[Nx, Ny]:
258
+ """Shift a sub grid of grid in the y directions.
259
+
260
+ Args:
261
+ grid (Grid): a grid object
262
+ y_indices (ilist.IList[int, typing.Any]): a list/ilist of y indices to shift
263
+ y_shift (float): shift in the y direction
264
+ Returns:
265
+ Grid: a new grid object that has been shifted
266
+ """
267
+ ...
268
+
269
+
270
+ @_wraps(Shape)
271
+ def shape(grid: Grid) -> tuple[int, int]:
272
+ """Get the shape of a grid.
273
+
274
+ Args:
275
+ grid (Grid): a grid object
276
+ Returns:
277
+ tuple[int, int]: a tuple of (num_x, num_y)
278
+ """
279
+ ...
280
+
281
+
282
+ @_wraps(RowXPos)
283
+ def row_xpos(
284
+ grid: Grid[typing.Any, typing.Any], row_index: int
285
+ ) -> ilist.IList[float, typing.Any]:
286
+ """Get the x positions of a specific row in the grid.
287
+
288
+ Args:
289
+ grid (Grid): a grid object
290
+ row_index (int): the index of the row to get x positions for
291
+ Returns:
292
+ ilist.IList[float, typing.Any]: a list of x positions for the specified row
293
+ """
294
+ ...
295
+
296
+
297
+ @_wraps(ColYPos)
298
+ def col_ypos(
299
+ grid: Grid[typing.Any, typing.Any], column_index: int
300
+ ) -> ilist.IList[float, typing.Any]:
301
+ """Get the y positions of a specific column in the grid.
302
+
303
+ Args:
304
+ grid (Grid): a grid object
305
+ column_index (int | None): the index of the column to get y positions for, or None for all columns
306
+ Returns:
307
+ ilist.IList[float, typing.Any]: a list of y positions for the specified column
308
+ """
309
+ ...