Skip to main content

Spectral, divergence-free helical flow-field generator (numpy port of the JS helix-noise library).

Project description

helix-noise (Python)

Spectral, divergence-free helical flow fields for procedural graphics — smoke, fluids, curl-noise motion, vector-field art. The field is an analytic sum of Beltrami (helical) modes, so you can evaluate it grid-free at any point in space and time, bake it to a texture, constrain it around an obstacle, or emit an equivalent GLSL shader.

This is a Python + numpy port of the JavaScript helix-noise library. It is at numerical parity with the JS reference: the mulberry32 RNG stream is bit-identical across languages, and field values match to ~1e-12 (transcendental ULP differences only). A parity test suite reproduces the reference fixture (mode arrays, samples, relative helicity, bake sums, boundary samples, and the GLSL emitter).

Install

pip install helix-noise

Requires Python >= 3.9 and numpy >= 1.20. From a source checkout:

pip install -e .

Quickstart

import helix_noise as hn

field = hn.create(modes=48, seed=1, helicity=0.6, coherence=0.4)

# Sample velocity at a point (grid-free).
u = field.sample(1.0, 2.0, 0.5)            # (ux, uy, uz)
w = field.vorticity(1.0, 2.0, 0.5)         # (wx, wy, wz)

# Animate over time.
u_t = field.sample(1.0, 2.0, 0.5, t=0.3)

# Vectorized: evaluate many points at once (numpy).
import numpy as np
pts = np.random.rand(10000, 3) * (2 * np.pi)
vel = field.sample_many(pts)               # (10000, 3)

# Bake a tileable 3D velocity texture (n, n, n, 4) float32; rgba = (u, v, w, u·w).
tex = field.bake3d(32)

# Emit an equivalent WebGL2 / GLSL ES 3.00 shader.
print(field.glsl(name="myFlow", curl=True))

Free-slip obstacles

Wrap the field with a signed-distance function to make the flow slide tangentially around an obstacle while staying divergence-free:

import math

def sphere(x, y, z):
    return math.hypot(x - 3, y - 3, z - 3) - 1.2

bounded = field.with_boundary(sphere, thickness=0.9)
u = bounded.sample(3.0, 3.0, 4.5)          # zero inside, slip on the surface

API

create(**opts) -> HelixField

Option Default Meaning
modes 48 Number of helical modes (per-sample cost is O(modes)).
slope 1.6 Spectral slope s: amplitude ~ |k|^-s (steep = big swirls).
helicity 0.0 In [-1, 1]: energy split between +/- helical states.
coherence 0.0 In [0, 1]: random phases -> structured (fixed spectrum).
kmin 1.0 Smallest wavenumber (largest structures).
kmax 6.2 Largest wavenumber (finest detail).
centers 3 Focus points the coherent phases organize toward.
amplitude 1.0 Output scale; field is normalized to unit RMS speed, then scaled.
tileable False Snap wavevectors to the integer lattice => exactly 2π-periodic.
seed 1 RNG seed (uint32).
layout "fibonacci" Mode layout: "fibonacci" (low-discrepancy) or "random" (i.i.d.).
churn 1.0 Time-evolution rate for sample(x, y, z, t).
decay 0.0 Viscosity ν >= 0: amplitudes decay as e^(-ν k² t).
anisotropy 0.0 Direction stretch along axis (< 0 streaks, > 0 layers).
axis [0, 0, 1] Anisotropy axis.
spectrum None Optional callable (k: float) -> float overriding the |k|^-slope law.

HelixField methods

Method Returns Notes
sample(x, y, z, t=0.0) (u, v, w) Velocity at a point.
sample_uw(x, y, z, t=0.0) ((u...), (w...)) Velocity + vorticity.
sample_ua(x, y, z, t=0.0) ((u...), (A...)) Velocity + vector potential.
vorticity(x, y, z, t=0.0) (wx, wy, wz) Curl of velocity.
helicity_density(x, y, z, t=0.0) float u · w.
potential(x, y, z, t=0.0) (Ax, Ay, Az) Analytic vector potential.
sample_many(pos, t=0.0) (n, 3) array Vectorized velocity; pos is (n, 3) or flat.
sample_many_uw(pos, t=0.0) (u, w) arrays Vectorized velocity + vorticity.
bake3d(n, t=0.0) (n, n, n, 4) float32 rgba = (u, v, w, u·w).
bake2d(nx, ny, z=0.0, t=0.0) (ny, nx, 4) float32 Slice at height z.
bake_potential3d(n, t=0.0) (n, n, n, 4) float32 rgb = potential, a = u·w.
relative_helicity(ng=12) float Normalized mean helicity over an ng³ grid.
with_boundary(sdf, thickness=1.0, gradient=None, fd_step=1e-3) BoundedField Free-slip SDF obstacle.
glsl(name="helixNoise", precision=7, curl=True, potential=False) str Self-contained WebGL2 shader.
set(**opts) self Update options and rebuild in place.
params dict The resolved option set.

Mode arrays (kx, ky, kz, km, a, s, ph, om, e1*, e2*, N, nu, _scale) are exposed as numpy float64 arrays for inspection.

BoundedField

Returned by with_boundary. Provides sample, sample_uw, vorticity, helicity_density, potential, bake3d, and bake_potential3d. Velocity is curl(ramp(d/thickness) · A) — divergence-free, tangent to the wall (free-slip), zero inside the obstacle, and identical to the base field beyond the influence band.

Parity / testing

python3 tests/test_parity.py       # stdlib + numpy only
python3 -m pytest -q                # if pytest is installed

The suite rebuilds every fixture config and asserts mode arrays, sample u/w/A, relative helicity, the bake sum, the free-slip boundary samples, and the GLSL emitter all match the JS reference within abs+rel 1e-9 (1e-7 for the float32 bake sum).

Scope / follow-ups

v0.1 ships the spectral engine, the free-slip SDF boundary, and the GLSL emitter. The atom engine from the JS library is out of scope for this release and is a documented follow-up.

Changelog

See CHANGELOG.md.

License

MIT © Rifat Jumagulov

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

helix_noise-0.1.0.tar.gz (17.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

helix_noise-0.1.0-py3-none-any.whl (14.9 kB view details)

Uploaded Python 3

File details

Details for the file helix_noise-0.1.0.tar.gz.

File metadata

  • Download URL: helix_noise-0.1.0.tar.gz
  • Upload date:
  • Size: 17.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.13

File hashes

Hashes for helix_noise-0.1.0.tar.gz
Algorithm Hash digest
SHA256 e6e3846c86323df7d1489f0f4c4f9f6bf085d9a2b85d35eedcc66ae8c513e746
MD5 b96367faa5d7bd71b10a408cd228a73c
BLAKE2b-256 0f9396146ebf91e685c3815ee338ade9302f8b2aea770658338f53e57b2aa0a4

See more details on using hashes here.

File details

Details for the file helix_noise-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: helix_noise-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 14.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.13

File hashes

Hashes for helix_noise-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5ca999c2744e7d113036bb7ab80be8eaad1a0891d822fe0dedb196e8c00db9a7
MD5 e043ba03b589a81cd4d263577a097d28
BLAKE2b-256 8a944200f8138f499dd0fe6320e006a5c0ea6e9bb21dc7c3f58af594e43dc207

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page