43 lines
1.4 KiB
JavaScript
43 lines
1.4 KiB
JavaScript
// Numerical methods for transcendental equations
|
||
|
||
/**
|
||
* Bisection method — finds root of f in [lo, hi] within tolerance.
|
||
* Returns null if no sign change is found.
|
||
*/
|
||
export function bisect(f, lo, hi, tol = 1e-10, maxIter = 200) {
|
||
let flo = f(lo)
|
||
let fhi = f(hi)
|
||
if (!isFinite(flo) || !isFinite(fhi)) return null
|
||
if (flo * fhi > 0) return null // no sign change
|
||
for (let i = 0; i < maxIter; i++) {
|
||
const mid = (lo + hi) / 2
|
||
if ((hi - lo) / 2 < tol) return mid
|
||
const fmid = f(mid)
|
||
if (fmid === 0) return mid
|
||
if (flo * fmid < 0) { hi = mid; fhi = fmid }
|
||
else { lo = mid; flo = fmid }
|
||
}
|
||
return (lo + hi) / 2
|
||
}
|
||
|
||
/**
|
||
* Isentropic area-ratio function A/A* as a function of Mach M and gamma.
|
||
* A/A* = (1/M) * [(2/(γ+1)) * (1 + (γ-1)/2 * M²)]^((γ+1)/(2(γ-1)))
|
||
*/
|
||
export function areaRatioFromMach(M, gamma) {
|
||
const exp = (gamma + 1) / (2 * (gamma - 1))
|
||
const base = (2 / (gamma + 1)) * (1 + (gamma - 1) / 2 * M * M)
|
||
return (1 / M) * Math.pow(base, exp)
|
||
}
|
||
|
||
/**
|
||
* Solve Mach number from area ratio and gamma using bisection.
|
||
* supersonic=true searches M > 1, false searches M < 1.
|
||
* Returns null if unsolvable.
|
||
*/
|
||
export function machFromAreaRatio(eps, gamma, supersonic = true) {
|
||
const f = (M) => areaRatioFromMach(M, gamma) - eps
|
||
if (supersonic) return bisect(f, 1.0001, 200, 1e-9)
|
||
else return bisect(f, 0.0001, 0.9999, 1e-9)
|
||
}
|