Theory & User Guide
How PIBS's interior-ballistics solver actually works, and everything needed to run it — from a first install to a worked recoilless-gun case. Every number below comes from solving the presets already bundled with the project; nothing is invented.
Theoretical Model
A direct read of pibs/ballistics/ — what the solver computes, not a black-box description. Follows the Serebryakov-system reduced-variable formulation used in Soviet/PRC ballistics literature (§References).
§1Scope: what "interior ballistics" means here
Interior ballistics covers the phase from primer ignition to shot exit: propellant burns, gas pressure builds, the shot accelerates down the bore. PIBS solves the forward problem (given a design, compute its pressure/velocity trace, §1–§10) and the inverse/constrained problem (given performance targets, solve for the grain web size and barrel length, §11) — both available in either GUI.
The model is 0-dimensional in the combustion chamber (space-mean pressure) with a 1-dimensional correction for the pressure gradient along the bore (§6). It is not a CFD simulation — no radial structure, no turbulence, no ignition transient. That trade-off buys design-level accuracy in seconds rather than hours.
§2Reduced (dimensionless) variables
Rather than integrate pressure, travel, velocity and time in SI units directly, the solver non-dimensionalizes everything against charge/gun-specific scales — this is what "reduced form" means in the README, and why gun.py variable names look like p_bar, l_bar, v_bar, t_bar: the _bar suffix denotes the dimensionless version.
| Quantity | Scale | Reduced variable |
|---|---|---|
| Pressure | p_scale = f·Δ | p_bar = p / p_scale |
| Travel | l₀ = V₀ / S | l_bar = l / l₀ |
| Velocity | v_j = √(2f·w / (θ·φ·m)) | v_bar = v / v_j |
| Time | t_scale = l₀ / v_j | t_bar = t / t_scale |
| Burnt fraction | web-normalized | Z = e / e₁ ∈ [0, Z_b] |
where f is propellant force (specific combustion energy, J/kg); Δ = w/V₀ is loading density; w/m are charge/shot mass; θ is the reduced adiabatic index (θ=γ−1); φ is the fictitious mass factor (§5) — shot mass alone under-accounts for how much mass the pressure has to accelerate, since the propellant gas itself has inertia; e₁ is grain half-web (Z=1 is when the primary grain shape burns through, Z=Z_b≥1 is complete combustion — §3).
v_j is the theoretical maximum velocity the charge could impart to the shot in the idealized limit of complete, instantaneous burning with no losses — the natural velocity scale for the problem.
§3Propellant charge model
3.1 Form functions
As a grain burns, its burning-surface area changes with the fraction of web consumed — the "form function". PIBS uses the standard cubic form function:
ψ(Z) is the burnt mass fraction; σ(Z) its derivative — the burning-surface area relative to the initial grain surface. The coefficients (χ, λ, μ) — and (χₛ, λₛ, Z_b) for grains that keep burning past Z=1 — are not free parameters; they're derived from grain geometry:
- Simple geometries (
SimpleGeometry): sphere, cylinder, tube, strip. Two shape ratiosα=e₁/b,β=e₁/cfully determine(χ,λ,μ); these grains burn out atZ_b=1— no secondary phase. - Multi-perforated geometries (
MultPerfGeometry): 7/14/19-perf cylinders, rosettes, hexagons. Start progressive (burning surface increases as perforations enlarge) until the web between perforations is consumed atZ=1, then the grain fragments into slivers that burn degressively for1<Z≤Z_b. This progressive-then-degressive shape is why multi-perf propellant is standard in high-performance guns — it front-loads surface growth to offset falling pressure as chamber volume increases with shot travel.
A Propellant can mix two grain populations (main + auxiliary, independently sized/shaped) plus an optional combustible-cartridge fraction (case material that itself burns and contributes gas).
3.2 Burn rate law
Grains regress per Vieille's/Muraour's law — linear in pressure raised to a propellant-specific exponent:
u₁ (burn rate coefficient) and n (pressure exponent) come from the propellant composition (propellants.csv — 40 bundled compositions from published references), independent of geometry (grain shape) — composition × geometry = grain, combined multiplicatively in the Propellant class.
§4Equation of state & space-mean pressure
Propellant gas is modeled with the Nobel–Abel (covolume) equation of state — ideal gas with a correction α for the finite volume the gas molecules occupy at high density. Combined with conservation of energy (chemical energy released = kinetic energy of shot and gas + friction/counter-pressure work), the space-mean pressure falls out as an algebraic function of the current state — no separate energy ODE needed:
l_ψ_bar is the "unburnt propellant + covolume" correction to available expansion length: (1−ψ)/ρ_p accounts for volume still occupied by solid unburnt propellant, α·ψ for the covolume of gas already produced. This is Gun.f_p_bar() — evaluated fresh every integration step, not itself an ODE state variable.
§5Equation of motion
With p_bar available algebraically, the reduced-variable ODE system (time domain) is:
b is a dimensionless grouping of burn-rate/geometry/energy terms: b = S²e₁² / (f·φ·w·m·u₁²) · (f·Δ)^(2(1−n)) (S = bore area). p_ad_bar is the ambient aerodynamic counter-pressure (§7).
gun.py solves this system in three different independent variables depending on numerical convenience at each stage: ode_t (time), ode_l (travel — needed once v_bar is no longer small, since 1/v_bar blows up at t=0), ode_z (burnt fraction — robustly locates burnout/exit even as dZ/dt→0 near full burn). Same physics, three re-parameterizations for robustness at different phases of the shot.
The φ (fictitious mass) factor
Newton's law needs a mass to divide by, but only the shot's mass is truly rigid — the propellant gas behind it also accelerates and carries kinetic energy. Rather than track the gas velocity field explicitly, this is lumped into a correction factor:
φ₁ = 1/(1−drag_coefficient) is the separate correction for bore friction/engraving resistance (the "Resistance %" input). λ₂ and the chambrage correction cc come from the pressure-gradient solution (§6) — where charge-to-shot mass ratio and gun geometry feed back into the acceleration itself, not just the pressure distribution.
§6Pressure gradient along the bore
Space-mean pressure (§4) is one number, but at any instant local pressure is highest at the breech (accelerating the gas column behind it) and lowest at the shot base — the classical Lagrange problem: gas of nonzero mass filling a tube, accelerated by pressure with a fixed shot at one end.
Two dimensionless distribution coefficients λ₁, λ₂ are computed once per gun, from one of three models (the "Gradient" setting):
SOL_LAGRANGE— the classical simplifying assumption: gas density uniform along the tube at every instant. Closed formλ₁=1/2, λ₂=1/3directly, no iteration.SOL_PIDDUCK— self-similar solution for a gas with adiabatic indexθ+1, solved via the integral equation∫₀¹ (1 − Ω·ξ²)^[1/(k−1)] dξ = [w/(2φ₁m)]·[(k−1)/k]·(1−Ω)^[k/(k−1)] / ΩforΩ(root-found with the Dekker method) —w/(φ₁m)is charge mass relative to the friction-corrected ("fictitious") shot mass, not the raw shot mass.λ₁,λ₂follow fromΩby further quadrature. The more physically complete model, and the default.SOL_MAMONTOV— thek→1(isothermal-gas) limit of the same Pidduck family, evaluated as a separate closed form to avoid the numerical0/0atk=1.
Given λ₁,λ₂ and a chambrage correction cc (chamber wider than bore, χ_k = chamber area / bore area), breech and shot-base pressures recover from space-mean pressure:
with λ₁',λ₂' further adjusted for shot travel. Pressure at an arbitrary axial probe point interpolates assuming a quadratic (Lagrangian) profile in the gas velocity field — this powers the desktop app's "Barrel Trace" plot and the tube-strength calculation.
§7Ambient / aerodynamic drag
Once propellant is exhausted (or even before, for high-velocity shots), the atmosphere ahead of the shot pushes back. Modeled as a counter-pressure term from the shot's velocity relative to local sound speed, using ambient density/pressure/adiabatic-index inputs (func_p_ad_bar()) — a standard supersonic-projectile drag correction. Switchable off (ambient density → 0), solving as if firing in vacuum ahead of the shot.
§8Characteristic points & numerical methods
The solver doesn't just uniformly sample the trajectory — it explicitly locates named events, each via the method suited to it:
| Event | Meaning | Method |
|---|---|---|
| SHOT_START | ignition, Z=Z₀ | initial condition |
| FRACTURE | Z=1, primary shape consumed (multi-perf only) | direct integration to Z=1 |
| BURNOUT | Z=Z_b, propellant fully consumed | direct integration to Z=Z_b |
| SHOT_EXIT | l=l_g, barrel length reached | direct integration to l_bar=l_g_bar |
| PEAK_AVG/BREECH/SHOT_P | maxima of each pressure trace vs. time | Golden Section Search, independently |
Z₀ (burnt fraction at ignition) is itself root-found: given a user-specified start pressure (needed to shear the shot's rotating band / begin motion), the solver finds ψ(Z₀)=ψ₀ where ψ₀ comes from inverting the Nobel-Abel EOS at that pressure and zero travel — via the Dekker method (bisection/secant/inverse-quadratic hybrid, similar to Brent's method).
The ODE system integrates with an adaptive embedded Runge–Kutta–Fehlberg scheme, self-adjusting step size to a user-set relative tolerance (-log10(ε) in the UI — e.g. 4 means tolerance 1e-4), with early-abort conditions (pressure exceeding the 600 MPa Nobel-Abel validity ceiling, or a squib condition where the shot stalls).
§9Recoilless guns
A recoilless gun vents propellant gas backward through a nozzle, countering breech reaction so the weapon needs no recoil mechanism. Recoilless extends the conventional model with two coupled state variables tracked through every step:
- η (eta) — cumulative mass fraction of propellant gas that has flowed out the nozzle rather than remaining in chamber/bore
- τ (tau) — a reduced temperature/energy ratio, since gas leaving through the nozzle carries away energy the simple closed-form pressure equation (§4) no longer captures alone
Space-mean pressure becomes p_bar = τ/(l_bar+l_ψ_bar)·(ψ−η) — compare §4: (ψ−η) replaces ψ, since only gas mass retained in the gun contributes to pressure — with dη, dτ integrated alongside Z, l_bar, v_bar.
Because a meaningful fraction of chemical energy is deliberately vented rather than accelerating the shot, recoilless guns have markedly lower thermal/ballistic efficiency than closed-breech guns for the same propellant — confirmed by the bundled examples: the 105mm M40A1 recoilless design solves to ~7% thermal efficiency vs. ~33% for the 76mm ZiS-3 conventional gun (Part II §5). Expected physical trade-off for eliminating recoil, not a modeling artifact.
§10Efficiencies
Three figures derived from the solved trace:
te measures how much of the theoretical maximum velocity (§2) was realized. be further corrects for φ, isolating losses from charge-to-shot mass ratio and pressure gradient rather than incomplete combustion. pe measures how efficiently peak pressure was "used" — flat-and-high for the whole travel (ideal) gives pe→1; a sharp early spike that decays wastes barrel length at sub-peak pressure and scores low.
§11Constrained design, optimization, and structural sizing
Everything above solves the forward problem: given a design, compute its performance. The pieces below build on that same core solver to solve the inverse problem (given performance targets, find a design) and to size the resulting barrel. All four are available in both the desktop app and the web GUI.
11.1 Constrained design (the inverse problem)
ConstrainedGun/ConstrainedRecoilless solve for grain web size and barrel length given a target velocity v_d and pressure p_d, via nested root-finding:
- For a chosen charge-to-shot mass ratio
w/mand chamber loading densityΔ/ρ_p("load fraction"), the charge mass and chamber volume — and hencel₀, Δ— are fixed. - The web (via half-web
e₁) is root-found with the Dekker method so the chosen pressure constraint point (space-mean, breech, or shot-base) exactly peaks atp_d: probing outward from a small starting web, doubling/halving until the sign ofp_peak(e₁) − p_dbrackets a root, then converging on it. - With
e₁fixed, the gun is integrated forward from that peak point until velocity reachesv_d, giving the required barrel lengthl_g. - Because the chambrage correction
cc(§6) depends onl_g, and the pressure-gradient coefficients in step 2 depend oncc, steps 2–3 repeat with the newly-convergedccuntill_gitself stops changing (bounded by a max iteration count).
An error here ("Solution requires excessive tube length...", "Design velocity exceeded before peak pressure point...") means the chosen charge ratio and loading density can't physically reach the target within the barrel-length search ceiling — not a numerical failure.
11.2 Optimization: minimum bore volume / minimum barrel length
Constrained.find_min_v() treats load fraction as a free variable instead of a fixed input: it searches it with Golden Section Search between the minimum load fraction (below which the design pressure is unreachable even in the closed-bomb limit — ψ₀ would exceed 1, §8) and the maximum (found by probing upward until the constrained solve in §11.1 stops converging), minimizing either total chamber+barrel volume (MIN_BARR_VOLUME) or barrel length alone (MIN_PROJ_TRAVEL).
11.3 Tube strength & autofrettage
Given the solved pressure trace, Gun.structure() sizes barrel wall thickness at each axial probe point using thick-walled cylinder theory under the Tresca (maximum shear stress) yield criterion, against the highest pressure ever reached at that axial position across the entire trace (not just when the shot happens to pass it — the pressure envelope over time, §6), scaled by a safety factor.
Monoblock (single-piece barrel) — for inner:outer radius ratio k:
Thickening the wall (raising k) lets it contain a higher p without the bore exceeding yield strength σ_y — but this construction is mathematically impossible above p = σ_y/2, regardless of wall thickness.
Autofrettage — the barrel is first pressurized beyond yield so it retains a residual compressive pre-stress at the bore once depressurized; working pressure must overcome that pre-stress before the bore sees net tension. The optimal autofrettage radius ratio:
has no p = σ_y/2 ceiling — which is why high-pressure guns are routinely autofrettaged rather than built monoblock. Barrel volume (and hence estimated tube mass) is integrated from these radius ratios along the bore.
11.4 Guidance diagrams
A guidance diagram maps every design — across a grid of charge-to-shot mass ratios and chamber loading densities — that satisfies a given velocity/pressure target, showing how barrel length and chamber volume trade off across that space. It's §11.1's constrained solve repeated at every grid point: for each charge ratio, the maximum feasible load fraction is found, then every load fraction from the minimum up to that maximum (in steps) is solved individually, keeping only the combinations that converge to a physically valid design.
The desktop app parallelizes this sweep across CPU cores, since a single diagram can mean solving hundreds of individual designs. The web GUI instead runs it sequentially — spawning worker processes from inside a Streamlit rerun is unsafe on Windows' spawn start method, since each worker would try to re-import and re-run the Streamlit script itself — so keep the sweep grid modest there.
RefsReferences
As cited in the source (docstrings, pidduck() in gun.py, and bundled example descriptions):
- 金志明 (2014). 《枪炮内弹道学》(Interior Ballistics of Guns).
- 鲍廷钰,邱文坚 (1995). 《内弹道学》(Interior Ballistics).
- 王连荣,张佩勤 (1987). 《火炮内弹道计算手册》, National Defense Industry Press.
- 兵器工业部第二管理局 (1982). 《国产火炮手册》.
- Multiple Russian-language ordnance service manuals, cited per-example in
pibs/examples/*.json.
User Guide — Zero to Hundred
Installing PIBS, running both GUIs, understanding every input and output, and two full worked examples — using only the presets already bundled with the project. Nothing here is invented.
§1Which interface do I use?
| Desktop app | Web app | |
|---|---|---|
| Forward calculation | ✓ | ✓ |
| Constrained design | ✓ | ✓ |
| Optimization | ✓ | ✓ |
| Tube strength / autofrettage | ✓ | ✓ |
| Guidance diagrams | ✓ | ✓ |
| Runs headless / on a server | — | ✓ |
| Conventional guns | ✓ | ✓ |
| Recoilless guns | ✓ | ✓ |
| Save/load custom design & propellant files | ✓ | — |
| Localization (English / 中文) | ✓ | — |
Both interfaces now cover the same calculations. Use the web app if you don't have a desktop session, want to explore designs quickly, or are deploying somewhere headless; use the desktop app if you need to save/load your own custom design or propellant files, or want the Chinese-language interface.
§2Installation
Activate the environment:
Install what you need:
Requires Python ≥ 3.9 (the desktop app additionally needs tkinter and a display — standard on Windows/most Linux desktops, not on headless servers).
§3Running the apps
§4Worked example — Web GUI, demo mode, conventional gun
Exactly what you'll see using the bundled Guns/76x385_ZiS-3_UOF-354AM preset — the 76×385mm round fired from the Soviet ZiS-3 divisional gun (M1942).
- Open the web app, leave the sidebar on "Demo (load example)".
- In the Example dropdown, pick
Guns/76x385_ZiS-3_UOF-354AM. - Click Load & Solve.
The design loaded, verbatim from the bundled JSON:
| Caliber | 76.2 mm |
| Shot mass | 6.2 kg |
| Charge mass | 1.08 kg |
| Chamber volume | 1.484 L |
| Chambrage ratio | 1.1 |
| Start pressure | 30.0 MPa |
| Travel | 2687.0 mm |
| Web (grain thickness) | 8.2872 mm |
| Propellant | [GAU Table] |
| Grain geometry | SEVEN_PERF_CYLINDER |
Solved result (actual solver output, reproducible by running the preset yourself):
| Event | Time | Travel | Burnt | Velocity | Avg P | Breech P | Shot P |
|---|---|---|---|---|---|---|---|
| SHOT_START | 0 ms | 0 mm | 2.4% | 0 m/s | 30.0 | 30.7 | 28.6 |
| PEAK_AVG_P | 2.80 ms | 262 mm | 51.7% | 270 m/s | 261.3 | 267.6 | 248.9 |
| BURNOUT | 5.57 ms | 1548 mm | 100% | 603 m/s | 100.2 | 102.8 | 95.3 |
| SHOT_EXIT | 7.32 ms | 2687 mm | 100% | 684.8 m/s | 53.2 | 54.6 | 50.6 |
Breech pressure is always a little higher than average, which is always higher than shot-base pressure — the pressure gradient from Part I §6, not numerical noise. The propellant is fully burnt well before the shot exits (57.6% of the way down the barrel) — pressure past that point falls purely from volume expansion of already-generated gas.
§5Worked example — recoilless gun
Recoilless/105x607_Type75(M40A1)_HEAT-FS — the 105mm HEAT-FS round for the Type 75 (M40A1) recoilless rifle. In the web app, pick this preset under Demo, or select Manual input → Gun Type RECOILLESS (pre-fills matching defaults for a from-scratch recoilless design).
| Caliber | 105.0 mm |
| Shot mass | 7.96 kg |
| Charge mass | 3.6 kg |
| Chamber volume | 7.2 L |
| Chambrage ratio | 1.7 |
| Start pressure | 5.48 MPa |
| Travel | 2683.0 mm |
| Web | 0.834 mm |
| Propellant | Pyroxylin |
| Grain geometry | FOURTEEN_PERF_ROSETTE |
| Nozzle expansion ratio | 1.125 |
| Nozzle efficiency | 100% |
Compare 7.3% thermal efficiency here against 33.0% for the conventional ZiS-3 above — a similar-caliber, similar-pressure comparison. That ~4–5× gap is the real, expected physical cost of a recoilless gun venting propellant gas out the nozzle to cancel recoil (Part I §9), not a bug.
Nozzle Expansion Ratio is the nozzle exit-to-throat area ratio; Nozzle Efficiency is a 0–100% loss factor for non-ideal nozzle flow. If caliber/chambrage/expansion-ratio can't physically fit a large-enough throat into the breech face, the solver raises "Achieving recoilless condition necessitates a larger throat area than could be fit into breech face" — an infeasible-design error, not a numerical failure; widen chambrage or reduce nozzle expansion to fix it.
Constrained design and tube structural sizing for recoilless guns are also available in the web GUI — see §7 and §8.
§6Manual input mode
Use this to explore a design of your own rather than a bundled preset. Switching the Gun Type radio immediately reloads all fields with a self-consistent starting design for that type — a conventional gun and a recoilless gun need very different pressure/web combinations (see the two worked examples above for why). Click Solve Gun immediately to see a working baseline, then change fields from there.
| Field | Meaning | Core parameter |
|---|---|---|
| Caliber | Bore diameter | caliber |
| Shot Mass | Projectile mass | shot_mass |
| Charge Mass | Propellant mass | charge_mass |
| Chamber Volume | Volume behind shot at start | chamber_volume |
| Travel / Barrel Length | Distance shot travels in bore | length_gun |
| Chambrage Ratio | Chamber area ÷ bore area | chambrage |
| Start Pressure | Pressure at which shot begins to move | start_pressure |
| Web | Grain half-thickness × 2 | web |
| Bore Resistance | Friction/engraving work, % | drag_coefficient |
| Propellant Composition | Chemical propellant | propellant.composition |
| Grain Geometry | Physical grain shape | propellant.main_geom |
| Grain 1/α, 1/β | Shape ratios (Part I §3.1) | main_r1/r2 |
| Sample Points | Points sampled along the trace | step |
| Nozzle Expansion Ratio (recoilless) | Exit ÷ throat area | nozzle_expansion |
| Nozzle Efficiency (recoilless) | Non-ideal flow loss factor | nozzle_efficiency |
§7Constrained design mode (web GUI)
Select Constrained design in the sidebar. This solves the inverse problem (Part I §11.1): given a target velocity and pressure, a chosen charge-to-shot mass ratio, and a chamber loading density, it finds the grain web size and barrel length that hit those targets exactly — rather than you specifying web/length directly.
Worked example: leave everything at its CONVENTIONAL default (which mirrors the ZiS-3 example's real charge ratio and loading density — Charge / Shot Mass Ratio 0.174, Load Fraction 45.5%) and click Solve Constrained Design. Solved output (reproducible):
| Solved quantity | Value | Reference (ZiS-3 actual) |
|---|---|---|
| Web | 8.2849 mm | 8.2872 mm |
| Chamber Volume | 1.482 L | 1.484 L |
| Barrel Length | 2596.7 mm | 2687.0 mm |
| Charge Mass | 1.079 kg | 1.08 kg |
Running the resulting design forward gives muzzle velocity 680.0 m/s and peak avg. pressure 261.3 MPa — exactly the target values entered, by construction. The small differences from the ZiS-3 reference numbers come from the constrained solver finding a self-consistent design meeting those two targets at that charge ratio and loading density, not necessarily bit-identical geometry to the historical gun (which had other constraints, like a fixed production barrel length, that this solve doesn't know about).
find_min_v(), Part I §11.2), instead of using the fixed value you specify. This searches the entire feasible range and can land near the Max Barrel Length search ceiling — if solving fails with "Solution requires excessive tube length", raise that ceiling or narrow the charge ratio.Lock barrel length: check this to fix barrel length yourself and solve only for web size, useful when barrel length is a hard constraint (e.g. matching an existing gun) rather than something to solve for.
This mode works identically for RECOILLESS — switching Gun Type reloads matching defaults (based on the 105mm M40A1 example) and adds the Nozzle Expansion Ratio / Nozzle Efficiency fields, same as manual input mode.
§8Tube strength & autofrettage (web GUI)
After any successful solve — demo, manual, or constrained — an optional "Tube strength & autofrettage" section appears below the results. Expand it, set material density, yield strength, and safety factor, choose whether to autofrettage, and click Compute Tube Strength (Part I §11.3).
It reports estimated tube mass and plots the barrel cross-section: bore radius, outer radius, and (if autofrettaged) the elastic-plastic junction radius, along the length of the tube. For the ZiS-3 constrained-design result above with steel at 7850 kg/m³ density, 1000 MPa yield strength, 1.35 safety factor, and autofrettage enabled, this comes out to ~55 kg of tube — a plausible mass for a 76mm gun barrel.
§9Guidance diagram mode (web GUI)
Select Guidance diagram in the sidebar. This sweeps a grid of charge-to-shot mass ratios and chamber loading densities and plots every combination that reaches the target velocity/pressure (Part I §11.4) — a scatter of feasible designs, colored by the resulting barrel length, so you can see the volume/length trade-off across the whole design space at a glance, plus a full data table (downloadable as CSV).
§10Reading the output
Summary metrics: muzzle velocity, time to exit, three peak pressures, burnout travel, three efficiency figures.
Table Data — one row per named event plus evenly-spaced samples:
| Column | Meaning |
|---|---|
| Event | SHOT_START, SAMPLE, FRACTURE, BURNOUT, PEAK_*_P, SHOT_EXIT (Part I §8) |
| Time | Elapsed since ignition |
| Travel | Shot position in the bore |
| Burnup | Fraction of propellant consumed (ψ, as %) |
| Velocity | Shot velocity |
| Avg / Breech / Shot Pressure | The three pressure definitions |
| Temperature | Local gas temperature (Nobel-Abel EOS) |
Download the table as CSV from the button below it for further analysis.
§11Running the full bundled example set
run_examples.py solves every preset under pibs/examples/ — the same corpus the web GUI's demo dropdown draws from — checking computed muzzle velocity and design-constrained peak pressure against each preset's own recorded target:
This script is a regression check: modify the solver core, re-run it — any example that starts failing or drifting materially off-target is worth investigating. To add a new case, drop a new preset JSON in the same schema under pibs/examples/ (e.g. saved from the desktop app's Design → Save) — both this script and the web GUI's demo dropdown pick it up automatically, no code changes needed.
§12Troubleshooting
Errors are raised by the solver with a specific cause — the common ones:
| Error | Cause | Fix |
|---|---|---|
| "Initial burnup fraction is solved to be negative" | Loading density Δ = charge/chamber volume exceeds the propellant's own solid density (~1600 kg/m³) | Reduce charge mass or increase chamber volume so Δ < ρ_p |
| "...greater than unity" | Start pressure too high relative to loading density (roughly, start_pressure > f·Δ) | Lower start pressure, or raise charge mass / lower chamber volume |
| "Squib load condition detected" | Shot stalls in bore — insufficient propulsive force | Web/geometry mismatch (see below), or genuinely too little charge for shot mass and travel |
| "Nobel-Abel EoS is generally accurate enough below 600MPa..." | Pressure exceeded the model's validity ceiling | Web too small / geometry too fast-burning for the charge and chamber |
| "...larger throat area than could be fit into breech face" (recoilless) | Nozzle can't physically fit | Increase chambrage ratio or reduce nozzle expansion ratio |
| "Auxiliary grains must complete combustion in advance..." | Mixed-charge web ratio inconsistent | Adjust Web Aux/Main so auxiliary grain burns out first |
| "Solution requires excessive tube length..." (constrained) | Charge ratio / loading density can't reach the design velocity within the barrel-length search ceiling | Raise Max Barrel Length, increase charge ratio, or lower the velocity target |
| "Propellant load too low to achieve design velocity" (constrained) | Even at 100% burn, this charge can't reach the target velocity | Increase charge-to-shot mass ratio |
| "Design velocity exceeded before peak pressure point..." (constrained) | Inconsistent target/charge combination | Lower the velocity target or raise the pressure target relative to it |
§13Where to go next
- Part I — Theoretical Model — the full physical/numerical model.
pibs/examples/— all 48 bundled reference designs (Autocannons, Guns, Howitzers, Gun-Howitzer, Recoilless).excluded_examples/holds additional presets (including Naval) not wired into the demo dropdown/runner by default.pibs/ballistics/resource/propellants.csv— the 40 bundled propellant compositions with literature sourcing.- Desktop app
Datamenu — load/save designs and propellants, including your own.