Calculations API Reference

Docstrings for computing quantities from loaded data. The narrative guide is Basic Calculations, and How Quantities Are Computed gives the formulas.

getvar is the main entry point: it returns any stored or derived quantity, in code units by default or converted if you name a unit. The reductions below are conveniences built on it.

Quantities

Mera.getvarFunction

Get variables or derived quantities from the dataset:

  • overview the list of predefined quantities with: getinfo()
  • select variable(s) and their unit(s)
  • give the spatial center (with units) of the data within the box (relevant e.g. for radius dependency)
  • relate the coordinates to a direction (x,y,z)
  • pass a modified database
  • pass a mask to exclude elements (cells/particles/...) from the calculation
`center` here is the coordinate origin — and it defaults to the box corner

getvar's center sets the ORIGIN about which frame-relative quantities are measured: :r_sphere, :r_cylinder, , the v*_sphere/v*_cylinder, a*_sphere/a*_cylinder, mach_* and angular-momentum families. It is a different argument from the center that places a region (Sphere(10; center=[:bc])) and it defaults to [0.,0.,0.], the box corner.

For absolute positions (:x, :y, :z) the corner is the right default — those are the simulation's own coordinates. For the frame-relative quantities it is almost never intended, and the wrong origin returns a plausible number rather than an error, so Mera mentions it once per quantity per session. Pass center=[:bc] for the box centre, or center=[x,y,z] with center_unit=:kpc for another point; pass the same origin you gave the region. verbose(false) silences the reminder.

getvar(gas, :r_sphere, :kpc)                  # about the box CORNER (reminder shown)
getvar(gas, :r_sphere, :kpc, center=[:bc])    # about the box centre
getvar(gas, :x, :kpc)                         # absolute coordinates — no reminder
`:mass` and `:volume` are boundary-aware on a split sub-region

A sub-region built from a value-type region (subregion(gas, Sphere(10)), split=true by default) carries a per-cell :fraction ∈ (0,1] — how much of that cell lies inside the region. getvar(:volume) returns fraction * cellsize^3 and getvar(:mass) returns fraction * rho * volume, so totals are the amount inside the boundary rather than the sum over every cell the boundary touches, and adjacent regions add exactly. Interior cells have fraction = 1 and are unaffected.

Cuts made any other way attach no :fraction and so count whole boundary cells — the loaders' xrange/yrange/zrange, the classic symbol subregion/shellregion, covering_grid — and particles/clumps are points, with no fraction by construction. See subregion and msum.

getvar(   dataobject::DataSetType, var::Symbol;
        filtered_db::IndexedTables.AbstractIndexedTable=IndexedTables.table([1]),
        center::Array{<:Any,1}=[0.,0.,0.],
        center_unit::Symbol=:standard,
        direction::Symbol=:z,
        unit::Symbol=:standard,
        mask::MaskType=[false],
        ref_time::Real=dataobject.info.time)

return Array{Float64,1}

Arguments

Required:

  • dataobject: needs to be of type: "DataSetType"
  • var(s): select a variable from the database or a predefined quantity (see field: info, function getvar(), dataobject.data)

Predefined/Optional Keywords:

  • filtered_db: pass a filtered or manipulated database together with the corresponding DataSetType object (required argument)
  • center: in units given by argument center_unit; by default [0., 0., 0.]; the box-center can be selected by e.g. [:bc], [:boxcenter], [value, :bc, :bc], etc..
  • center_unit: :standard (code units), :Mpc, :kpc, :pc, :mpc, :ly, :au , :km, :cm (of typye Symbol) ..etc. ; see for defined length-scales viewfields(info.scale)
  • direction: todo
  • unit(s): return the variable in given units
  • mask: needs to be of type MaskType which is a supertype of Array{Bool,1} or BitArray{1} with the length of the database (rows)
  • ref_time: reference zero-time for particle age calculation

Defined Methods - function defined for different arguments

  • getvar( dataobject::DataSetType, var::Symbol; ...) # one given variable -> returns 1d array
  • getvar( dataobject::DataSetType, var::Symbol, unit::Symbol; ...) # one given variable with its unit -> returns 1d array
  • getvar( dataobject::DataSetType, vars::Array{Symbol,1}; ...) # several given variables -> array needed -> returns dictionary with 1d arrays
  • getvar( dataobject::DataSetType, vars::Array{Symbol,1}, units::Array{Symbol,1}; ...) # several given variables and their corresponding units -> both arrays -> returns dictionary with 1d arrays
  • getvar( dataobject::DataSetType, vars::Array{Symbol,1}, unit::Symbol; ...) # several given variables that have the same unit -> array for the variables and a single Symbol for the unit -> returns dictionary with 1d arrays

Examples

# read simulation information
julia> info = getinfo(420)
julia> gas = gethydro(info)

# Example 1: get the mass for each cell of the hydro data (1dim array)
mass1 = getvar(gas, :mass)  # in [code units]
mass = getvar(gas, :mass) * gas.scale.Msol # scale the result from code units to solar masses
mass = getvar(gas, :mass, unit=:Msol) # unit calculation, provided by a keyword argument
mass = getvar(gas, :mass, :Msol) # unit calculation provided by an argument


# Example 2: get the mass and |v| (several variables) for each cell of the hydro data
quantities = getvar(gas, [:mass, :v]) # in [code units]
returns: Dict{Any,Any} with 2 entries:
  :mass => [8.9407e-7, 8.9407e-7, 8.9407e-7, 8.9407e-7, 8.9407e-7, 8.9407e-7, 8…
  :v => [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  2.28274e-7, 2.…

quantities = getvar(gas, [:mass, :v], units=[:Msol, :km_s]) # unit calculation, provided by a keyword argument
quantities = getvar(gas, [:mass, :v], [:Msol, :km_s]) # unit calculation provided by an argument

# Example 3: get several variables in the same units by providing a single argument
quantities = getvar(gas, [:vx, :vy, :vz], :km_s)
...

Radiative transfer (RT) quantities

For an RT run (rt = getrt(info)) the stored variables are, per photon group g, the photon number density :Np<g> and the flux components :Fx<g>, :Fy<g>, :Fz<g> (code units). Derived RT quantities on the RT object:

  • :Fmag<g> flux magnitude |F_g| = √(Fx²+Fy²+Fz²) [code units]
  • :Np_total photon number density summed over all groups [code units]
  • :reducedflux<g> reduced flux f = |Fg| / (c·Npg), dimensionless in 0,1
  • :Np<g>_cgs physical photon number density = Npg · unitnp [photons cm⁻³]
  • :Fmag<g>_cgs physical flux magnitude = |Fg| · unitpf [photons cm⁻² s⁻¹]
  • :photon_energy_density<g> radiation energy density of group g = Npg · unitnp · egyg [erg cm⁻³] (egyg = mean photon energy from info.descriptor.rt[:group_egy])
  • :rad_energy_density total radiation energy density summed over all groups [erg cm⁻³]

The per-group photon properties parsed from info_rt (mean energy, energy bounds, photoionization cross-sections, species→group map) are available in info.descriptor.rtPhotonGroups ([g][:egy_eV], [:csn_cm2], [:cse_cm2], plus [:L0_eV], [:L1_eV], [:spec2group]).

The ionization fractions are passive hydro scalars (located via the RT descriptor info.descriptor.rt[:iIons]); request them on the hydro object (gas = gethydro(info)):

  • :xHII, :xHeII, :xHeIII ionization fractions (dimensionless)
  • :xHI neutral atomic-hydrogen fraction (a stored scalar with H2 chemistry, else the closure 1 − xHII; dimensionless)
  • :xH2 molecular-hydrogen fraction = (1 − xHI − xHII)/2 (H2-chemistry runs only; ½ ⇒ fully molecular)
  • :n_HII, :n_HI, :n_e, :n_H2 HII / HI / free-electron / H₂ number density cm⁻³
  • :em_recomb recombination-emissivity proxy ∝ nₑ·nHII ≈ nHII² cm⁻⁶
  • :mu RT-aware mean molecular weight from the ionization (and, with H2 chemistry, molecular) state and metallicity: μ = 1/[XH·hₚ + (XHe/4)(1+xHeII+2xHeIII) + Z/AZ], where hₚ = 1+xHII (no H2) or xHI+2·xHII+xH2 (H2); XH/XHe scaled by the local metal mass fraction Z (the :metallicity scalar, 0 if absent) and AZ≈16. Metal free electrons are neglected (RT does not track metal ionization).
H₂-enabled RAMSES-RT runs

With molecular-hydrogen chemistry (Nickerson et al. 2018) RAMSES stores an extra xHI scalar before xHII, so the species order becomes [xHI, xHII, xHeII, xHeIII] and nIons is even. Mera detects this from nIons (isH2 = iseven(nIons), isHe = nIons≥3) and remaps :xHII/:xHeII/:xHeIII/:n_*/:mu/:T_rt accordingly, and exposes :xHI, :xH2, :n_H2. (Standard non-H₂ runs are unchanged.)

  • :T_rt gas temperature [K] using the local μ (= (P/ρ)·scale.Tmu·μ). Plain :T (unit=:K) bakes in a constant μ (= scale.K/scale.Tmu ≈ 1/0.76 ≈ 1.32, the fixed primordial default — independent of the run's X), so it over-estimates the ionized-gas temperature by μconst/μlocal (e.g. ≈1.32/0.5 ≈ 2.6× for fully-ionized pure hydrogen). Prefer :T_rt for RT runs.
rt   = getrt(info)
gas  = gethydro(info)
f    = getvar(rt, :reducedflux1)                 # reduced flux of group 1
nphot = getvar(rt, :Np1_cgs)                     # physical photon density [cm^-3]
xHII = getvar(gas, :xHII)                        # ionization fraction (hydro scalar)
ne   = getvar(gas, :n_e)                         # free-electron density [cm^-3]
T    = getvar(gas, :T_rt)                        # RT-aware temperature [K] (local μ)

:mu and :T_rt also work on non-RT hydro runs: without tracked ionization fractions they fall back to the constant μ Mera's temperature scaling assumes (μ = scale.K/scale.Tmu), so there `:Trtequalsgetvar(:T, :K). The other RT quantities (:xHII,:xHI,:n*,:emrecomb`) require an RT run and error otherwise.

RAMSES-RT field reference (physical quantity → Mera accessor):

quantity (per photon group i / ion)Mera
photon number densitygetvar(rt, :Npi)unit_np:Npi_cgs)
photon flux componentsgetvar(rt, :Fxi/:Fyi/:Fzi) (magnitude :Fmagi``)
reduced flux (M1 closure):reducedfluxi``
HII ionization fractiongetvar(gas, :xHII)
HeII / HeIII fractions:xHeII / :xHeIII
HII / HI / electron density:n_HII / :n_HI / :n_e

Radiation–matter rates (RT object; use the reduced light speed rt_c_frac·c):

  • :Gamma_HI<g>, :Gamma_HI HI photoionization rate per group / total [s⁻¹]
  • :photoheating_HI<g>, :photoheating_HI HI photoheating rate per HI atom [erg s⁻¹]

Recombination (hydro object): :recomb_rate = αB(T)·nₑ·nHII cm⁻³ s⁻¹.

Combined radiation+gas — request on the RT object with the matching hydro_data (both loaded over the same cells); Mera asserts the cell sets align:

  • :photoionizations = ΓHI·nHI [cm⁻³ s⁻¹]
  • :ionization_balance = photoionizations − recombinations (≈0 in local equilibrium)
rt  = getrt(info);  gas = gethydro(info)            # same lmax/ranges → aligned cells
Γ   = getvar(rt, :Gamma_HI)                          # photoionization rate [1/s]
bal = getvar(rt, :ionization_balance, hydro_data=gas)  # Γ·n_HI − α_B·nₑ·n_HII  [cm^-3 s^-1]

Most RT quantities are single-object (photon fields on rt, ionization state on gas); only the coupling terms above need both. For other hydro variables you may also pass hydro_data=gas to getvar(rt, …) to fetch them aligned to the RT cells.

Get gravity data with optional hydro data for advanced energy analysis

Arguments:

  • dataobject: needs to be of type: "GravDataType"
  • var: select a variable from the database or a predefined quantity

Keyword Arguments:

  • hydro_data: optional hydro data object for energy calculations that require density/mass
  • center: center position (default: [0.,0.,0.])
  • direction: direction for cylindrical coordinates (default: :z)
  • ...

Examples:

# Basic gravity analysis
grav_data = getvar(grav, :epot)

# Advanced energy analysis with hydro data (keyword syntax)
energy_density = getvar(grav, :gravitational_energy_density, hydro_data=hydro)
binding_energy = getvar(grav, :gravitational_binding_energy, hydro_data=hydro)

# NEW: Simplified positional syntax
jeans_mass = getvar(grav, hydro, :jeansmass, :Msol)
thermal_energy = getvar(grav, hydro, :etherm, :erg)
mixed_analysis = getvar(grav, hydro, [:epot, :T, :jeanslength], [:erg, :K, :pc])

Get gravity data with hydro data as second positional argument

New simplified syntax:

# Single variable with unit
getvar(grav, hydro, :jeansmass, :Msol)

# Multiple variables with units  
getvar(grav, hydro, [:jeansmass, :epot], [:Msol, :erg])

# Multiple variables with same unit
getvar(grav, hydro, [:T, :cs], :K)
Mera.getmassFunction

Get mass-array from the dataset (cells/particles/clumps/...):

getmass(dataobject::HydroDataType)
getmass(dataobject::PartDataType)
getmass(dataobject::ClumpDataType)

return Array{Float64,1}
Mera.add_fieldFunction
add_field(name::Symbol, compute::Function; depends_on=Symbol[], datatypes=:hydro,
          unit::Symbol=:standard, description::String="")

Register a user-defined derived field that then behaves like any built-in getvar quantity — it works in getvar, and therefore in projection, profile, phase, etc.

  • compute(dataobject, deps) — your kernel. deps is a Dict{Symbol,Vector} holding the arrays of depends_on (already centered / masked consistently). Return the field in code units; the requested unit (or this field's default unit) is applied for you.
  • depends_on — the variables your kernel needs (built-in or other user fields). These are also recorded in the dependency graph so getvar_requirements (and the read-only-what-you-need logic in project/quicklook) cover your field.
  • datatypes — a kind symbol or collection of them: :hydro, :gravity, :rt, :particle, :clump.
  • unit — default unit symbol (must be a field of info.scale, or :standard).
add_field(:vmag2, (o, d) -> d[:vx].^2 .+ d[:vy].^2 .+ d[:vz].^2; depends_on=[:vx,:vy,:vz])
getvar(gas, :vmag2)
projection(gas, :vmag2)

See also delete_field, list_fields.

Reductions

Mera.msumFunction

Calculate the total mass of any ContainMassDataSetType:

msum(dataobject::ContainMassDataSetType; unit::Symbol=:standard, mask::MaskType=[false])

return Float64

Arguments

Required:

  • dataobject: needs to be of type: "ContainMassDataSetType"

Optional Keywords:

  • unit: the unit of the result (can be used w/o keyword): :standard (code units) :Msol, :Mearth, :Mjupiter, :g, :kg (of typye Symbol) ..etc. ; see for defined mass-scales viewfields(info.scale)
  • mask: needs to be of type MaskType which is a supertype of Array{Bool,1} or BitArray{1} with the length of the database (rows)

Sub-regions: the sum is boundary-aware

msum sums getvar(obj, :mass), which honours the per-cell :fraction attached by a value-type sub-region (subregion(gas, Sphere(10)), split=true by default): a boundary cell contributes fraction * rho * volume, i.e. only the part of it inside the region. So the result is the mass inside the boundary, and adjacent regions add up exactly. Interior cells carry fraction = 1 and are unaffected.

Cuts made any other way carry no :fraction and therefore count whole boundary cells: the loaders' xrange/yrange/zrange, the classic symbol subregion/shellregion, covering_grid. Particles and clumps are points and have no fraction at all. See subregion.

Mera.center_of_massFunction

Calculate the center-of-mass of any ContainMassDataSetType:

center_of_mass(dataobject::ContainMassDataSetType; unit::Symbol=:standard, mask::MaskType=[false])

return Tuple{Float64, Float64, Float64,}

Arguments

Required:

  • dataobject: needs to be of type: "ContainMassDataSetType"

Optional Keywords:

  • unit: the unit of the result (can be used w/o keyword): :standard (code units), :Mpc, :kpc, :pc, :mpc, :ly, :au , :km, :cm (of typye Symbol) ..etc. ; see for defined length-scales viewfields(info.scale)
  • mask: needs to be of type MaskType which is a supertype of Array{Bool,1} or BitArray{1} with the length of the database (rows)

Calculate the joint center-of-mass of any HydroPartType:

center_of_mass(dataobject::Array{HydroPartType,1}, unit::Symbol; mask::MaskArrayAbstractType=[[false],[false]])

return Tuple{Float64, Float64, Float64,}

Arguments

Required:

  • dataobject: needs to be of type: "Array{HydroPartType,1}""

Optional Keywords:

  • unit: the unit of the result (can be used w/o keyword): :standard (code units), :Mpc, :kpc, :pc, :mpc, :ly, :au , :km, :cm (of typye Symbol) ..etc. ; see for defined length-scales viewfields(info.scale)
  • mask: needs to be of type MaskArrayAbstractType which contains two entries with supertype of Array{Bool,1} or BitArray{1} and the length of the database (rows)
Mera.comFunction

Calculate the center-of-mass of any ContainMassDataSetType:

com(dataobject::ContainMassDataSetType; unit::Symbol=:standard, mask::MaskType=[false])

return Tuple{Float64, Float64, Float64,}

Arguments

Required:

  • dataobject: needs to be of type: "ContainMassDataSetType"

Optional Keywords:

  • unit: the unit of the result (can be used w/o keyword): :standard (code units), :Mpc, :kpc, :pc, :mpc, :ly, :au , :km, :cm (of typye Symbol) ..etc. ; see for defined length-scales viewfields(info.scale)
  • mask: needs to be of type MaskType which is a supertype of Array{Bool,1} or BitArray{1} with the length of the database (rows)

Calculate the joint center-of-mass of any HydroPartType:

com(dataobject::Array{HydroPartType,1}, unit::Symbol; mask::MaskArrayAbstractType=[[false],[false]])

return Tuple{Float64, Float64, Float64,}

Arguments

Required:

  • dataobject: needs to be of type: "Array{HydroPartType,1}""

Optional Keywords:

  • unit: the unit of the result (can be used w/o keyword): :standard (code units), :Mpc, :kpc, :pc, :mpc, :ly, :au , :km, :cm (of typye Symbol) ..etc. ; see for defined length-scales viewfields(info.scale)
  • mask: needs to be of type MaskArrayAbstractType which contains two entries with supertype of Array{Bool,1} or BitArray{1} and the length of the database (rows)
Mera.bulk_velocityFunction

Calculate the average velocity (w/o mass-weight) of any ContainMassDataSetType:

bulk_velocity(dataobject::ContainMassDataSetType; unit::Symbol=:standard, weighting::Symbol=:mass, mask::MaskType=[false])

return Tuple{Float64, Float64, Float64,}

Arguments

Required:

  • dataobject: needs to be of type: "ContainMassDataSetType"

Optional Keywords:

  • unit: the unit of the result (can be used w/o keyword): :standard (code units) :kms, :ms, :cm_s (of typye Symbol) ..etc. ; see for defined velocity-scales viewfields(info.scale)
  • weighting: use different weightings: :mass (default), :volume (hydro), :no
  • mask: needs to be of type MaskType which is a supertype of Array{Bool,1} or BitArray{1} with the length of the database (rows)
Mera.average_velocityFunction

Calculate the average velocity (w/o mass-weight) of any ContainMassDataSetType:

average_velocity(dataobject::ContainMassDataSetType; unit::Symbol=:standard, weighting::Symbol=:mass, mask::MaskType=[false])

return Tuple{Float64, Float64, Float64,}

Arguments

Required:

  • dataobject: needs to be of type: "ContainMassDataSetType"

Optional Keywords:

  • unit: the unit of the result (can be used w/o keyword): :standard (code units) :kms, :ms, :cm_s (of typye Symbol) ..etc. ; see for defined velocity-scales viewfields(info.scale)
  • weighting: use different weightings: :mass (default), :volume (hydro), :no
  • mask: needs to be of type MaskType which is a supertype of Array{Bool,1} or BitArray{1} with the length of the database (rows)
Mera.average_mweightedFunction
average_mweighted(dataobject, var::Symbol; mask=[false]) -> Float64

Mass-weighted mean of var over the cells or particles in dataobject: $\langle q \rangle_m = \sum m_i q_i / \sum m_i$.

The mass weight is the natural one for intensive quantities — it follows the dense gas, whereas a volume weight follows the diffuse. Use wstat when you also want the median, spread or higher moments, or to weight by something other than mass.

average_mweighted(gas, :T)              # mass-weighted mean temperature, code units
average_mweighted(gas, :T, mask=hot)    # over a subset only

See also wstat, center_of_mass, bulk_velocity.

Statistics

Mera.wstatFunction

Calculate statistical values w/o weighting of any Array:

wstat(array::Array{<:Real,1}; weight::Array{<:Real,1}=[1.], mask::MaskType=[false])

WStatType(mean, median, std, skewness, kurtosis, min, max)

Arguments

Required:

  • array: Array needs to be of type: "<:Real"

Optional Keywords:

  • weight: Array needs to be of type: "<:Real" (can be used w/o keyword)
  • mask: needs to be of type MaskType which is a supertype of Array{Bool,1} or BitArray{1} with the length of the Array

Time & stellar ages

Mera.gettimeFunction
gettime(output::Real; path::String="./", unit::Symbol=:standard)
gettime(dataobject::DataSetType; unit::Symbol=:standard)
gettime(dataobject::InfoType, unit::Symbol=:standard)

Get the physical simulation time in selected units. Returns a Float64.

For a cosmological run (see iscosmological) info.time is conformal time, so gettime instead returns the age of the universe at the snapshot's scale factor (from cosmology), converted to unit. Supported units for cosmological runs: :Gyr, :Myr, :yr, :s (:standard ⇒ seconds). For a non-cosmological run the behaviour is unchanged (info.time scaled to unit).

gettime(1, path="/path/to/sim", unit=:Myr)
gettime(gas, unit=:Gyr)
gettime(info, :Myr)

Arguments Function 1

Required:

  • output: give the output-number of the simulation

Predefined/Optional Keywords:

  • path: the path to the output folder relative to the current folder or absolute path
  • unit: return the variable in given unit

Arguments Function 2

Required:

  • dataobject: needs to be of type: "DataSetType"

Predefined/Optional Keywords:

  • unit: return the variable in given unit

Arguments Function 3

Required:

  • dataobject: needs to be of type: "InfoType"

Predefined/Optional Keywords:

  • unit: return the variable in given unit
Mera.printtimeFunction
printtime(text::String="", verbose::Bool=verbose_mode)

Print a Mera timestamp with optional text message to the screen when verbose mode is enabled.

Arguments

  • text::String="": Optional text message to display before the timestamp
  • verbose::Bool=verbose_mode: Control output display (uses global verbose_mode by default)

Examples

# Print timestamp with default message
printtime()

# Print timestamp with custom message
printtime("Starting calculation")

# Override verbose setting
printtime("Debug info", true)

For star particles, stellar_age converts a RAMSES :birth time and age_from_aform converts a GADGET/AREPO/TNG GFM_StellarFormationTime. The latter preserves the negative aform that marks TNG wind particles as NaN rather than silently turning them into ages.

Mera.stellar_ageFunction
stellar_age(info::InfoType, birth; unit::Symbol=:Gyr)

Physical age of star particle(s) for a cosmological RAMSES run, from their super-conformal :birth time(s) (scalar or array, as returned by getvar(particles, :birth)). The age is t_proper(a_snap) − t_proper(a_birth) obtained from the Friedmann table (see cosmology); info.time provides the snapshot's conformal time.

unit is a time unit symbol like elsewhere in Mera: :Gyr (default), :Myr, :yr, :s (:standard ⇒ seconds). Non-star sentinels (birth = 0) and any birth time ≥ the snapshot return age 0. This is the conversion used internally by getvar(particles, :age) on cosmological runs.

part = getparticles(info)                 # cosmological run
ages = stellar_age(info, getvar(part, :birth))          # [Gyr]
ages = stellar_age(info, getvar(part, :birth), unit=:Myr)
Mera.age_from_aformFunction
age_from_aform(info::InfoType, aform; unit::Symbol=:Gyr)

Stellar age(s) for data whose formation time is stored as the scale factor a_form (AREPO / IllustrisTNG GFM_StellarFormationTime, exposed by Mera as :aform), rather than as the RAMSES super-conformal :birth used by stellar_age.

Wind particles — which TNG marks with a_form < 0 — return NaN, as does any non-finite entry.

`getvar(:age)` shows 0, not NaN, for wind particles

getvar ends with a global NaN→0 sweep (it exists for r = 0 singularities), so getvar(stars, :age) reports 0 for wind particles rather than NaN, which reads as "formed just now". Select real stars on the raw column — getvar(stars, :aform) .> 0 — before building ages or a star-formation history. Calling age_from_aform directly preserves the NaN.

unit accepts :Gyr (default), :Myr, :yr, :s.

stars = getparticles(info; families=[4])
ages  = age_from_aform(info, getvar(stars, :aform))          # [Gyr]

Units are resolved by getunit; createscales builds the conversion factors from a simulation's own unit system.


Every docstring in the package is also on the Complete API Reference.