init
This commit is contained in:
519
src/engine/equations.js
Normal file
519
src/engine/equations.js
Normal file
@@ -0,0 +1,519 @@
|
||||
import { machFromAreaRatio, areaRatioFromMach } from './numerics.js'
|
||||
|
||||
// Each equation:
|
||||
// id – unique key
|
||||
// name – display name
|
||||
// formula – formula string shown to user
|
||||
// variables – all variable ids involved
|
||||
// solvers – map of { variableId: fn(knownValues) => number }
|
||||
// A solver may return NaN/Infinity to signal infeasibility.
|
||||
|
||||
export const EQUATIONS = [
|
||||
|
||||
// ── Thrust ─────────────────────────────────────────────────────────────
|
||||
{
|
||||
id: 'fundamental_thrust',
|
||||
name: 'Fundamental Thrust Equation',
|
||||
formula: 'F = ṁ·Vₑ + (pₑ − pₐ)·Aₑ',
|
||||
category: 'Thrust',
|
||||
variables: ['F', 'mdot', 'Ve', 'pe', 'pa', 'Ae'],
|
||||
solvers: {
|
||||
F: v => v.mdot * v.Ve + (v.pe - v.pa) * v.Ae,
|
||||
mdot: Object.assign(
|
||||
v => (v.F - ('Ae' in v ? (v.pe - v.pa) * v.Ae : 0)) / v.Ve,
|
||||
{
|
||||
requires: known => {
|
||||
const adapted = 'pe' in known && 'pa' in known && known.pe === known.pa
|
||||
return adapted ? ['F', 'Ve', 'pe', 'pa'] : ['F', 'Ve', 'pe', 'pa', 'Ae']
|
||||
},
|
||||
},
|
||||
),
|
||||
Ve: v => (v.F - (v.pe - v.pa) * v.Ae) / v.mdot,
|
||||
pe: v => (v.F - v.mdot * v.Ve) / v.Ae + v.pa,
|
||||
pa: v => v.pe - (v.F - v.mdot * v.Ve) / v.Ae,
|
||||
Ae: v => (v.F - v.mdot * v.Ve) / (v.pe - v.pa),
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'thrust_from_isp',
|
||||
name: 'Thrust from Isp',
|
||||
formula: 'F = ṁ·Isp·g₀',
|
||||
category: 'Thrust',
|
||||
variables: ['F', 'mdot', 'Isp', 'g0'],
|
||||
solvers: {
|
||||
F: v => v.mdot * v.Isp * v.g0,
|
||||
mdot: v => v.F / (v.Isp * v.g0),
|
||||
Isp: v => v.F / (v.mdot * v.g0),
|
||||
g0: v => v.F / (v.mdot * v.Isp),
|
||||
},
|
||||
},
|
||||
|
||||
// ── Effective Exhaust Velocity ─────────────────────────────────────────
|
||||
{
|
||||
id: 'ceff_def',
|
||||
name: 'Effective Exhaust Velocity',
|
||||
formula: 'cₑ = F / ṁ',
|
||||
category: 'Thrust',
|
||||
variables: ['ceff', 'F', 'mdot'],
|
||||
solvers: {
|
||||
ceff: v => v.F / v.mdot,
|
||||
F: v => v.ceff * v.mdot,
|
||||
mdot: v => v.F / v.ceff,
|
||||
},
|
||||
},
|
||||
|
||||
// ── Specific Impulse ───────────────────────────────────────────────────
|
||||
{
|
||||
id: 'isp_from_ve',
|
||||
name: 'Isp from Effective Exhaust Velocity',
|
||||
formula: 'Isp = cₑ / g₀',
|
||||
category: 'Specific Impulse',
|
||||
variables: ['Isp', 'ceff', 'g0'],
|
||||
solvers: {
|
||||
Isp: v => v.ceff / v.g0,
|
||||
ceff: v => v.Isp * v.g0,
|
||||
g0: v => v.ceff / v.Isp,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'isp_from_thrust',
|
||||
name: 'Isp from Thrust & Mass Flow',
|
||||
formula: 'Isp = F / (ṁ·g₀)',
|
||||
category: 'Specific Impulse',
|
||||
variables: ['Isp', 'F', 'mdot', 'g0'],
|
||||
solvers: {
|
||||
Isp: v => v.F / (v.mdot * v.g0),
|
||||
F: v => v.Isp * v.mdot * v.g0,
|
||||
mdot: v => v.F / (v.Isp * v.g0),
|
||||
g0: v => v.F / (v.Isp * v.mdot),
|
||||
},
|
||||
},
|
||||
|
||||
// ── Characteristic Velocity ────────────────────────────────────────────
|
||||
{
|
||||
id: 'cstar_def',
|
||||
name: 'Characteristic Velocity',
|
||||
formula: 'c* = p₀·Aₜ / ṁ',
|
||||
category: 'Nozzle Performance',
|
||||
variables: ['cstar', 'p0', 'At', 'mdot'],
|
||||
solvers: {
|
||||
cstar: v => (v.p0 * v.At) / v.mdot,
|
||||
p0: v => (v.cstar * v.mdot) / v.At,
|
||||
At: v => (v.cstar * v.mdot) / v.p0,
|
||||
mdot: v => (v.p0 * v.At) / v.cstar,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'cstar_from_cf_isp',
|
||||
name: 'c* from Thrust Coefficient & Isp',
|
||||
formula: 'c* = Isp·g₀ / Cꜰ',
|
||||
category: 'Nozzle Performance',
|
||||
variables: ['cstar', 'Isp', 'g0', 'CF'],
|
||||
solvers: {
|
||||
cstar: v => (v.Isp * v.g0) / v.CF,
|
||||
Isp: v => (v.cstar * v.CF) / v.g0,
|
||||
g0: v => (v.cstar * v.CF) / v.Isp,
|
||||
CF: v => (v.Isp * v.g0) / v.cstar,
|
||||
},
|
||||
},
|
||||
|
||||
// ── Thrust Coefficient ─────────────────────────────────────────────────
|
||||
{
|
||||
id: 'thrust_coefficient',
|
||||
name: 'Thrust Coefficient',
|
||||
formula: 'Cꜰ = F / (p₀·Aₜ)',
|
||||
category: 'Nozzle Performance',
|
||||
variables: ['CF', 'F', 'p0', 'At'],
|
||||
solvers: {
|
||||
CF: v => v.F / (v.p0 * v.At),
|
||||
F: v => v.CF * v.p0 * v.At,
|
||||
p0: v => v.F / (v.CF * v.At),
|
||||
At: v => v.F / (v.CF * v.p0),
|
||||
},
|
||||
},
|
||||
|
||||
// ── Tsiolkovsky Rocket Equation ────────────────────────────────────────
|
||||
{
|
||||
id: 'tsiolkovsky_ve',
|
||||
name: 'Tsiolkovsky Rocket Equation (cₑ)',
|
||||
formula: 'Δv = cₑ·ln(m₀/mf)',
|
||||
category: 'Rocket Equation',
|
||||
variables: ['dv', 'ceff', 'm0', 'mf'],
|
||||
solvers: {
|
||||
dv: v => v.ceff * Math.log(v.m0 / v.mf),
|
||||
ceff: v => v.dv / Math.log(v.m0 / v.mf),
|
||||
m0: v => v.mf * Math.exp(v.dv / v.ceff),
|
||||
mf: v => v.m0 / Math.exp(v.dv / v.ceff),
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'tsiolkovsky_isp',
|
||||
name: 'Tsiolkovsky Rocket Equation (Isp)',
|
||||
formula: 'Δv = Isp·g₀·ln(m₀/mf)',
|
||||
category: 'Rocket Equation',
|
||||
variables: ['dv', 'Isp', 'g0', 'm0', 'mf'],
|
||||
solvers: {
|
||||
dv: v => v.Isp * v.g0 * Math.log(v.m0 / v.mf),
|
||||
Isp: v => v.dv / (v.g0 * Math.log(v.m0 / v.mf)),
|
||||
g0: v => v.dv / (v.Isp * Math.log(v.m0 / v.mf)),
|
||||
m0: v => v.mf * Math.exp(v.dv / (v.Isp * v.g0)),
|
||||
mf: v => v.m0 / Math.exp(v.dv / (v.Isp * v.g0)),
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'mass_ratio',
|
||||
name: 'Mass Ratio',
|
||||
formula: 'MR = m₀ / mf',
|
||||
category: 'Rocket Equation',
|
||||
variables: ['MR', 'm0', 'mf'],
|
||||
solvers: {
|
||||
MR: v => v.m0 / v.mf,
|
||||
m0: v => v.MR * v.mf,
|
||||
mf: v => v.m0 / v.MR,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'propellant_mass',
|
||||
name: 'Propellant Mass',
|
||||
formula: 'mₚ = m₀ − mf',
|
||||
category: 'Rocket Equation',
|
||||
variables: ['mp', 'm0', 'mf'],
|
||||
solvers: {
|
||||
mp: v => v.m0 - v.mf,
|
||||
m0: v => v.mp + v.mf,
|
||||
mf: v => v.m0 - v.mp,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'mass_fraction',
|
||||
name: 'Propellant Mass Fraction',
|
||||
formula: 'ζ = mₚ / m₀',
|
||||
category: 'Rocket Equation',
|
||||
variables: ['zeta', 'mp', 'm0'],
|
||||
solvers: {
|
||||
zeta: v => v.mp / v.m0,
|
||||
mp: v => v.zeta * v.m0,
|
||||
m0: v => v.mp / v.zeta,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'burn_time',
|
||||
name: 'Burn Time',
|
||||
formula: 'tᵦ = mₚ / ṁ',
|
||||
category: 'Rocket Equation',
|
||||
variables: ['tb', 'mp', 'mdot'],
|
||||
solvers: {
|
||||
tb: v => v.mp / v.mdot,
|
||||
mp: v => v.tb * v.mdot,
|
||||
mdot: v => v.mp / v.tb,
|
||||
},
|
||||
},
|
||||
|
||||
// ── Isentropic Flow Relations ──────────────────────────────────────────
|
||||
{
|
||||
id: 'isentropic_temp',
|
||||
name: 'Isentropic Temperature Ratio',
|
||||
formula: 'T/T₀ = (1 + (γ−1)/2·M²)⁻¹',
|
||||
category: 'Isentropic Flow',
|
||||
variables: ['T', 'T0', 'M', 'gamma'],
|
||||
solvers: {
|
||||
T: v => v.T0 / (1 + (v.gamma - 1) / 2 * v.M * v.M),
|
||||
T0: v => v.T * (1 + (v.gamma - 1) / 2 * v.M * v.M),
|
||||
M: v => Math.sqrt((v.T0 / v.T - 1) * 2 / (v.gamma - 1)),
|
||||
gamma: v => {
|
||||
// T/T0 = 1/(1 + (γ-1)/2·M²) → T0/T - 1 = (γ-1)/2·M²
|
||||
// γ = 1 + 2(T0/T - 1)/M²
|
||||
return 1 + 2 * (v.T0 / v.T - 1) / (v.M * v.M)
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'isentropic_pressure',
|
||||
name: 'Isentropic Pressure Ratio',
|
||||
formula: 'p/p₀ = (1 + (γ−1)/2·M²)^(−γ/(γ−1))',
|
||||
category: 'Isentropic Flow',
|
||||
variables: ['p_static', 'p0', 'M', 'gamma'],
|
||||
solvers: {
|
||||
p_static: v => {
|
||||
const exp = v.gamma / (v.gamma - 1)
|
||||
return v.p0 / Math.pow(1 + (v.gamma - 1) / 2 * v.M * v.M, exp)
|
||||
},
|
||||
p0: v => {
|
||||
const exp = v.gamma / (v.gamma - 1)
|
||||
return v.p_static * Math.pow(1 + (v.gamma - 1) / 2 * v.M * v.M, exp)
|
||||
},
|
||||
M: v => {
|
||||
// p0/p = (1 + (γ-1)/2·M²)^(γ/(γ-1))
|
||||
// (p0/p)^((γ-1)/γ) = 1 + (γ-1)/2·M²
|
||||
const ratio = Math.pow(v.p0 / v.p_static, (v.gamma - 1) / v.gamma)
|
||||
return Math.sqrt((ratio - 1) * 2 / (v.gamma - 1))
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'isentropic_density',
|
||||
name: 'Isentropic Density Ratio',
|
||||
formula: 'ρ/ρ₀ = (1 + (γ−1)/2·M²)^(−1/(γ−1))',
|
||||
category: 'Isentropic Flow',
|
||||
variables: ['rho', 'rho0', 'M', 'gamma'],
|
||||
solvers: {
|
||||
rho: v => {
|
||||
const exp = 1 / (v.gamma - 1)
|
||||
return v.rho0 / Math.pow(1 + (v.gamma - 1) / 2 * v.M * v.M, exp)
|
||||
},
|
||||
rho0: v => {
|
||||
const exp = 1 / (v.gamma - 1)
|
||||
return v.rho * Math.pow(1 + (v.gamma - 1) / 2 * v.M * v.M, exp)
|
||||
},
|
||||
M: v => {
|
||||
const ratio = Math.pow(v.rho0 / v.rho, v.gamma - 1)
|
||||
return Math.sqrt((ratio - 1) * 2 / (v.gamma - 1))
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'speed_of_sound',
|
||||
name: 'Speed of Sound',
|
||||
formula: 'a = √(γ·R·T)',
|
||||
category: 'Isentropic Flow',
|
||||
variables: ['a_sound', 'gamma', 'R', 'T'],
|
||||
solvers: {
|
||||
a_sound: v => Math.sqrt(v.gamma * v.R * v.T),
|
||||
T: v => (v.a_sound * v.a_sound) / (v.gamma * v.R),
|
||||
R: v => (v.a_sound * v.a_sound) / (v.gamma * v.T),
|
||||
gamma: v => (v.a_sound * v.a_sound) / (v.R * v.T),
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'flow_velocity',
|
||||
name: 'Flow Velocity',
|
||||
formula: 'v = M·a',
|
||||
category: 'Isentropic Flow',
|
||||
variables: ['v_flow', 'M', 'a_sound'],
|
||||
solvers: {
|
||||
v_flow: v => v.M * v.a_sound,
|
||||
M: v => v.v_flow / v.a_sound,
|
||||
a_sound: v => v.v_flow / v.M,
|
||||
},
|
||||
},
|
||||
|
||||
// ── Nozzle Geometry ────────────────────────────────────────────────────
|
||||
{
|
||||
id: 'expansion_ratio',
|
||||
name: 'Nozzle Expansion Ratio',
|
||||
formula: 'ε = Aₑ / Aₜ',
|
||||
category: 'Nozzle Geometry',
|
||||
variables: ['eps', 'Ae', 'At'],
|
||||
solvers: {
|
||||
eps: v => v.Ae / v.At,
|
||||
Ae: v => v.eps * v.At,
|
||||
At: v => v.Ae / v.eps,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'area_ratio_mach',
|
||||
name: 'Isentropic Area Ratio (supersonic)',
|
||||
formula: 'ε = (1/Mₑ)·[(2/(γ+1))·(1+(γ−1)/2·Mₑ²)]^((γ+1)/(2(γ−1)))',
|
||||
category: 'Nozzle Geometry',
|
||||
variables: ['eps', 'Me', 'gamma'],
|
||||
solvers: {
|
||||
eps: v => areaRatioFromMach(v.Me, v.gamma),
|
||||
Me: v => machFromAreaRatio(v.eps, v.gamma, true),
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'choked_mass_flow',
|
||||
name: 'Choked Throat Mass Flow',
|
||||
formula: 'ṁ = Aₜ·p₀·√(γ/(R·T₀))·(2/(γ+1))^((γ+1)/(2(γ−1)))',
|
||||
category: 'Nozzle Geometry',
|
||||
variables: ['mdot', 'At', 'p0', 'gamma', 'R', 'T0'],
|
||||
solvers: {
|
||||
mdot: v => {
|
||||
const exp = (v.gamma + 1) / (2 * (v.gamma - 1))
|
||||
return v.At * v.p0 * Math.sqrt(v.gamma / (v.R * v.T0)) * Math.pow(2 / (v.gamma + 1), exp)
|
||||
},
|
||||
At: v => {
|
||||
const exp = (v.gamma + 1) / (2 * (v.gamma - 1))
|
||||
const coeff = v.p0 * Math.sqrt(v.gamma / (v.R * v.T0)) * Math.pow(2 / (v.gamma + 1), exp)
|
||||
return v.mdot / coeff
|
||||
},
|
||||
p0: v => {
|
||||
const exp = (v.gamma + 1) / (2 * (v.gamma - 1))
|
||||
const coeff = v.At * Math.sqrt(v.gamma / (v.R * v.T0)) * Math.pow(2 / (v.gamma + 1), exp)
|
||||
return v.mdot / coeff
|
||||
},
|
||||
T0: v => {
|
||||
const exp = (v.gamma + 1) / (2 * (v.gamma - 1))
|
||||
const coeff = v.At * v.p0 * Math.pow(2 / (v.gamma + 1), exp)
|
||||
// mdot = coeff * sqrt(gamma/(R*T0))
|
||||
// mdot/coeff = sqrt(gamma/(R*T0))
|
||||
// (mdot/coeff)^2 = gamma/(R*T0)
|
||||
// T0 = gamma/(R * (mdot/coeff)^2)
|
||||
const ratio = v.mdot / coeff
|
||||
return v.gamma / (v.R * ratio * ratio)
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ── Exit Conditions ────────────────────────────────────────────────────
|
||||
// Order matters for the greedy solver: exit_pressure must come before
|
||||
// exit_temperature so that Mₑ is in `known` when exit_temperature runs.
|
||||
// If exit_pressure appeared after exit_temperature, the solver would
|
||||
// reach exit_velocity first (with Mₑ freshly set) and use Vₑ = Isp·g₀
|
||||
// to back-calculate an unphysical Tₑ > T₀.
|
||||
{
|
||||
id: 'exit_pressure',
|
||||
name: 'Nozzle Exit Pressure',
|
||||
formula: 'pₑ = p₀·(1 + (γ−1)/2·Mₑ²)^(−γ/(γ−1))',
|
||||
category: 'Nozzle Geometry',
|
||||
variables: ['pe', 'p0', 'Me', 'gamma'],
|
||||
solvers: {
|
||||
pe: v => {
|
||||
const exp = v.gamma / (v.gamma - 1)
|
||||
return v.p0 / Math.pow(1 + (v.gamma - 1) / 2 * v.Me * v.Me, exp)
|
||||
},
|
||||
p0: v => {
|
||||
const exp = v.gamma / (v.gamma - 1)
|
||||
return v.pe * Math.pow(1 + (v.gamma - 1) / 2 * v.Me * v.Me, exp)
|
||||
},
|
||||
Me: v => {
|
||||
const ratio = Math.pow(v.p0 / v.pe, (v.gamma - 1) / v.gamma)
|
||||
return Math.sqrt((ratio - 1) * 2 / (v.gamma - 1))
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'exit_temperature',
|
||||
name: 'Nozzle Exit Temperature',
|
||||
formula: 'Tₑ = T₀ / (1 + (γ−1)/2·Mₑ²)',
|
||||
category: 'Nozzle Geometry',
|
||||
variables: ['Te', 'T0', 'Me', 'gamma'],
|
||||
solvers: {
|
||||
Te: v => v.T0 / (1 + (v.gamma - 1) / 2 * v.Me * v.Me),
|
||||
T0: v => v.Te * (1 + (v.gamma - 1) / 2 * v.Me * v.Me),
|
||||
Me: v => Math.sqrt((v.T0 / v.Te - 1) * 2 / (v.gamma - 1)),
|
||||
gamma: v => 1 + 2 * (v.T0 / v.Te - 1) / (v.Me * v.Me),
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'exit_velocity',
|
||||
name: 'Nozzle Exit Velocity',
|
||||
formula: 'Vₑ = Mₑ·√(γ·R·Tₑ)',
|
||||
category: 'Nozzle Geometry',
|
||||
variables: ['Ve', 'Me', 'gamma', 'R', 'Te'],
|
||||
solvers: {
|
||||
Ve: v => v.Me * Math.sqrt(v.gamma * v.R * v.Te),
|
||||
Me: v => v.Ve / Math.sqrt(v.gamma * v.R * v.Te),
|
||||
Te: v => (v.Ve / v.Me) ** 2 / (v.gamma * v.R),
|
||||
R: v => (v.Ve / v.Me) ** 2 / (v.gamma * v.Te),
|
||||
gamma: v => (v.Ve / v.Me) ** 2 / (v.R * v.Te),
|
||||
},
|
||||
},
|
||||
|
||||
// ── Performance ────────────────────────────────────────────────────────
|
||||
{
|
||||
id: 'twr',
|
||||
name: 'Thrust-to-Weight Ratio',
|
||||
formula: 'TWR = F / (mᵥ·g₀)',
|
||||
category: 'Performance',
|
||||
variables: ['TWR', 'F', 'm_vehicle', 'g0'],
|
||||
solvers: {
|
||||
TWR: v => v.F / (v.m_vehicle * v.g0),
|
||||
F: v => v.TWR * v.m_vehicle * v.g0,
|
||||
m_vehicle: v => v.F / (v.TWR * v.g0),
|
||||
g0: v => v.F / (v.TWR * v.m_vehicle),
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'total_impulse',
|
||||
name: 'Total Impulse',
|
||||
formula: 'J = F·tᵦ',
|
||||
category: 'Performance',
|
||||
variables: ['J', 'F', 'tb'],
|
||||
solvers: {
|
||||
J: v => v.F * v.tb,
|
||||
F: v => v.J / v.tb,
|
||||
tb: v => v.J / v.F,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'isp_from_impulse',
|
||||
name: 'Isp from Total Impulse',
|
||||
formula: 'Isp = J / (mₚ·g₀)',
|
||||
category: 'Performance',
|
||||
variables: ['Isp', 'J', 'mp', 'g0'],
|
||||
solvers: {
|
||||
Isp: v => v.J / (v.mp * v.g0),
|
||||
J: v => v.Isp * v.mp * v.g0,
|
||||
mp: v => v.J / (v.Isp * v.g0),
|
||||
g0: v => v.J / (v.Isp * v.mp),
|
||||
},
|
||||
},
|
||||
|
||||
// ── Propellant ─────────────────────────────────────────────────────────
|
||||
{
|
||||
id: 'of_ratio',
|
||||
name: 'Oxidiser/Fuel Ratio',
|
||||
formula: 'O/F = ṁₒₓ / ṁf',
|
||||
category: 'Propellant',
|
||||
variables: ['OF', 'mdot_ox', 'mdot_f'],
|
||||
solvers: {
|
||||
OF: v => v.mdot_ox / v.mdot_f,
|
||||
mdot_ox: v => v.OF * v.mdot_f,
|
||||
mdot_f: v => v.mdot_ox / v.OF,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'total_mass_flow',
|
||||
name: 'Total Mass Flow',
|
||||
formula: 'ṁ = ṁₒₓ + ṁf',
|
||||
category: 'Propellant',
|
||||
variables: ['mdot', 'mdot_ox', 'mdot_f'],
|
||||
solvers: {
|
||||
mdot: v => v.mdot_ox + v.mdot_f,
|
||||
mdot_ox: v => v.mdot - v.mdot_f,
|
||||
mdot_f: v => v.mdot - v.mdot_ox,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
id: 'of_mass_split',
|
||||
name: 'Mass Flow Split from O/F',
|
||||
formula: 'ṁ_f = ṁ/(1+OF), ṁ_ox = ṁ·OF/(1+OF)',
|
||||
category: 'Propellant',
|
||||
variables: ['mdot', 'OF', 'mdot_f', 'mdot_ox'],
|
||||
solvers: {
|
||||
mdot_f: Object.assign(v => v.mdot / (1 + v.OF), { requires: () => ['mdot', 'OF'] }),
|
||||
mdot_ox: Object.assign(v => v.mdot * v.OF / (1 + v.OF), { requires: () => ['mdot', 'OF'] }),
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
// Equation presets: named groups that seed the workspace with a useful set of variables
|
||||
export const EQUATION_PRESETS = [
|
||||
{ id: 'fundamental_thrust', label: 'Fundamental Thrust', equationIds: ['fundamental_thrust'] },
|
||||
{ id: 'rocket_equation', label: 'Rocket Equation', equationIds: ['tsiolkovsky_isp', 'mass_ratio', 'propellant_mass', 'burn_time'] },
|
||||
{ id: 'nozzle_full', label: 'Full Nozzle', equationIds: ['exit_pressure', 'exit_temperature', 'exit_velocity', 'area_ratio_mach', 'choked_mass_flow', 'thrust_coefficient', 'cstar_def'] },
|
||||
{ id: 'isentropic', label: 'Isentropic Flow', equationIds: ['isentropic_temp', 'isentropic_pressure', 'speed_of_sound', 'flow_velocity'] },
|
||||
{ id: 'performance', label: 'Performance', equationIds: ['twr', 'total_impulse', 'isp_from_impulse', 'isp_from_thrust'] },
|
||||
{ id: 'propellant', label: 'Propellant Mix', equationIds: ['of_ratio', 'total_mass_flow', 'burn_time'] },
|
||||
]
|
||||
Reference in New Issue
Block a user