diff options
Diffstat (limited to '')
| -rw-r--r-- | src/physics/models.ts | 112 |
1 files changed, 0 insertions, 112 deletions
diff --git a/src/physics/models.ts b/src/physics/models.ts deleted file mode 100644 index 8fb121f..0000000 --- a/src/physics/models.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { COULOMB_CONSTANT, electricField, type Charge, type Point } from './electricField'; - -export const VACUUM_PERMITTIVITY = 8.8541878128e-12; -export const ELEMENTARY_CHARGE = 1.602176634e-19; -const THERMAL_ENERGY_EV = 8.617333262e-5 * 300; - -function positive(...values: number[]) { - if (values.some(value => !Number.isFinite(value) || value <= 0)) { - throw new RangeError('Physical dimensions and material constants must be finite and positive.'); - } -} - -/** Vacuum potential in volts, referenced to infinity. Undefined inside the - * same 0.18 m visualization exclusion used by electricField. */ -export function potential(point: Point, charges: readonly Charge[]): number { - let volts = 0; - for (const charge of charges) { - if (charge.coulombs === 0) continue; - const r = Math.hypot(point.x - charge.x, point.y - charge.y, point.z - charge.z); - if (r < 0.18) return NaN; - volts += COULOMB_CONSTANT * charge.coulombs / r; - } - return volts; -} - -/** Force on a test charge, excluding that charge from the supplied sources. */ -export function forceOn(test: Charge, sources: readonly Charge[]): Point { - const field = electricField(test, sources); - return { x: field.x * test.coulombs, y: field.y * test.coulombs, z: field.z * test.coulombs }; -} - -export function pairEnergy(q1: number, q2: number, separation: number): number { - positive(separation); - return COULOMB_CONSTANT * q1 * q2 / separation; -} - -/** Exact signed flux for an origin-centred spherical Gaussian surface. - * A point charge exactly on the surface makes the integral undefined. */ -export function gaussianFlux(charges: readonly Charge[], radius: number): number { - positive(radius); - let enclosed = 0; - for (const charge of charges) { - if (charge.coulombs === 0) continue; - const r = Math.hypot(charge.x, charge.y, charge.z); - if (Math.abs(r - radius) < 1e-9) return NaN; - if (r < radius) enclosed += charge.coulombs; - } - return enclosed / VACUUM_PERMITTIVITY; -} - -export interface CapacitorParameters { - area: number; - gap: number; - relativePermittivity: number; - voltage: number; - /** If isolated, voltage means the initial vacuum charging voltage. */ - isolated?: boolean; -} -export function capacitor(p: CapacitorParameters) { - positive(p.area, p.gap, p.relativePermittivity); - const vacuumCapacitance = VACUUM_PERMITTIVITY * p.area / p.gap; - const capacitance = vacuumCapacitance * p.relativePermittivity; - const voltage = p.isolated ? p.voltage / p.relativePermittivity : p.voltage; - const charge = capacitance * voltage; - const field = voltage / p.gap; - return { - capacitance, voltage, charge, field, - energy: 0.5 * capacitance * voltage ** 2, - polarization: VACUUM_PERMITTIVITY * (p.relativePermittivity - 1) * field, - }; -} - -export interface ConductorParameters { - voltage: number; - resistivity: number; - length: number; - area: number; - carrierDensity: number; -} -export function conductor(p: ConductorParameters) { - positive(p.resistivity, p.length, p.area, p.carrierDensity); - const resistance = p.resistivity * p.length / p.area; - const current = p.voltage / resistance; - return { - resistance, current, - power: p.voltage * current, - density: current / p.area, - electronDrift: -current / (p.carrierDensity * ELEMENTARY_CHARGE * p.area), - }; -} - -export interface SemiconductorParameters { - intrinsicDensity: number; - /** Fully ionized donors minus acceptors, in m^-3. */ - netDoping: number; - electronMobility: number; - holeMobility: number; -} -/** Non-degenerate thermal equilibrium at 300 K. Solving for the minority - * through mass action avoids catastrophic subtraction at large doping. */ -export function semiconductor(p: SemiconductorParameters) { - positive(p.intrinsicDensity, p.electronMobility, p.holeMobility); - const majority = (Math.abs(p.netDoping) + Math.hypot(p.netDoping, 2 * p.intrinsicDensity)) / 2; - const minority = p.intrinsicDensity ** 2 / majority; - const electrons = p.netDoping >= 0 ? majority : minority; - const holes = p.netDoping >= 0 ? minority : majority; - return { - electrons, holes, - fermiShift: THERMAL_ENERGY_EV * Math.log(electrons / p.intrinsicDensity), - conductivity: ELEMENTARY_CHARGE * (electrons * p.electronMobility + holes * p.holeMobility), - }; -} |