jaxdem.utils.meshes#
Asperity mesh generators for geometric-asperity (GA) particles.
Each generate_*_mesh function produces (nv, dim) or (N, nv, dim)
unit-scaled vertex positions — the longest axis has extent 1 — suitable for
consumption by create_ga_state().
Available meshes#
generate_thomson_mesh()— generalized Thomson problem on a hyper-ellipsoid; iterative Riesz-energy minimization, works in 2D and 3D.generate_icosphere_mesh()— recursive icosahedron subdivision (3D) or regular polygon (2D); deterministic; discretenvin 3D.generate_fibonacci_sphere_mesh()— golden-angle spiral sphere (3D) or evenly-spaced circle (2D); deterministic; anynv.generate_torus_mesh()— quasi-uniform torus surface points (3D).generate_helix_mesh()— right-handed helix (3D) or Archimedean spiral (2D).generate_arclength_mesh()— 2D only: equal-arc-length spacing along an ellipse / circle perimeter. Closed-form analogue of the converged Thomson ground state in 2D (exact in the α→∞ packing limit).generate_faceted_mesh()— polygonal / icosahedral shell. Vertex asperities at the corners + face-interior fillers to reachnv. Gives genuinely angular, crystalline particles (flat faces, sharp edges) as opposed to the smooth-sphere family.
Functions
|
2D mesh with equal arc-length spacing along the ellipse / circle perimeter. |
|
Regular n-gon (2D) or icosahedron (3D) with vertex + surface-filler asperities. |
|
Generate |
|
Generate |
|
Generate |
|
Generate and minimize charges constrained to a hyper-ellipsoid surface. |
|
Generate |
|
Minimize Riesz energy for points constrained to a hyper-ellipsoid surface. |
|
Remove the normal component of the gradient (project onto tangent plane of surface). |
|
Generate nv uniform random points on a dim-dimensional unit hyper-ellipsoid surface with a set aspect ratio, repeated N times. |
|
Project point back onto the ellipsoid/ellipse surface. |
|
Riesz energy kernel. |
- jaxdem.utils.meshes.random_points_on_hyper_ellipsoid(key: Array, nv: int, N: int, dim: int, aspect_ratio: Any = None, use_uniform_sampling: bool = True) tuple[Array, Array][source]#
Generate nv uniform random points on a dim-dimensional unit hyper-ellipsoid surface with a set aspect ratio, repeated N times. If using uniform sampling, expensive rejection sampling is used to ensure the points are uniform across the surface. This gives the exact result for hyper-ellipsoids, but is not necessary for hyper-spheres. Scaled so that the longest axis is unit-length.
- jaxdem.utils.meshes.riesz_energy(pos: Array, alpha: float) Array[source]#
Riesz energy kernel. alpha=1 reduces to the Thomson problem. alpha=infty reduces to the packing problem
- jaxdem.utils.meshes.project_to_tangent(grad: Array, pos: Array, aspect_ratio: Array) Array[source]#
Remove the normal component of the gradient (project onto tangent plane of surface).
- jaxdem.utils.meshes.retract_to_surface(pos: Array, aspect_ratio: Array) Array[source]#
Project point back onto the ellipsoid/ellipse surface.
- jaxdem.utils.meshes.minimize_on_hyper_ellipsoid(pos: Array, axes: Array, alpha: float, lr: float = 0.01, steps: int = 1000) tuple[Array, Array][source]#
Minimize Riesz energy for points constrained to a hyper-ellipsoid surface.
- jaxdem.utils.meshes.generate_thomson_mesh(nv: int, N: int, dim: int, alpha: float = 1.0, lr: float = 0.01, steps: int = 1000, aspect_ratio: Any = None, use_uniform_sampling: bool = True, batch_size: int | None = None, seed: int | None = None) tuple[Array, Array][source]#
Generate and minimize charges constrained to a hyper-ellipsoid surface.
- jaxdem.utils.meshes.generate_icosphere_mesh(nv: int, N: int, dim: int, aspect_ratio: Any = None) Array[source]#
Generate
Nicosphere meshes (3D) or regular polygons (2D).In 3D,
nvmust be10 * frequency**2 + 2for some integerfrequency >= 1(i.e. one of{12, 42, 92, 162, 252, ...}). Powers of two use recursive midpoint subdivision; other frequencies use direct triangular geodesic subdivision. Usegenerate_fibonacci_sphere_mesh()if you need an arbitrary vertex count on a sphere.In 2D,
nvcan be any integer and the output is a regularnv-gon on the unit circle.The mesh is deterministic, so all
Nbodies are identical copies; per-body random orientation is typically applied downstream bydistribute_bodies().
- jaxdem.utils.meshes.generate_fibonacci_sphere_mesh(nv: int, N: int, dim: int, aspect_ratio: Any = None) Array[source]#
Generate
NFibonacci-sphere meshes (3D) or circles (2D).In 3D the points are laid out by a golden-angle spiral (the sunflower / Fibonacci lattice):
zis stratified in(-1, 1)and the azimuth advances by the golden angle on each step. The result is a near-optimal, deterministic, low-discrepancy covering of the sphere for anynv >= 1. It’s the “I want uniform points fast” default and a drop-in alternative to Thomson that skips the minimization.In 2D the output is
nvevenly-spaced points on the unit circle (there’s no non-trivial 1D analogue of the spiral).The mesh is deterministic, so all
Nbodies are identical copies; per-body random orientation is typically applied downstream bydistribute_bodies().
- jaxdem.utils.meshes.generate_torus_mesh(nv: int, N: int, dim: int = 3, tube_ratio: float = 0.3, aspect_ratio: Any = None) Array[source]#
Generate
Ntorus surface meshes withnvquasi-uniform points each.The torus is parameterized by two radii: the major radius
R(center of the tube → center of the torus) and the minor radiusr(tube half-thickness).tube_ratiosetsrdirectly under the “longest axis has extent 1” convention:r = tube_ratioandR = 1 - tube_ratio, so the torus fits inx, y ∈ [-1, 1]andz ∈ [-r, r].Points are placed by stratified angular sampling around the major axis (
theta, evenly spaced) paired with a golden-ratio quasi-random phase around the tube (phi). This gives good 2D coverage of the torus surface for anynv, with a slight over-representation of the inner rim relative to the outer rim (exact-uniform sampling would require a(R + r cos(phi))area weighting, which we skip for simplicity).Useful for non-convex, genus-1 particles — e.g. studies of interlocking or linking in packings where non-convexity matters.
- jaxdem.utils.meshes.generate_helix_mesh(nv: int, N: int, dim: int, n_turns: float = 3.0, helix_radius: float = 0.3, aspect_ratio: Any = None) Array[source]#
Generate
Nhelical meshes (3D) or Archimedean spirals (2D).In 3D the points trace a right-handed helix along the
zaxis:nvpoints evenly spaced in the arc parameter, makingn_turnsfull turns fromz = -1toz = 1on a circle of radiushelix_radius. This gives chiral, rod-like bodies with a controllable pitch; good for studies of enantiomeric packing or helical-fiber clumps.In 2D the helix degenerates to an Archimedean spiral centered at the origin, with
nvpoints going from near the origin out to the unit circle overn_turnsturns.
- jaxdem.utils.meshes.generate_faceted_mesh(nv: int, N: int, dim: int, n_facets: int = 6, aspect_ratio: Any = None) Array[source]#
Regular n-gon (2D) or icosahedron (3D) with vertex + surface-filler asperities.
Unlike the smooth-sphere family (thomson / icosphere / fibonacci), this mesh keeps the particle genuinely faceted: the shape is a polygon or polyhedron with sharp vertices and flat faces, and the asperities sit on those flat features rather than being projected to a circumscribed sphere.
Asperity layout
Vertex asperities are always placed at the corners of the shape (
n_facetsin 2D, 12 for the icosahedron in 3D).The remaining
nv - n_verticesasperities are distributed uniformly across the surface primitives — edges in 2D, triangular face interiors in 3D — to achieve an (approximately) uniform surface density. Ifnv - n_verticesis not divisible by the number of primitives, the first few get one extra asperity so the total exactly matchesnv.
In 2D, edge-interior asperities are evenly spaced along each edge (excluding the endpoints, which are already vertex asperities).
In 3D, face-interior asperities are quasi-uniformly sampled inside each triangular face via a barycentric-coordinate remap. They stay on the flat face — not projected to the circumscribing sphere — so the particle’s faceted character is preserved (asperities on faces sit closer to the center than vertex asperities).
- Parameters:
nv (int) – Total number of asperities. Must be
>= n_facetsin 2D and>= 12in 3D. Largernv→ higher surface density.N (int) – Number of bodies (all identical copies; per-body orientation is handled downstream).
dim (int) – Spatial dimension (2 or 3).
n_facets (int) – 2D only: number of polygon sides / vertices. Must be
>= 3. Ignored in 3D (the icosahedron has 12 vertices / 20 faces fixed).aspect_ratio (None, scalar, or (dim,) array-like) – Axis stretch in the usual “normalize to max=1” convention.
- Returns:
Shape
(nv, dim)ifN == 1else(N, nv, dim). Vertex asperities appear first in the array, followed by edge/face fillers grouped by primitive.- Return type:
jax.Array
- jaxdem.utils.meshes.generate_arclength_mesh(nv: int, N: int, dim: int = 2, aspect_ratio: Any = None, n_fine: int | None = None) Array[source]#
2D mesh with equal arc-length spacing along the ellipse / circle perimeter.
This is the closed-form analogue of the converged (
n_steps → ∞) Thomson ground state in 2D. On a circle the two coincide exactly — both give the regularnv-gon. On an ellipse, “uniform neighbor distance” (= equal arc-length spacing) is exactly theα → ∞packing-problem limit of Riesz-energy minimization and a very close approximation to theα = 1Thomson ground state. Use this when you’d otherwise run Thomson with a hugen_stepsbudget on a 2D particle — it arrives at essentially the same answer in one numerical integration, deterministically.The algorithm inverts the arc-length parameterization of the ellipse
(a cos t, b sin t)numerically: trapezoidal-rule the arclength integrand on a fine grid, then linearly interpolate the angles corresponding tonvequally spaced target arc lengths. Accuracy is controlled byn_fine(auto-sized tomax(10_000, 200 * nv)by default).- Parameters:
nv (int) – Number of surface vertices. Must be
>= 3.N (int) – Number of bodies (all identical copies; per-body orientation is handled downstream).
dim (int) – Must be 2. In 3D “uniform neighbor distance” is generically the multi-point Thomson problem — use
generate_thomson_mesh().aspect_ratio (None, scalar, or (2,) array-like) – Ellipse semi-axes in the usual “normalize to max=1” convention.
Nonegives a circle.n_fine (int, optional) – Grid resolution for the arc-length integral.
Noneauto-sizes.
- Returns:
Shape
(nv, 2)ifN == 1else(N, nv, 2).- Return type:
jax.Array