@ferret/physics-rotor
blades, paddles and buckets around an axis turning wind and water into torque, and the blade actuator: a plate in a medium.
Read the guide: how to use it →
Functions
bladeCp function
function bladeCp(r: BladeRotor, rho: number, U: number, lambda: number): numberThe power coefficient of a blade rotor at the tip-speed ratio λ in a wind U: what the lumped mode is fitted to.
packages/physics-rotor/src/loads.ts:108
bladeLoads function
function bladeLoads(r: BladeRotor, rho: number, U: number, omega: number): BladeLoadsBlade-element and momentum theory at one station of the blades: the flow U along the axis and the speed ω give the angle of attack; the lift and drag turn into the torque and the thrust; the induced flow (a, a′) from momentum theory is iterated with the tip loss, so the power can never pass the Betz limit. Positive torque turns the rotor the way ω does (a turbine); a propeller (pitched past the inflow angle) gives negative torque and negative thrust. For the thrust sign U is taken as its magnitude: the caller turns the force to the flow.
packages/physics-rotor/src/loads.ts:68
fitLumped function
function fitLumped(r: BladeRotor, rho = 1.225, U = 8): { cpMax: number; peak: number }Fit the lumped curve (cpCurve: a parabola with its peak at peak, height cpMax) to the element model by sweeping the tip-speed ratio.
packages/physics-rotor/src/loads.ts:114
frameOf function
function frameOf(axis: Vec3, up: Vec3): { a: Vec3; u: Vec3; t: Vec3 }The in-plane frame of a rotor: radial reference u, the direction t = a × u that a positive turn moves towards.
packages/physics-rotor/src/loads.ts:124
plateForce function
function plateForce(W: Vec3, n: Vec3, rho: number, A: number, polar?: Polar): Vec3The force of a flat plate of area A and unit normal n in a flow W relative to it (the fluid's velocity minus the plate's): drag along W, lift across it on the side the plate is hit from. At right angles it is the drag of a plate facing the flow; edge-on it is skin friction only.
packages/physics-rotor/src/loads.ts:37
polarAt function
function polarAt(p: Polar | undefined, alpha: number): { cl: number; cd: number }Lift and drag coefficients at the angle of attack α (rad, any value): attached up to the stall, then falling to zero lift at 90°; the plate is symmetric.
packages/physics-rotor/src/loads.ts:21
rotors function
function rotors(): RotorsCapabilitypackages/physics-rotor/src/index.ts:124
strokePose function
function strokePose(o: OarStroke, time: number): StrokePosepackages/physics-rotor/src/stroke.ts:40
validateRotor function
function validateRotor(d: unknown, path = 'rotor'): string[]packages/physics-rotor/src/index.ts:81
windAvailable function
function windAvailable: (rho: number, radius: number, U: number) => numberPower available in the wind through the disc, W.
packages/physics-rotor/src/loads.ts:105
Interfaces
BladeLoads interface
interface BladeLoadsthrust: number | |
torque: number | |
a: number | |
ap: number | |
phi: number | |
alpha: number | |
power: number |
packages/physics-rotor/src/loads.ts:60
BladeRotor interface
interface BladeRotorcount: number | number of blades, rotor radius, hub radius (default 0.15 R) and the area of one blade |
radius: number | |
hub?: number | |
area: number | |
pitch: number | angle of the chord from the plane of rotation, rad |
station?: number | the station along the blade the loads are taken at, as a share of the radius (0.7) |
polar?: Polar | |
induction?: boolean | switch the induced flow off (a propeller at the bollard, a quick estimate) |
packages/physics-rotor/src/loads.ts:49
BladeSpec interface
interface BladeSpecThe blade kind of actuator: a plate in a medium. area, normal (the body's frame) and a polar; the force comes from the plate's velocity against the local flow. The profile drives the plate's stroke, not the force: stroke: { dir, speed } moves the plate relative to the body at speed × profile (an oar sweeping through the water), so the same stroke gives less against the current.
packages/physics-rotor/src/index.ts:374
OarStroke interface
interface OarStrokeThe stroke of an oar: where the blade is, and how the plate faces, at a point of the cycle. The oar pivots at the oarlock (pivot, the body's frame); the blade is at the end of reach (from the pivot, at the middle of the sweep) turned about axis by an angle that goes arc[0] to arc[1] in the drive (a share drive of the cycle) and back in the recovery. In the recovery the blade is lifted out of the water along the axis by up to lift metres and the plate turns edge-on (feathered), so the same stroke pulls in the water and slips through the air. Immersion is not a number here: the force is read from the medium at the blade's place, so the lift decides it.
pivot: Vec3 | |
reach: Vec3 | |
axis: Vec3 | |
arc: [number, number] | angles of the sweep, rad: the blade is at arc[0] at the catch and at arc[1] at the finish |
period: number | seconds of a whole stroke (drive + recovery) |
drive?: number | share of the cycle that is the drive (default 0.4) |
lift?: number | metres the blade is lifted along the axis at the middle of the recovery (default 0.25); it reaches it within a quarter of the recovery and holds it |
feather?: boolean | turn the plate edge-on in the recovery (default true) |
packages/physics-rotor/src/stroke.ts:10
Polar interface
interface PolarPure load models of the plan and the blade kind of 3.2: no host, no world, so they are tested against the analytic values and reused by the capability and by anything that wants the numbers (a tool, a game's own rotor).
clSlope?: number | slope of the lift in the attached range, per rad (2π for a thin plate) |
clMax?: number | the lift at stall |
cd0?: number | |
cdMax?: number | the drag of a plate facing the flow |
cl?: (alpha: number) => number | code: your own curves, α in [0, π/2]; lift for the positive side (the polar is odd), drag even |
cd?: (alpha: number) => number |
packages/physics-rotor/src/loads.ts:7
RotorDef interface
interface RotorDefname: string | |
node?: string | the body the rotor sits on (reaction and thrust go to it), and/or the drivetrain shaft it turns |
shaft?: string | |
axis: Vec3 | the axis: in the body's frame with a node, in the world without one |
at?: Vec3 | the centre, in the body's frame (with a node) or the world |
up?: Vec3 | the direction radial angle 0 points to (default up) |
radius: number | |
medium?: 'air' | 'water' | |
model?: 'elements' | 'lumped' | |
elements: { kind: RotorElementKind; count: number; /** blade, paddle: area of one element, m² */ area?: number; /** blade: pitch of the chord from the plane of rotation (rad or "5deg"), hub radius, station, polar, induction */ pitch?: number | string; hub?: number; station?: number; polar?: Polar; induction?: boolean; /** paddle: how far in from the rim the paddle reaches (m), drag coefficient */ depth?: number; cd?: number; /** bucket: capacity in kg of water; filled by `fill`, emptied from the angle `empty.from` on */ capacity?: number; fill?: { angle: number; width: number; rate: number }; empty?: { from: number; rate?: number }; } | |
lumped?: { cpMax?: number; peak?: number; ct?: number; kt?: number; kq?: number; diameter?: number } | lumped mode: a turbine { cpMax, peak, ct } (fitted from the elements with fitLumped when missing) or a propeller { kt, kq, diameter } |
spin?: { J?: number; friction?: number; speed?: number | string; theta?: number } | a rotor on a body with no shaft spins by itself: inertia, bearing friction (N·m·s), or a held speed (rad/s or "300rpm") of a driven rotor |
command?: number | 0..1 multiplier of the water flow into the buckets (a sluice) |
packages/physics-rotor/src/index.ts:19
RotorsCapability interface
interface RotorsCapability extends Capabilityreadonly rotors: Map<string, RotorState> | |
set(def: RotorDef): void | |
remove(name: string): void | |
list(): RotorDef[] | |
state(name?: string): RotorState | RotorState[] | |
pitch(name: string, value: number | string): void | |
command(name: string, value: number): void | |
useDrivetrain(train: Drivetrain): void | a drivetrain whose shafts rotors can turn |
addTarget(node: string, target: ForceTarget): void | a body that is not a RigidBody (a vessel) for rotors naming node |
packages/physics-rotor/src/index.ts:64
RotorState interface
interface RotorStatename: string | |
omega: number | |
theta: number | |
torque: number | |
power: number | |
thrust: number | |
force: Vec3 | |
tipSpeedRatio: number | tip speed over the wind along the axis (blades) |
flow: number | the flow along the axis against the rotor, m/s, and the power coefficient (blades) |
cp: number | |
pitch: number | |
command: number | |
fill: number[] | |
error?: string |
packages/physics-rotor/src/index.ts:54
StrokePose interface
interface StrokePoseat: Vec3 | the blade in the body's frame, and the unit normal of the plate there |
normal: Vec3 | |
raised: number | 0 in the drive, up to 1 at the middle of the recovery |
phase: number | the cycle position 0..1 and whether the blade is in the drive |
driving: boolean |
packages/physics-rotor/src/stroke.ts:24
Types
RotorElementKind type
type RotorElementKind = 'blade' | 'paddle' | 'bucket'rotors. N blades, paddles or buckets around an axis, on a body or on a drivetrain shaft, summed into one torque (and a force) each step without a body per element:
blade blade-element and momentum theory in the local flow (windmill sails, wind turbine, propeller, fan), or a lumped curve fitted to it
paddle the drag of the immersed part of flat paddles in the local water (undershot wheel, paddle steamer)
bucket the weight of the water in buckets filled at one angle and emptied at another (overshot wheel)Also here: the blade kind of actuator, a plate in a medium whose stroke is driven by the profile (an oar).
packages/physics-rotor/src/index.ts:18