# @ferret/physics-nuclear: API

decay, activation, radiation dose and shielding, reactor kinetics, fallout.

46 exports. Generated from the source (`packages/physics-nuclear/src`), so it matches the code.

## Classes

### Assembly

*class* · `packages/physics-nuclear/src/assembly.ts:34`

```ts
class Assembly
```

- `spec: AssemblySpec`
- `F: number` — fission rate now, 1/s
- `fissions: number` — fissions so far
- `time: number`
- `critical: boolean`
- `disassembled: boolean`
- `onEvent: ((e: AssemblyEvent) => void) | null`
- `constructor(spec: AssemblySpec)`
- `get energy()` — J released so far
- `get fissioned()` — kg of nuclei that fissioned
- `get expansion()` — compression that the heating has undone: the assembly expands as the energy per kg approaches its disassembly energy
- `get criticalMassNow()` — the effective critical mass now, kg
- `get k()` — multiplication
- `step(dt: number)`

### Fallout

*class* · `packages/physics-nuclear/src/fallout.ts:9`

```ts
class Fallout
```

What a release leaves on the ground: a grid of cells, each with its own inventory that decays exactly like any other, so a cell that
holds Cs-137 loses its activity by the half-life and one that holds Ba-137m next to it keeps the daughter in step. Washing (rain, a hose)
takes a share of every isotope off a cell, to a sink that is not tracked here.

- `readonly cell: number`
- `readonly library: IsotopeLibrary`
- `constructor(cell = 1, library: IsotopeLibrary = new IsotopeLibrary())`
- `deposit(x: number, z: number, isotope: string, atoms: number)` — Put `atoms` of an isotope on the cell holding (x, z).
- `deposit_disc(x: number, z: number, radius: number, isotope: string, bq: number)` — Spread an activity (Bq) of an isotope evenly over a disc of the given radius.
- `surfaceActivity(x: number, z: number, isotope?: string): number` — Bq per m² on the cell holding (x, z): all isotopes, or one (a daughter grows in beside its parent, so the sum can rise as the parent falls).
- `get total(): number` — Bq on the whole ground.
- `decay(dt: number)` — Let every cell decay.
- `wash(fraction: number, at?: [number, number])` — Take the share `fraction` of every isotope off the cell holding (x, z) or, with no position, off all of them.
- `doseRate(x: number, z: number, height = 1, o: { mu?: number; coefficient?: number; reach?: number } = {}): number` — The gamma dose rate (Sv/s) at (x, z) and `height` m above the ground: every cell is a point source of its gamma photons per second (activity x the gamma yield of each isotope), seen through the air as e^(-mu r) / (4 pi r^2), summed over the cells within `reach` m. mu is the attenuation of air for ~0.7 MeV photons (0.0035 /m); the dose coefficient is the library's fluence-to-dose for gammas.

### Inventory

*class* · `packages/physics-nuclear/src/decay.ts:108`

```ts
class Inventory
```

Atoms of each isotope in a body, a vessel or a patch of soil.

- `readonly library: IsotopeLibrary`
- `readonly atoms: Map<string, number>`
- `stream: (() => number) | null` — when set, the number of decays in a step is drawn from the Poisson law instead of taken at its expectation
- `constructor(library: IsotopeLibrary = new IsotopeLibrary())`
- `add(isotope: string, atoms: number)`
- `addActivity(isotope: string, bq: number)` — Add an amount by its activity in Bq.
- `amount(isotope: string)`
- `activity(isotope?: string): number` — Bq
- `get mass(): number` — kg
- `get power(): number` — Heat power now, W
- `decay(dt: number): DecayResult` — Decay for dt seconds. Exact for the expectation (matrix exponential of the network, with the decays integrated alongside).

### IsotopeLibrary

*class* · `packages/physics-nuclear/src/decay.ts:49`

```ts
class IsotopeLibrary
```

- `constructor(initial: Record<string, IsotopeDef> = EXAMPLE_ISOTOPES)`
- `add(name: string, d: IsotopeDef)`
- `get(name: string): IsotopeDef`
- `has(name: string)`
- `names()`
- `lambda(name: string): number` — 1/s

### Reactor

*class* · `packages/physics-nuclear/src/reactor.ts:84`

```ts
class Reactor
```

- `readonly spec: Required<Pick<ReactorSpec, 'power' | 'generation' | 'rodWorth' | 'rodsCritical' | 'fuelHeat' | 'coolantHeat' | 'exchange' | 'inlet' | 'scramSpeed'>> & ReactorSpec`
- `readonly beta: number[]`
- `readonly lambda: number[]`
- `P: number` — fission power now, W
- `C: number[]` — delayed precursor groups in power units, W
- `Tf: number`
- `Tc: number`
- `sink: number` — heat taken from the fuel by whatever it is linked to (a structure, a pool), W; set by a link
- `readonly Tf0: number`
- `readonly Tc0: number`
- `rods: number`
- `target: number` — a rod position the controller is driving to (the scram sets it to 1)
- `external: number` — extra reactivity from outside (a game's own cause)
- `iodine: number` — iodine-135 and xenon-135 as a share of their equilibrium at nominal power (1 = nominal equilibrium)
- `xe: number`
- `flow: number`
- `scrammed: boolean`
- `melted: boolean`
- `time: number`
- `fissions: number`
- `energy: number` — J of fission energy released
- `maxSubstep: number` — the longest sub-step, s; raise it for a long coast where nothing changes quickly
- `onEvent: ((e: ReactorEvent) => void) | null`
- `constructor(spec: ReactorSpec)`
- `get betaTotal()`
- `get void(): number`
- `get rho(): number` — reactivity (Δk/k)
- `get decayHeat(): number` — decay heat power now, W
- `get thermal(): number` — heat into the fuel, W
- `get fissionRate()` — fissions per second
- `get period(): number` — e-folding time of the power, s (Infinity when steady)
- `scram()`
- `setRods(position: number)`
- `step(dt: number)` — Advance dt seconds. Sub-steps follow the fastest rate of the kinetics.

### ShieldLibrary

*class* · `packages/physics-nuclear/src/radiation.ts:35`

```ts
class ShieldLibrary
```

- `constructor(initial: Record<string, ShieldMaterial> = EXAMPLE_SHIELDS)`
- `add(name: string, s: ShieldMaterial)`
- `get(name: string): ShieldMaterial | undefined`
- `names()`
- `transmission(kind: RadiationKind, layers: Layer[]): number` — The share of a beam of this kind that gets through the layers.

## Functions

### activate

*function* · `packages/physics-nuclear/src/activation.ts:15`

```ts
function activate(inv: Inventory, captures: readonly Capture[], flux: number, dt: number): number
```

Neutron activation. A flux Φ (neutrons per m² and s) turns the nuclei of a target into its radioactive product at the rate σ Φ per nucleus:
N_to gains N_from (1 - e^(-σΦt)) over t and the target loses the same, so what is made is never more than there was. The product then decays
with the rest of the inventory (call `inv.decay(dt)` after this, which makes the activity rise to the saturation value N_from σ Φ and no further).
Returns the atoms made.

### chord

*function* · `packages/physics-nuclear/src/radiation.ts:62`

```ts
function chord(b: Body, origin: Vec3, dir: Vec3, maxDistance: number): { enter: number; length: number } | null
```

Length of the chord a ray cuts through a body, from the point it enters, m (planes have no thickness here).

### doseRate

*function* · `packages/physics-nuclear/src/radiation.ts:121`

```ts
function doseRate( inventory: Inventory, r: number, layers: Layer[], shields: ShieldLibrary, coefficients: Record<RadiationKind, number> = EXAMPLE_DOSE_COEFFICIENTS, ): Record<RadiationKind, number>
```

Dose rate (Sv/s) of a source at a point through the given layers, by kind.

### expm

*function* · `packages/physics-nuclear/src/decay.ts:84`

```ts
function expm(A: number[][]): number[][]
```

exp of a small dense matrix by scaling and squaring

### inhourRoot

*function* · `packages/physics-nuclear/src/reactor.ts:236`

```ts
function inhourRoot(rho: number, generation: number, groups = DELAYED_GROUPS): number
```

The stable period of the point-kinetics model for a reactivity step: the largest root ω of the inhour equation ρ = Λω + Σ βᵢω/(ω+λᵢ).

### layersBetween

*function* · `packages/physics-nuclear/src/radiation.ts:91`

```ts
function layersBetween(host: PhysicsHost, from: Vec3, to: Vec3, shieldOf: (b: Body) => string | undefined, except: Body[] = []): Layer[]
```

The layers a ray crosses between two points: every body in the way, by the shield material its physics material names, plus the air between.
`except` bodies (the source and the receiver themselves) are not counted.

### nuclear

*function* · `packages/physics-nuclear/src/index.ts:69`

```ts
function nuclear(isotopes = new IsotopeLibrary(), shields = new ShieldLibrary()): NuclearCapability
```

### poisson

*function* · `packages/physics-nuclear/src/decay.ts:71`

```ts
function poisson(mean: number, rand: () => number): number
```

A count drawn from the Poisson law (Knuth for small means, the normal approximation above 50).

### rng

*function* · `packages/physics-nuclear/src/decay.ts:65`

```ts
function rng(seed: number)
```

Deterministic seeded stream (mulberry32).

### solve

*function* · `packages/physics-nuclear/src/reactor.ts:222`

```ts
function solve(A: number[][], b: number[]): number[]
```

Solve A·x = b by Gaussian elimination with partial pivoting.

### totalOf

*function* · `packages/physics-nuclear/src/radiation.ts:137`

```ts
function totalOf: (r: Record<RadiationKind, number>) => number
```

### wayWigner

*function* · `packages/physics-nuclear/src/reactor.ts:16`

```ts
function wayWigner(tau: number, top = Infinity): number
```

Way–Wigner: fraction of the operating power left as decay heat τ seconds after shutdown from `top` seconds of operation.

## Interfaces

### AssemblyEntry

*interface* · `packages/physics-nuclear/src/index.ts:46`

```ts
interface AssemblyEntry extends Placed
```

- `assembly: Assembly`
- `spent: boolean`

### AssemblyEvent

*interface* · `packages/physics-nuclear/src/assembly.ts:32`

```ts
interface AssemblyEvent
```

- `type: 'critical' | 'disassembled'`
- `energy: number`
- `fissioned: number`
- `time: number`

### AssemblySpec

*interface* · `packages/physics-nuclear/src/assembly.ts:11`

```ts
interface AssemblySpec
```

- `mass: number` — kg of fissile material
- `criticalMass: number` — the bare critical mass of the material in this shape, kg (data)
- `reflector?: number` — critical mass is multiplied by this (a reflector < 1)
- `compression?: number` — density relative to the data's (compression > 1 lowers the critical mass as 1/c²)
- `exponent?: number` — exponent of k against m / m_c (1 = k equals the ratio)
- `generation?: number` — generation time, s
- `source?: number` — stray neutrons per second that start a chain
- `disassemblyEnergy: number` — J/kg of the assembly that blows it apart (data)
- `nucleusMass?: number` — kg per nucleus

### Capture

*interface* · `packages/physics-nuclear/src/activation.ts:7`

```ts
interface Capture
```

A capture that makes a radioactive nucleus: the stable `from` takes a neutron and becomes `to`, with a cross-section in barns (thermal Co-59: 37, Na-23: 0.53).

- `from: string`
- `to: string`
- `sigma: number`

### DecayResult

*interface* · `packages/physics-nuclear/src/decay.ts:98`

```ts
interface DecayResult
```

- `heat: number` — J left in the matter by the decays of the step
- `decays: Map<string, number>` — decays of each isotope in the step
- `emitted: Record<RadiationKind, number>` — particles of each kind that left

### IsotopeDef

*interface* · `packages/physics-nuclear/src/decay.ts:10`

```ts
interface IsotopeDef
```

- `halfLife: number` — seconds; Infinity for a stable nucleus
- `daughter?: string` — what it becomes (a name in the library); missing = leaves the books
- `energy: number` — total energy per decay, J
- `retained?: number` — share of it that stays in the matter and becomes heat (1 when the radiation is absorbed where it is born)
- `emits?: Partial<Record<RadiationKind, number>>` — particles of each kind that leave the source per decay
- `atomicMass?: number` — kg per atom (for the mass of a quantity)

### Layer

*interface* · `packages/physics-nuclear/src/radiation.ts:33`

```ts
interface Layer
```

- `material: string`
- `thickness: number`

### NuclearCapability

*interface* · `packages/physics-nuclear/src/index.ts:48`

```ts
interface NuclearCapability extends Capability
```

- `readonly isotopes: IsotopeLibrary`
- `readonly shields: ShieldLibrary`
- `readonly sources: Map<string, SourceEntry>`
- `readonly receivers: Map<string, ReceiverEntry>`
- `readonly reactors: Map<string, ReactorEntry>`
- `readonly assemblies: Map<string, AssemblyEntry>`
- `coefficients: Record<RadiationKind, number>`
- `addSource(name: string, o?: Placed & { body?: Body; inventory?: Inventory }): Inventory`
- `addReceiver(name: string, o: Placed & { sensitivity?: number; seed?: number; body?: Body }): ReceiverEntry`
- `addReactor(name: string, spec: ReactorSpec, o?: Placed): Reactor`
- `addAssembly(name: string, spec: AssemblySpec, o?: Placed): Assembly`
- `doseAt(receiver: string): Record<RadiationKind, number>` — Dose rate by kind at a receiver now, Sv/s (through the scene's shielding).

### ReactorEntry

*interface* · `packages/physics-nuclear/src/index.ts:45`

```ts
interface ReactorEntry extends Placed
```

- `reactor: Reactor`

### ReactorEvent

*interface* · `packages/physics-nuclear/src/reactor.ts:82`

```ts
interface ReactorEvent
```

- `type: 'scram' | 'prompt' | 'melt'`
- `time: number`

### ReactorSpec

*interface* · `packages/physics-nuclear/src/reactor.ts:38`

```ts
interface ReactorSpec
```

- `power: number` — nominal fission power, W
- `generation?: number` — prompt neutron generation time, s
- `groups?: { beta: number[]; lambda: number[] }` — delayed groups (defaults to thermal fission)
- `rodWorth: number` — reactivity worth of the whole rod travel, Δρ, and the rod position (0 out .. 1 in) at which the core is critical at nominal
- `rodsCritical: number`
- `rods?: number`
- `fuelCoefficient?: number` — temperature coefficients, Δρ per K (negative = self-stabilising)
- `coolantCoefficient?: number`
- `voidCoefficient?: number` — Δρ for a fully voided core and the coolant temperature span over which it boils out
- `boil?: [number, number]`
- `fuelHeat: number` — J/K of the fuel and of the coolant with its structure
- `coolantHeat: number`
- `exchange: number` — W/K from fuel to coolant, and the W/K the coolant loses to the heat sink (flow·cp) at inlet temperature
- `flow: number`
- `inlet?: number`
- `xenon?: { worth: number; burnout?: number; iodine?: number }` — Xenon-135 poisoning. `worth` is the reactivity the equilibrium xenon takes at nominal power (about 0.025 for a thermal core; the rods are critical with it, so a core at nominal power has no xenon term). `burnout` is the burn-out rate at nominal flux over the decay rate of xenon (about 3 to 4); `iodine` the share of the xenon yield that comes by iodine-135 (0.95).
- `burnup?: { worth: number; energy: number }` — Burn-up: the fuel loses reactivity as it burns, `worth` (Δρ) for each `energy` joules of fission energy released (a core of 1 GW(th) for 500 days is 4e16 J; ~30 000 MWd/t is about 0.1 of the fissile loss). The rods make up for it, so a core whose rods are at the end of their travel is a spent core. Both are linear: the model has no fission-product poisoning but xenon.
- `melt?: number` — the fuel melts here, K
- `scramSpeed?: number` — rod speed in a scram, 1/s of the full travel
- `trip?: { power?: number; fuel?: number }` — trips: scram automatically above this power (× nominal) or this fuel temperature

### ReceiverEntry

*interface* · `packages/physics-nuclear/src/index.ts:34`

```ts
interface ReceiverEntry extends Placed
```

- `dose: number` — Sv so far and Sv/s now
- `rate: number`
- `sensitivity?: number` — counts per Sv for a counter (a Geiger tube is about 6·10⁹)
- `counts: number`
- `body?: Body`
- `next: number`
- `stream: () => number`

### ShieldMaterial

*interface* · `packages/physics-nuclear/src/radiation.ts:9`

```ts
interface ShieldMaterial
```

Radiation transport, lumped: a point source gives a fluence that falls as 1/(4πr²); each material along the ray takes a part of it away
by its half-value layer; a dose coefficient turns the fluence into a dose. Alphas stop by range, not by a half-value layer.

- `halfValue?: Partial<Record<RadiationKind, number>>` — half-value layer by kind, m: the thickness that halves the beam
- `alphaRange?: number` — how far an alpha gets in it, m
- `buildup?: number` — build-up of scattered radiation behind the shield: B = 1 + buildup·μx (0 = none)

### SourceDef

*interface* · `packages/physics-nuclear/src/radiation.ts:113`

```ts
interface SourceDef
```

- `position: Vec3`
- `inventory: Inventory`
- `body?: Body` — the body that carries it (not counted as a shield)

### SourceEntry

*interface* · `packages/physics-nuclear/src/index.ts:33`

```ts
interface SourceEntry extends Placed
```

- `inventory: Inventory`
- `body?: Body`

## Types

### RadiationKind

*type* · `packages/physics-nuclear/src/decay.ts:8`

```ts
type RadiationKind = 'alpha' | 'beta' | 'gamma' | 'neutron'
```

## Constants

### BARN

*const* · `packages/physics-nuclear/src/activation.ts:4`

```ts
const BARN: 1e-28
```

1 barn in m².

### DECAY_FRACTION

*const* · `packages/physics-nuclear/src/reactor.ts:36`

```ts
const DECAY_FRACTION: number
```

the steady share of the fission energy that comes out later as decay heat

### DELAYED_GROUPS

*const* · `packages/physics-nuclear/src/reactor.ts:10`

```ts
const DELAYED_GROUPS: { beta: number[]; lambda: number[]; }
```

Standard thermal-fission delayed groups: fractions and decay constants (1/s).

### E_FISSION

*const* · `packages/physics-nuclear/src/reactor.ts:7`

```ts
const E_FISSION: 3.2e-11
```

A lumped power reactor: point kinetics with six delayed-neutron groups, reactivity from the rods and from the temperatures of the fuel
and the coolant, a two-lump thermal model, and the decay heat of the fission products. Everything is data; there is no geometry.

### EXAMPLE_DOSE_COEFFICIENTS

*const* · `packages/physics-nuclear/src/radiation.ts:31`

```ts
const EXAMPLE_DOSE_COEFFICIENTS: Record<RadiationKind, number>
```

Sv·m² per particle that crosses a square metre (fluence-to-dose, order of magnitude for ~1 MeV).

### EXAMPLE_ISOTOPES

*const* · `packages/physics-nuclear/src/decay.ts:29`

```ts
const EXAMPLE_ISOTOPES: Record<string, IsotopeDef>
```

A few real isotopes with their well-known half-lives, as sample data; a game writes its own.

### EXAMPLE_SHIELDS

*const* · `packages/physics-nuclear/src/radiation.ts:19`

```ts
const EXAMPLE_SHIELDS: Record<string, ShieldMaterial>
```

Textbook values for roughly 1 MeV photons and fast neutrons (as sample data).

### FISSION_ENERGY_PER_KG

*const* · `packages/physics-nuclear/src/assembly.ts:9`

```ts
const FISSION_ENERGY_PER_KG: number
```

A runaway assembly in the one-group, lumped sense: the multiplication k follows from the mass against a critical mass the game
supplies (with a reflector factor and a compression), the fission rate grows on the generation time as dF/dt = (k − 1)/Λ · F + S, and
the assembly comes apart as it heats, which ends the reaction. This is a model for a game's accident or device record, with the
numbers in the data; it has no geometry and is too coarse to be a design tool.

### MEV

*const* · `packages/physics-nuclear/src/decay.ts:5`

```ts
const MEV: 1.602176634e-13
```

Radioactive decay: isotopes with half-lives and daughters, an inventory that decays exactly (the matrix exponential of the decay
network, so a chain of any length closes), the heat the decays leave in the matter, and a seeded Poisson stream for counters.

### NUCLEAR_DEFAULTS

*const* · `packages/physics-nuclear/src/index.ts:30`

```ts
const NUCLEAR_DEFAULTS: { doseStep: number; }
```

nuclear processes. Inventories of isotopes decay with the world (the heat goes to H when the carrier has a temperature),
dose accumulates in receivers through the shielding the scene puts in the way, reactors run on point kinetics with feedback and decay
heat, and a runaway assembly ends in an energy that is handed to X as a blast.

values (each at world / level / zone / entity scope):
  doseStep    dose between two `radiation:dose` events, Sv   (1e-3)

events: `decay` { source, decays }, `radiation:dose` { receiver, dose }, `radiation:counts` { receiver, n },
        `reactor:scram` / `reactor:prompt` / `reactor:melt` { name }, `assembly:critical` { name }, `assembly:disassembled` { name, energy, tnt }.

### Sv_PER_MSV

*const* · `packages/physics-nuclear/src/radiation.ts:138`

```ts
const Sv_PER_MSV: 0.001
```

### YEAR

*const* · `packages/physics-nuclear/src/decay.ts:6`

```ts
const YEAR: number
```

