Skip to content

Grids and coordinates

Download notebookView on GitHubRun when the site was built.

Create a structured grid, inspect its node coordinates, and see how periodic axes change spacing.

A Grid takes a lower bound, upper bound, and node count for each axis. Bounded axes include both endpoints, so their spacing is (upper - lower) / (n - 1).

import numpy as np
from simgeometry.grid import Grid
grid = Grid(
ndim=2,
lower_bound=(-1.0, 2.0),
upper_bound=(1.0, 4.0),
num_gridpoints=(11, 21),
)
print("spacing:", grid.grid_spacing)
print("node (5, 10):", grid.node_coordinates((5, 10)))
print("all node positions shape:", grid.node_points().shape)
assert np.allclose(grid.node_coordinates((5, 10)), (0.0, 3.0))
spacing: [0.2 0.1]
node (5, 10): [0. 3.]
all node positions shape: (2, 231)

node_points() returns a host NumPy array of shape (ndim, N). Each column is one node, ordered like grid.indices. In 1D, node_coordinates() takes a plain integer index.

mask = np.zeros(grid.num_gridpoints, dtype=bool)
mask[5, 10] = True
print("selected indices:", grid.indices_from_mask(mask))
print("axis lengths:", [len(axis) for axis in grid.get_grid_points()])
selected indices: [(5, 10)]
axis lengths: [11, 21]

A periodic axis has n cells across its length and omits the duplicate upper endpoint. Other axes still include both endpoints.

periodic_grid = Grid(
ndim=2,
lower_bound=(0.0, 0.0),
upper_bound=(1.0, 1.0),
num_gridpoints=(4, 3),
periodic=(True, False),
)
for axis, values in enumerate(periodic_grid.get_grid_points()):
print(f"axis {axis}:", values)
assert np.allclose(periodic_grid.grid_spacing, (0.25, 0.5))
axis 0: [0. 0.25 0.5 0.75]
axis 1: [0. 0.5 1. ]

BoundingBox.contains() uses half-open bounds (lower <= x < upper). A nonperiodic upper endpoint is therefore a grid node even though grid.contains() reports that point as outside the box.

print("upper node:", grid.node_coordinates((10, 20)))
print("inside bounding box:", grid.contains((1.0, 4.0)))
upper node: [1. 4.]
inside bounding box: False