Curvilinear Grids¶
Curvilinear grids extend the base grid infrastructure to non-Cartesian coordinate systems. They provide vector calculus operators – gradient, divergence, curl, and Laplacian – that account for the metric factors of the underlying coordinate system. Concrete implementations are supplied for spherical, cylindrical, and polar coordinates.
- class numgrids.CurvilinearGrid(*axes, scale_factors: Sequence[Callable[[tuple[ndarray[tuple[Any, ...], dtype[_ScalarT]], ...]], ndarray[tuple[Any, ...], dtype[_ScalarT]]]])[source]¶
Orthogonal curvilinear grid with auto-generated vector calculus.
The user supplies one scale-factor callable per axis. Each callable has the signature
(coords: tuple[NDArray, ...]) -> NDArray, where coords isself.meshed_coords.From the scale factors \(h_i\) the class derives:
gradient
\[(\nabla f)_i = \frac{1}{h_i}\frac{\partial f}{\partial q_i}\]divergence (where \(J = \prod h_i\))
\[\nabla\!\cdot\!\mathbf{v} = \frac{1}{J}\sum_i \frac{\partial}{\partial q_i} \!\left(\frac{J}{h_i}\,v_i\right)\]Laplacian
\[\nabla^2 f = \frac{1}{J}\sum_i \frac{\partial}{\partial q_i} \!\left(\frac{J}{h_i^2}\,\frac{\partial f}{\partial q_i}\right)\]curl (3D only)
\[(\nabla\!\times\!\mathbf{v})_i = \frac{1}{h_j h_k}\!\left[ \frac{\partial(h_k\,v_k)}{\partial q_j} - \frac{\partial(h_j\,v_j)}{\partial q_k}\right]\]
For 2D grids a scalar curl is provided, equal to the out-of-plane component.
Coordinate singularities (e.g.
r = 0) are handled gracefully: non-finite values are replaced by zero.- Parameters:
*axes (Axis) – One or more
Axisobjects.scale_factors (sequence of callables) – One callable per axis.
scale_factors[i](meshed_coords)must return anndarrayof shapegrid.shape.
- Raises:
ValueError – If the number of scale factors does not match the number of axes.
Examples
>>> from numgrids import CurvilinearGrid, create_axis, AxisType >>> import numpy as np >>> r_ax = create_axis(AxisType.CHEBYSHEV, 25, 0.1, 2) >>> phi_ax = create_axis(AxisType.EQUIDISTANT_PERIODIC, 30, 0, 2 * np.pi) >>> z_ax = create_axis(AxisType.CHEBYSHEV, 25, -1, 1) >>> grid = CurvilinearGrid( ... r_ax, phi_ax, z_ax, ... scale_factors=( ... lambda c: np.ones_like(c[0]), # h_r = 1 ... lambda c: c[0], # h_phi = r ... lambda c: np.ones_like(c[0]), # h_z = 1 ... ), ... ) >>> R, Phi, Z = grid.meshed_coords >>> lap = grid.laplacian(R ** 2 + Z ** 2) # should be ~6
Constructor
- Parameters:
axes (one or more Axis objects) – One or more axes defining the grid. The order of the axes matters! The first axis passed will have index 0.
- gradient(f: ndarray[tuple[Any, ...], dtype[_ScalarT]]) tuple[ndarray[tuple[Any, ...], dtype[_ScalarT]], ...][source]¶
Gradient of a scalar field.
\[(\nabla f)_i = \frac{1}{h_i}\,\frac{\partial f}{\partial q_i}\]- Parameters:
f (NDArray) – Scalar field of shape
grid.shape.- Returns:
Physical gradient components, one per axis.
- Return type:
tuple of NDArray
- divergence(*v: ndarray[tuple[Any, ...], dtype[_ScalarT]]) ndarray[tuple[Any, ...], dtype[_ScalarT]][source]¶
Divergence of a vector field.
\[\nabla\!\cdot\!\mathbf{v} = \frac{1}{J}\sum_i \frac{\partial}{\partial q_i} \!\left(\frac{J}{h_i}\,v_i\right)\]- Parameters:
*v (NDArray) – Physical components of the vector field (one per axis).
- Returns:
The scalar divergence field.
- Return type:
NDArray
- Raises:
ValueError – If the number of components does not match the grid dimension.
- laplacian(f: ndarray[tuple[Any, ...], dtype[_ScalarT]]) ndarray[tuple[Any, ...], dtype[_ScalarT]][source]¶
Laplacian of a scalar field.
\[\nabla^2 f = \frac{1}{J}\sum_i \frac{\partial}{\partial q_i} \!\left(\frac{J}{h_i^2}\,\frac{\partial f}{\partial q_i}\right)\]- Parameters:
f (NDArray) – Scalar field of shape
grid.shape.- Returns:
The Laplacian, same shape as f.
- Return type:
NDArray
- curl(*v: ndarray[tuple[Any, ...], dtype[_ScalarT]]) tuple[ndarray[tuple[Any, ...], dtype[_ScalarT]], ...] | ndarray[tuple[Any, ...], dtype[_ScalarT]][source]¶
Curl of a vector field.
3D grids — returns a tuple of three arrays (one per component):
\[(\nabla\!\times\!\mathbf{v})_i = \frac{1}{h_j h_k}\!\left[ \frac{\partial(h_k\,v_k)}{\partial q_j} - \frac{\partial(h_j\,v_j)}{\partial q_k}\right]\]where \((i, j, k)\) is a cyclic permutation of \((0, 1, 2)\).
2D grids — returns a scalar array (the out-of-plane component):
\[(\nabla\!\times\!\mathbf{v})_z = \frac{1}{h_0 h_1}\!\left[ \frac{\partial(h_1\,v_1)}{\partial q_0} - \frac{\partial(h_0\,v_0)}{\partial q_1}\right]\]- Parameters:
*v (NDArray) – Physical components of the vector field.
- Returns:
The curl components.
- Return type:
tuple of NDArray (3D) or NDArray (2D)
- Raises:
ValueError – If the grid dimension is not 2 or 3, or if the number of components is wrong.
- class numgrids.SphericalGrid(raxis: Axis, theta_axis: Axis, phi_axis: Axis)[source]¶
A spherical grid in spherical coordinates (r, theta, phi).
Provides built-in vector calculus operators:
laplacian()— scalar Laplaciangradient()— gradient of a scalar fielddivergence()— divergence of a vector fieldcurl()— curl of a vector field
Coordinate singularities at r = 0 and theta = 0, pi are handled gracefully: non-finite values are replaced by zero.
Constructor
- Parameters:
raxis (Axis) – The radial axis.
theta_axis (Axis) – The polar axis (theta).
phi_axis (Axis) – The azimuthal axis (phi). Must be periodic.
- class numgrids.CylindricalGrid(raxis: Axis, phi_axis: Axis, zaxis: Axis)[source]¶
A grid in cylindrical coordinates (r, phi, z).
Provides built-in vector calculus operators:
laplacian()— scalar Laplaciangradient()— gradient of a scalar fielddivergence()— divergence of a vector fieldcurl()— curl of a vector field
Coordinate singularities at r = 0 are handled gracefully.
Examples
>>> from numgrids import * >>> import numpy as np >>> grid = CylindricalGrid( ... create_axis(AxisType.CHEBYSHEV, 20, 0.1, 2), ... create_axis(AxisType.EQUIDISTANT_PERIODIC, 30, 0, 2 * np.pi), ... create_axis(AxisType.CHEBYSHEV, 20, -1, 1), ... ) >>> R, Phi, Z = grid.meshed_coords >>> f = R ** 2 + Z ** 2 >>> lap_f = grid.laplacian(f) # should be ~6
Constructor
- Parameters:
raxis (Axis) – The radial axis.
phi_axis (Axis) – The azimuthal axis (phi). Should typically be periodic.
zaxis (Axis) – The axial (z) axis.
- class numgrids.PolarGrid(raxis: Axis, phi_axis: Axis)[source]¶
A 2D grid in polar coordinates (r, phi).
Provides built-in vector calculus operators:
laplacian()— scalar Laplaciangradient()— gradient of a scalar fielddivergence()— divergence of a 2D vector fieldcurl()— curl (returns the scalar z-component)
Coordinate singularities at r = 0 are handled gracefully.
Examples
>>> from numgrids import * >>> import numpy as np >>> grid = PolarGrid( ... create_axis(AxisType.CHEBYSHEV, 30, 0.1, 1), ... create_axis(AxisType.EQUIDISTANT_PERIODIC, 40, 0, 2 * np.pi), ... ) >>> R, Phi = grid.meshed_coords >>> f = R ** 2 * np.cos(Phi) >>> lap_f = grid.laplacian(f)
Constructor
- Parameters:
raxis (Axis) – The radial axis.
phi_axis (Axis) – The azimuthal axis (phi). Should typically be periodic.