@ferret/physics-explosions
blast waves, craters, fragments and spall from scaled-distance laws.
Read the guide: how to use it →
Functions
arrivalTime function
function arrivalTime(r: number, tnt: number, curve: BlastCurve = KINNEY_GRAHAM): numberTime the front takes to reach r: the integral of dR / U with the Rankine-Hugoniot shock speed U = c·sqrt(1 + 6 Ps / 7 P0).
packages/physics-explosions/src/blast.ts:47
blastAt function
function blastAt(r: number, tnt: number, curve: BlastCurve = KINNEY_GRAHAM): BlastPointThe blast at distance r from a charge of tnt kg: the wave is taken as a triangle, so the impulse is Ps·t+/2.
packages/physics-explosions/src/blast.ts:40
blastLoad function
function blastLoad(ps: number, area: number, drag = 1, ambient = P_ATM): numberForce a drag body takes in the blast: (peak overpressure around it, in the diffraction phase) plus drag times dynamic pressure.
packages/physics-explosions/src/blast.ts:154
blastWind function
function blastWind(ps: number, ambient = P_ATM): { speed: number; dynamic: number }Wind behind the front: speed u = c 5 Ps / (7 P0) / sqrt(1 + 6 Ps / 7 P0) and the dynamic pressure q = 5 Ps^2 / (2 (7 P0 + Ps)) that pushes on what stands in it.
packages/physics-explosions/src/blast.ts:148
craterRadius function
function craterRadius(law: CraterLaw, tnt: number, burial = 0): numberCrater radius for a charge of tnt kg whose centre is buried burial m: the surface-burst scaling times a burial factor.
packages/physics-explosions/src/blast.ts:127
diffracted function
function diffracted(tnt: number, source: number[], edge: number[], target: number[], curve: BlastCurve = KINNEY_GRAHAM): { path: number; turn: number; overpressure: number; arrival: number }Diffraction around an edge, as a path and a loss: the front reaches a point in the shadow by the way over the edge (path = to the edge +
from the edge), so it arrives later and lower than in the open: the pressure is the free-field value at that path length times
1 / (1 + turn / pi x 2), where turn is the angle the way bends at the edge (0 = no shadow). It is an engineering approximation, not a
wave solution: it is continuous at the shadow boundary, falls with the bend and with the longer path.
packages/physics-explosions/src/blast.ts:180
ejecta function
function ejecta(craterR: number, mass: number, gravity = 9.81, mu = 0.55, c = 0.5): EjectaWhat a crater throws out (Housen-Holsapple scaling): material leaving at radius r from the centre goes at v = c sqrt(g R) (R / r)^(1/mu), so the mass faster than v is the whole ejected mass x (v / v(R))^(-3 mu) and it lands at v^2 sin(2 angle) / g.
packages/physics-explosions/src/blast.ts:196
explosions function
function explosions(o: ExplosionOptions = {}): ExplosionCapabilitypackages/physics-explosions/src/index.ts:107
gurneyVelocity function
function gurneyVelocity(casing: number, charge: number, shape: CasingShape = 'cylinder', gurney = TNT_GURNEY): numberGurney: v = sqrt(2E) / sqrt(M/C + k), with k = 1/2 (cylinder), 3/5 (sphere), 1/3 (open plate, one side).
packages/physics-explosions/src/blast.ts:82
mottMasses function
function mottMasses(total: number, mu: number, rand: () => number, max = 10000): number[]Mott: masses of fragments with the cumulative number N(m) = (M / 2mu)·exp(-sqrt(m/mu)); so the mean mass is 2·mu and the number M/(2·mu). The masses are drawn as mu·E² with E exponential, then scaled so they add up to M exactly.
packages/physics-explosions/src/blast.ts:97
obliqueReflection function
function obliqueReflection(ps: number, incidence: number, ambient = P_ATM): numberThe reflected overpressure at an incidence angle (0 = head on, 90 deg = grazing): the head-on value blends to the incident one with cos^2, a standard engineering fit that Mach reflection beyond about 40 deg only raises.
packages/physics-explosions/src/blast.ts:142
penetrate function
function penetrate(o: { mass: number; speed: number; angle: number; area: number } & Armour & { grazing?: number }): PenetrationWhat a fragment does to a plate, by its energy against the work of pushing a hole through: the plate resists with its strength over the fragment's presented area along the slant thickness t / cos θ (θ from the plate's normal). Through when the energy is more than that work, with the speed the rest gives; stopped in it otherwise, at the depth the energy reaches; and at a grazing angle (past grazing, 70° by default) a fragment that could not get through the slant skids off: a ricochet.
packages/physics-explosions/src/index.ts:40
radiusFor function
function radiusFor(pressure: number, tnt: number, curve: BlastCurve = KINNEY_GRAHAM): numberThe distance at which the peak overpressure falls to pressure (Pa); the radius of a given damage ring.
packages/physics-explosions/src/blast.ts:59
reflectedPressure function
function reflectedPressure(ps: number, ambient = P_ATM): numberPeak pressure on a wall the front meets head on (normal reflection of an ideal gas): Pr = 2Ps (7P0 + 4Ps) / (7P0 + Ps), so 2 Ps for a weak wave and up to 8 Ps for a strong one.
packages/physics-explosions/src/blast.ts:137
rng function
function rng(seed: number)A seeded generator (mulberry32): the same seed, the same pieces.
packages/physics-explosions/src/blast.ts:88
scaledDistance function
function scaledDistance: (r: number, tnt: number) => numberHopkinson-Cranz scaled distance, m/kg^(1/3).
packages/physics-explosions/src/blast.ts:35
spall function
function spall(stress: number, duration: number, tensile: number, density: number, waveSpeed: number, wall: number): SpallHopkinson spalling: the compression pulse in a wall (peak stress, length duration x wave speed) comes back from the free back face as
tension; it tears off a slab where the tension passes tensile, a slab as thick as the length of the pulse's part that exceeds it
(at most half the wall), and the slab leaves with the momentum of the pulse above the strength: speed = impulse above it / (rho x slab).
packages/physics-explosions/src/blast.ts:164
underwaterAt function
function underwaterAt(r: number, tnt: number): { overpressure: number; theta: number; impulse: number }Under water (Cole): the peak pressure and the decay constant of the exponential pulse; the impulse is their product.
packages/physics-explosions/src/blast.ts:67
vesselTnt function
function vesselTnt(pressure: number, volume: number, gamma = 1.4, ambient = P_ATM): numberThe charge of a vessel bursting under pressure (Brode): E = (p1 - p0)·V / (gamma - 1), as kg of TNT.
packages/physics-explosions/src/blast.ts:74
Interfaces
Armour interface
interface ArmourA plate a fragment meets: its thickness (m) and the stress (Pa) it resists a projectile with (≈ 3× the tensile strength for steel).
thickness: number | |
strength: number |
packages/physics-explosions/src/index.ts:31
BlastCurve interface
interface BlastCurveoverpressure(z: number): number | peak incident overpressure, Pa, at scaled distance z (m/kg^(1/3)) |
duration(z: number): number | positive-phase duration, s per kg^(1/3) |
packages/physics-explosions/src/blast.ts:14
BlastPoint interface
interface BlastPointoverpressure: number | |
duration: number | |
impulse: number | |
arrival: number | |
scaled: number |
packages/physics-explosions/src/blast.ts:37
Casing interface
interface Casingmass: number | |
shape?: CasingShape | |
mu?: number | |
density?: number | |
gurney?: number |
packages/physics-explosions/src/index.ts:49
CraterLaw interface
interface CraterLawk: number | apparent radius of a surface burst of 1 kg: R = k·W^(1/3.4), m |
depthRatio: number | depth / radius of the apparent crater |
camouflet: number | scaled depth of burial (m/kg^(1/3)) at which no crater opens (a camouflet) |
throw: number | share of the heap thrown out beyond the rim |
packages/physics-explosions/src/blast.ts:106
DetonateDef interface
interface DetonateDefat: Vec3 | |
tnt?: number | kg of TNT equivalent, or ... |
energy?: number | ... joules |
burst?: BurstKind | |
burial?: number | depth of the charge centre under the ground, m |
casing?: Casing | |
seed?: number | |
vessel?: { pressure: number; volume: number; gamma?: number } | a vessel that bursts: {pressure, volume, gamma?} (Brode) in place of tnt |
packages/physics-explosions/src/index.ts:50
Ejecta interface
interface Ejectavelocity: (r: number) => number | |
massFaster: (v: number) => number | |
range: (r: number, angle?: number) => number | |
total: number |
packages/physics-explosions/src/blast.ts:191
ExplosionCapability interface
interface ExplosionCapability extends Capabilitydetonate(def: DetonateDef): ExplosionResult | |
preview(tnt: number, pressures: number[]): number[] | Radii (m) at which the peak overpressure falls to each of the given values (Pa). |
setTerrain(t: Terrain | undefined): void | |
readonly fragments: ReadonlySet<Entity> |
packages/physics-explosions/src/index.ts:87
ExplosionOptions interface
interface ExplosionOptionsterrain?: Terrain | |
curve?: BlastCurve | |
craters?: Record<string, CraterLaw> | |
maxFragments?: number | fragments alive at once; the oldest are recycled |
perFrame?: number | fragments created per step |
fragmentLife?: number | seconds a fragment lives |
packages/physics-explosions/src/index.ts:75
ExplosionResult interface
interface ExplosionResulttnt: number | |
effective: number | effective yield after the ground reflection / coupling, kg |
bodies: number | |
fragments: number | |
crater?: { radius: number; depth: number; removed: number; thrown: number; fallback: number } | |
camouflet: boolean |
packages/physics-explosions/src/index.ts:65
Penetration interface
interface Penetrationoutcome: 'through' | 'stopped' | 'ricochet' | |
depth: number | |
exitSpeed: number | |
slant: number |
packages/physics-explosions/src/index.ts:32
Spall interface
interface Spallspalls: boolean | |
thickness: number | |
speed: number |
packages/physics-explosions/src/blast.ts:158
WallSpec interface
interface WallSpecA wall that a blast meets: its tensile strength (Pa), density, speed of sound in it and thickness (m); when the reflected pulse tears a slab off the back, explosion:spall follows.
tensile: number | |
density: number | |
waveSpeed: number | |
thickness: number |
packages/physics-explosions/src/index.ts:27
Types
BurstKind type
type BurstKind = 'air' | 'surface' | 'buried' | 'water'packages/physics-explosions/src/index.ts:47
CasingShape type
type CasingShape = 'cylinder' | 'sphere' | 'plate'packages/physics-explosions/src/blast.ts:79
Constants
EXAMPLE_CRATERS const
const EXAMPLE_CRATERS: Record<string, CraterLaw>packages/physics-explosions/src/blast.ts:117
EXPLOSION_DEFAULTS const
const EXPLOSION_DEFAULTS: { minPressure: number; rupture: number; area: number | undefined; transmission: number; spread: number; armour: Armour | undefined; wall: WallSpec | undefined; }packages/physics-explosions/src/index.ts:28
KINNEY_GRAHAM const
const KINNEY_GRAHAM: BlastCurvepackages/physics-explosions/src/blast.ts:21
P_ATM const
const P_ATM: 101325packages/physics-explosions/src/blast.ts:9
SOUND_SPEED const
const SOUND_SPEED: 340.3packages/physics-explosions/src/blast.ts:10
TNT_GURNEY const
const TNT_GURNEY: 2440Gurney constant sqrt(2E) of TNT, m/s
packages/physics-explosions/src/blast.ts:12
TNT_JOULES_PER_KG const
const TNT_JOULES_PER_KG: 4184000The laws of a blast as plain functions: scaled distance, overpressure, positive-phase duration and impulse, the under-water pulse, Gurney velocity, Mott fragment masses and cratering. Units are SI; yield is in kilograms of TNT equivalent.
The air curve is the Kinney-Graham fit of the free-air burst; it is the data slot a Kingery-Bulmash table can replace
(BlastCurve), and every capability function below takes the curve as an argument.
packages/physics-explosions/src/blast.ts:8