Goal. Generate a star-cluster initial condition that sits in virial equilibrium — , the virial-theorem balance — so it neither collapses () nor expands () when handed to an integrator.
Inputs and assumptions¶
Table 1:Recipe inputs
Input | Meaning and role | Fiducial |
|---|---|---|
profile / | Spatial density model (Plummer here) and its half-mass radius. | Plummer, pc |
| Particle count; | 2000 (equal mass) |
| Unit system carrying the gravitational constant. Required (no default |
|
| Target virial ratio . | 0.5 |
Recipe A — convenience builder (shortest path)¶
import jax, jax.numpy as jnp
from jaxstro.units import STELLAR
from progenax import (
build_plummer_cluster,
compute_kinetic_energy, compute_potential_energy,
)
key = jax.random.PRNGKey(0)
ic = build_plummer_cluster(key=key, n=2000, r_h=1.0, units=STELLAR)
T = compute_kinetic_energy(ic.velocities, ic.masses)
V = compute_potential_energy(ic.positions, ic.masses, G=STELLAR.G)
print(f"virial Q = {T / jnp.abs(V):.4f}") # -> virial Q = 0.5000build_plummer_cluster defaults to Q=0.5, so the returned ICResult is
already virialized and centred on the cluster’s centre of mass.
Recipe B — explicit profile via build_cluster¶
When you want to choose the profile object yourself (and let progenax pick
the matched equilibrium velocity DF), use build_cluster:
from progenax import PlummerProfile, build_cluster
ic = build_cluster(PlummerProfile(r_h=1.0), key=key, n=2000,
units=STELLAR, Q=0.5)
# virial Q = 0.5000matched_velocity_df reads the profile’s own scale fields, so the velocity
DF can never desync from the profile’s — the classic footgun is removed.
Recipe C — full control with build_spatial_ic¶
The lowest-level builder takes an explicit profile and velocity DF — use it when you are composing a profile and DF by hand (see Mix Plummer positions with King velocities):
from progenax import PlummerProfile, PlummerVelocityDF, build_spatial_ic
masses = jnp.ones(2000)
ic = build_spatial_ic(
PlummerProfile(r_h=1.0), masses, PlummerVelocityDF(r_h=1.0),
key=key, G=STELLAR.G, Q=0.5,
)
# virial Q = 0.5000Verified output¶
All three recipes produce the same equilibrium (measured, PRNGKey(0),
):
Recipe | Measured |
|---|---|
A | 0.5000 |
B | 0.5000 |
C | 0.5000 |
See also¶
Fit the half-mass radius with jax.grad — differentiate through this builder to fit .
Virial Q convention (Q = T/|V|) — the convention.
Plummer equilibrium — the equilibrium validation suite.