The simplest non-trivial multi-component IC has two populations in
one shared potential. This page builds one through each engine of
MultiComponentCluster: a cold/hot pair where the DFs
define the model (Engine A), and a halo+core pair where prescribed
densities define it (Engine B). Both are true joint equilibria — no
external virial rescale anywhere — and both come with the measured
numbers that prove it.
Engine A: a cold population inside a hot one¶
Engine A components are lowered-isothermal DFs (theory); the one free per-component scale is the velocity-scale ratio . A colder component () sees the shared potential at the deeper rescaled depth and concentrates — concentration here is an equilibrium outcome, not a sampling choice:
import jax
import jax.numpy as jnp
from jaxstro.units import STELLAR
from progenax import MultiComponentCluster
model = MultiComponentCluster.from_components(
alpha_j=jnp.array([0.5, 0.5]), # central density fractions
w_j=jnp.array([0.7, 1.0]), # cold (0.7) + hot (1.0)
m_j=jnp.array([1.0, 1.0]), # equal stellar masses: pure w_j physics
W0=7.0, g=1.0, r_c=1.0, # King-like (g = 1) truncation
)
ic = model.sample_cluster(jax.random.PRNGKey(0), n_stars=20_000, G=STELLAR.G)
# ic.component_id: 0 = cold, 1 = hotMeasured (from scripts/validate_cluster_ic.py, with pc):
the cold () population’s median radius is 1.50 pc, inside
the hot population’s 8.36 pc — spatial segregation from velocity
scale alone, with equal stellar masses. The exact-quadrature
equilibrium oracle reads for both components.
For mass-driven versions of the same physics, use
from_mass_segregation () or from_imf; for a
GC 1G/2G setup, give the concentrated 2G the smaller .
Engine B: a Plummer halo plus an EFF core¶
Engine B starts from prescribed densities (theory): the headline decomposition is an extended Plummer halo carrying 60% of the mass plus a compact truncated EFF core (Elson et al. (1987)) carrying 40%:
import jax
import jax.numpy as jnp
from jaxstro.units import STELLAR
from progenax import MultiComponentCluster, PlummerProfile, EFFProfile
model = MultiComponentCluster.from_density_profiles(
profiles=[PlummerProfile(r_h=2.0), # halo
EFFProfile(a=0.8, gamma=5.0, r_t=9.0)], # core
mass_fractions=jnp.array([0.6, 0.4]), # M_j / M_total
m_j=jnp.array([0.5, 1.0]), # stellar-mass labels
)
ic = model.sample_cluster(jax.random.PRNGKey(0), n_stars=30_000, G=STELLAR.G)The shared potential is one direct quadrature pass over the summed prescribed density; each component’s DF is its Eddington inversion in that shared potential. Measured at close-out: theoretical (gate ), sampled global at , unscaled.
Honest physics 1: not every decomposition exists¶
Eddington inversion is a two-way street: a prescribed density in a given potential corresponds to a unique candidate , and if that is negative anywhere, the component cannot exist as an equilibrium in that potential — full stop. The originally drafted version of this very example used a shallower EFF core, , and it is genuinely unrealizable: its Eddington DF has , resolution-independent (verified against the closed-form two-Plummer oracle, since EFF is Plummer). A close-out sweep located the realizability boundary between (refused, ) and (realizable, ); the headline uses ( halo, core).
progenax treats this as physics, not failure: the constructor raises a
ValueError naming the component and the remedy (steepen it,
raise its mass fraction, or raise its ), and always stores
the f_min_j diagnostic. See the
realizability gate for the mechanism.
Honest physics 2: the truncation-edge plateau¶
The hard-truncated halo’s sampled per-component virial ratio plateaus slightly below 0.5 — and this is verified physics, not a bias to be rescaled away. A sharply truncated prescribed density has , a constant edge offset that no ergodic can carry (the Eddington pair represents ). Engine B samples a hybrid — positions from the prescribed , speeds from — so the exact-quadrature hybrid expectation predicts the offset: predicted , sampled (18 seeds × 16k stars, a agreement). The validation gate is against the prediction, never a tuned offset — and emphatically not a rescale to 0.5, which would destroy the core’s equilibrium to cosmetically fix the halo’s edge.
Choosing between the engines for two-component work¶
You have… | Use | Because |
|---|---|---|
A dynamical model in mind (relaxed, tidally truncated populations; mass segregation; fit to data) | Engine A ( | The lowered-isothermal family is the model; equilibrium and equipartition are built in. |
Observed/prescribed density shapes (surface-brightness decomposition, halo+core, literature profiles) | Engine B ( | Densities go in verbatim; Eddington tells you whether the decomposition is dynamically realizable. |
The two engines agree where they overlap: a single King component built both ways matches to a radial KS distance of and (the A-vs-B trust anchor; see The Eddington engine (Engine B)).
Domain of validity¶
True joint equilibrium, by construction. Unlike the retired layered superposition (each component sampled from its own isolated-cluster DF), both engines solve/integrate one shared potential and prove per component with no rescale.
Truncation edges are approximate (Engine B): hard-truncated prescribed profiles are only approximately stationary at the edge; the deviation is predicted and gated, not hidden (see above).
Deliberate non-equilibrium ICs (sub-/super-virial, mismatched DFs) remain a separate, explicit workflow — see Velocity distribution functions and Virial Q convention (Q = T/|V|).
Implementation, validation & references¶
In code: both engines are
MultiComponentClusterinsrc/progenax/cluster/multicomponent.py(from_componentsfor Engine A,from_density_profilesfor Engine B); the worked numbers come fromscripts/validate_cluster_ic.pyandscripts/validate_multicomponent_eddington.py. See the cluster API.Validated in: two-component, with Engine-specific anchors in multimass equilibrium and Engine B (Eddington).
Primary sources: self-consistent multi-mass lowered models Gieles & Zocchi (2015); Eddington inversion with Osipkov–Merritt anisotropy Merritt (1985); EFF profile Elson et al. (1987); layered multi-population ICs in N-body practice Küpper et al., 2011. Full notes in the bibliography.
- Elson, R. A. W., Fall, S. M., & Freeman, K. C. (1987). The structure of young star clusters in the Large Magellanic Cloud. The Astrophysical Journal, 323, 54–78. 10.1086/165807
- Gieles, M., & Zocchi, A. (2015). A family of lowered isothermal models. Monthly Notices of the Royal Astronomical Society, 454, 576–592. 10.1093/mnras/stv1848
- Merritt, D. (1985). Spherical stellar systems with spheroidal velocity distributions. The Astronomical Journal, 90, 1027–1037. 10.1086/113810
- Küpper, A. H. W., Maschberger, T., Kroupa, P., & Baumgardt, H. (2011). Mass segregation and fractal substructure in young massive clusters. Monthly Notices of the Royal Astronomical Society, 417, 2300–2317. 10.1111/j.1365-2966.2011.19412.x