UNPKG

davinci-newton

Version:

Physics Modeling and Engine using Geometric Algebra

1,649 lines (1,614 loc) 184 kB
import { Unit, Geometric1, Spacetime1, Geometric2, Spacetime2, Geometric3 } from '@geometryzen/multivectors'; export { Dimensions, Geometric1, Geometric2, Geometric3, Matrix1, Matrix3, QQ, Spacetime1, Spacetime2, Unit, setDimensionsChecking } from '@geometryzen/multivectors'; /** * @hidden */ declare class Newton { /** * The GitHub URL of the repository. */ GITHUB: string; /** * The last modification date in YYYY-MM-DD format. */ LAST_MODIFIED: string; /** * The namespace used for traditional JavaScript module loading. */ NAMESPACE: string; /** * The semantic version number of this library, i.e., (major.minor.patch) format. */ VERSION: string; /** * */ constructor(); } /** * @hidden */ declare const config: Newton; /** * @hidden * 0 = LOCAL, 1 = WORLD. */ type CoordType = 0 | 1; /** * The coordinate frame that is fixed in relation to the rigid body. * @hidden */ declare const LOCAL = 0; /** * The coordinate frame used as the basis for position and attitude of all bodies. * @hidden */ declare const WORLD = 1; /** * @hidden */ interface SimObject { /** * */ expireTime: number; } /** * @hidden */ declare class AbstractSimObject implements SimObject { /** * */ private expireTime_; /** * */ constructor(); /** * */ get expireTime(): number; set expireTime(expireTime: number); } /** * @hidden */ interface MatrixLike { readonly dimensions: number; /** * The unit of measure (shared by each element of the matrix). */ uom?: Unit; getElement(row: number, column: number): number; } /** * @hidden */ declare abstract class Torque<T> extends AbstractSimObject { private readonly body; readonly bivector: T; /** * */ bivectorCoordType: CoordType; private readonly $temp1; constructor(body: ForceBody<T>); /** * */ getBody(): ForceBody<T>; /** * * @param torque */ computeTorque(torque: T): void; } /** * A handle-body pattern abstraction of the multivector used by the Physics Engine. * The multivector encodes the metric in the multiplication of its basis vectors. */ interface Metric<T> { /** * Returns the time direction for relativistic metrics. * The returned vector is locked. * Non-relativistic metrics should return undefined. */ readonly e0: T; /** * Returns the scalar component of the multivector. * @param mv The multivector for which the scalar component is required. */ a(mv: T): number; add(lhs: T, rhs: T): T; addScalar(lhs: T, a: number, uom?: Unit): T; addVector(lhs: T, rhs: T): T; /** * TODO: Describe semantics of how this is expected to change the multivector argument. * @param mv * @param matrix */ applyMatrix(mv: T, matrix: MatrixLike): T; clone(source: T): T; /** * Modifies the target to have the same property values as the source. * @param source * @param target * @returns the target. */ copy(source: T, target: T): T; copyBivector(source: T, target: T): T; copyMatrix(m: MatrixLike): MatrixLike; copyScalar(a: number, uom: Unit, target: T): T; copyVector(source: T, target: T): T; /** * Create a non-generic instance derived from Force; Force is to be considered an abstract base type. * This will make it easier for clients; after instanceof Force2 or Force3, the properties of the * force application (F, and x) will have non-generic types. * * @param body The body that the force will be applied to. */ createForce(body: ForceBody<T>): Force<T>; /** * * @param body The body that the torque will be applied to. */ createTorque(body: ForceBody<T>): Torque<T>; direction(mv: T): T; divByScalar(lhs: T, a: number, uom?: Unit): T; ext(lhs: T, rhs: T): T; identityMatrix(): MatrixLike; /** * * @param matrix The matrix to be inverted. * @returns A new matrix which is the inverse of the specified matrix. */ invertMatrix(matrix: MatrixLike): MatrixLike; isBivector(mv: T): boolean; isOne(mv: T): boolean; isScalar(mv: T): boolean; isSpinor(mv: T): boolean; isVector(mv: T): boolean; isZero(mv: T): boolean; lco(lhs: T, rhs: T): T; /** * Used to change the mutability of the multivector from mutable to immutable. * An immutable multivector is also described as locked. The number returned is * a token that may be used to unlock the multivector, making it mutable again. * @param mv The multivector to be locked. * @returns A token that may be used to unlock the multivector. */ lock(mv: T): number; norm(mv: T): T; mul(lhs: T, rhs: T): T; mulByNumber(lhs: T, alpha: number): T; mulByScalar(lhs: T, a: number, uom?: Unit): T; mulByVector(lhs: T, rhs: T): T; neg(mv: T): T; /** * squared norm: |A| * |A| = A * rev(A) */ squaredNorm(A: T): T; rco(lhs: T, rhs: T): T; rev(mv: T): T; rotate(mv: T, spinor: T): T; /** * Creates a grade 0 (scalar) multivector with value `a * uom`. * The scalar returned is in the unlocked (mutable) state. * @param a The scaling factor for the unit of measure. * @param uom The optional unit of measure. Equivalent to 1 if omitted. */ scalar(a: number, uom?: Unit): T; scp(lhs: T, rhs: T): T; setUom(mv: T, uom: Unit): void; sub(lhs: T, rhs: T): T; subScalar(lhs: T, a: number, uom?: Unit): T; subVector(lhs: T, rhs: T): T; unlock(mv: T, token: number): void; uom(mv: T): Unit; write(source: T, target: T): void; /** * TODO: This looks a lot like copyVector. Is there any difference? * @param source * @param target */ writeVector(source: T, target: T): void; writeBivector(source: T, target: T): void; } /** * */ interface ForceBody<T> extends SimObject { /** * The metric must be known in order to compute the energies and angular velocity. */ metric: Metric<T>; /** * A placeholder for applications to define a unique identifier. */ uuid: string; /** * mass (scalar). In the case of relativistic systems, this is the rest mass. */ M: T; /** * position (vector) */ X: T; /** * attitude (spinor) */ R: T; /** * momentum (vector) */ P: T; /** * angular momentum (bivector) */ L: T; /** * angular velocity (bivector) */ Ω: T; /** * offset into state array */ varsIndex: number; /** * computes the rotational kinetic energy. */ rotationalEnergy(): T; /** * computes the translational kinetic energy. */ translationalEnergy(): T; /** * updates the angular velocity from the angular momentum. */ updateAngularVelocity(): void; } /** * @hidden */ declare class Force<T> extends AbstractSimObject { private readonly body; /** * The point of application of the force. */ readonly location: T; /** * */ private $locationCoordType; /** * The force vector, may be in local or world coordinates. */ readonly vector: T; /** * */ private $vectorCoordType; private readonly $temp1; private readonly $temp2; /** * */ constructor(body: ForceBody<T>); /** * */ get locationCoordType(): CoordType; set locationCoordType(locationCoordType: CoordType); /** * */ get vectorCoordType(): CoordType; set vectorCoordType(vectorCoordType: CoordType); /** * */ getBody(): ForceBody<T>; /** * Computes the point of application of the force in world coordinates. * * @param position (output) */ computePosition(position: T): void; /** * Computes the force being applied (vector) in WORLD coordinates. * * @param force (output) */ computeForce(force: T): void; /** * Computes the torque, i.e. moment of the force about the center of mass (bivector). * Torque = (x - X) ^ F, so the torque is being computed with center of mass as origin. * Torque = r ^ F because r = x - X * * @param torque (output) */ computeTorque(torque: T): void; get F(): T; get x(): T; } /** * A force law computes the forces on one or more bodies in the system. */ interface ForceLaw<T> extends SimObject { /** * The forces that were computed the last time that the `updateForces()` method was called. */ readonly forces: Force<T>[]; /** * Updates the forces based upon the current state of the bodies. */ updateForces(): Force<T>[]; /** * TODO: This does not do anything in the existing implementations of ForceLaw. */ disconnect(): void; /** * Computes the potential energy associated with the interaction of the bodies. */ potentialEnergy(): T; } /** * */ declare class ConstantForceLaw<T> extends AbstractSimObject implements ForceLaw<T> { private body; /** * The attachment point to the body in body coordinates. */ private readonly $force; private readonly $forces; private readonly $potentialEnergy; private $potentialEnergyLock; /** * * @param body the body that the force acts upon. * @param vector the force vector. * @param vectorCoordType 0 => LOCAL, 1 => WORLD. */ constructor(body: ForceBody<T>, vector: T, vectorCoordType?: CoordType); get forces(): Force<T>[]; get location(): T; set location(location: T); get vector(): T; set vector(vector: T); /** * */ updateForces(): Force<T>[]; /** * */ disconnect(): void; /** * */ potentialEnergy(): T; } /** * */ interface TorqueLaw<T> extends SimObject { /** * */ readonly torques: Torque<T>[]; /** * */ updateTorques(): Torque<T>[]; /** * */ disconnect(): void; /** * */ potentialEnergy(): T; } /** * */ declare class ConstantTorqueLaw<T> extends AbstractSimObject implements TorqueLaw<T> { private $body; private readonly $torque; private readonly $torques; constructor($body: ForceBody<T>, value: T, valueCoordType: CoordType); get torques(): Torque<T>[]; updateTorques(): Torque<T>[]; disconnect(): void; potentialEnergy(): T; } /** * @hidden */ interface Charged<T> extends ForceBody<T> { Q: T; } /** * The Electric Force (Coulomb's Law) */ declare class CoulombLaw<T> extends AbstractSimObject implements ForceLaw<T> { private readonly body1; private readonly body2; /** * The constant of proportionality. */ private readonly $k; private readonly F1; private readonly F2; private readonly $forces; /** * Scratch variable for computing potential energy. */ private readonly potentialEnergy_; private potentialEnergyLock_; private readonly metric; /** * */ constructor(body1: Charged<T>, body2: Charged<T>, k?: T); /** * The proportionality constant, Coulomb's constant. * The approximate value in SI units is 9 x 10<sup>9</sup> N·m<sup>2</sup>/C<sup>2</sup>. * The default value is one (1). */ get k(): T; set k(k: T); get forces(): Force<T>[]; /** * Computes the forces due to the Coulomb interaction. * F = k * q1 * q2 * direction(r2 - r1) / quadrance(r2 - r1) */ updateForces(): Force<T>[]; /** * */ disconnect(): void; /** * Computes the potential energy of the gravitational interaction. * U = k q1 q2 / r, where * r is the center to center separation of m1 and m2. */ potentialEnergy(): T; } /** * */ interface GeometricConstraint<T> { /** * */ getBody(): ForceBody<T>; /** * Computes the radius of the curve. * @param x (input) The location at which the radius is required. * @param radius (output) The radius (scalar). */ computeRadius(x: T, radius: T): void; /** * Computes the plane containing the rotation. * The orientation is ambiguous. * However tangent * rotation should give the direction towards the center of curvature. * @param x (input) The position (vector) at which the rotation is required. * @param plane (output) The rotation (bivector). */ computeRotation(x: T, plane: T): void; /** * Computes the tangent to the wire. * The orientation is ambiguous. * However tangent * rotation should give the direction towards the center of curvature. * @param x (input) The position (vector) at which the tangent is required. * @param tangent (output) The tangent (vector). */ computeTangent(x: T, tangent: T): void; /** * * @param N */ setForce(N: T): void; } /** * @hidden */ interface Parameter extends SubjectEvent { /** * Sets whether the value is being automatically computed. * @param computed whether the value is being automatically computed. */ setComputed(computed: boolean): void; } /** * @hidden */ declare class ParameterBoolean implements Parameter { private subject_; private name_; constructor(subject: Subject, name: string, getter: () => boolean, setter: (value: boolean) => unknown, choices?: string[], values?: boolean[]); get name(): string; getSubject(): Subject; nameEquals(name: string): boolean; setComputed(value: boolean): void; } /** * @hidden */ declare class ParameterNumber implements Parameter { /** * the Subject which provides notification of changes in this Parameter */ private subject_; private name_; private getter_; /** * Fixed number of fractional decimal places to show, or -1 if variable. */ private upperLimit_; constructor(subject: Subject, name: string, getter: () => number, setter: (value: number) => unknown, choices?: string[], values?: number[]); get name(): string; getSubject(): Subject; getValue(): number; nameEquals(name: string): boolean; setComputed(value: boolean): void; /** * Sets the lower limit; the Parameter value is not allowed to be less than this, * {@link #setValue} will throw an Error in that case. * @param lowerLimit the lower limit of the Parameter value * @return this Parameter for chaining setters * @throws {Error} if the value is currently less than the lower limit, or the lower limit is not a number */ setLowerLimit(lowerLimit: number): this; /** * Sets suggested number of significant digits to show. This affects the number of * decimal places that are displayed. Examples: if significant digits is 3, then we would * show numbers as: 12345, 1234, 123, 12.3, 1.23, 0.123, 0.0123, 0.00123. * @param signifDigits suggested number of significant digits to show * @return this Parameter for chaining setters */ setSignifDigits(signifDigits: number): this; } /** * @hidden */ declare class ParameterString implements Parameter { private subject_; private name_; private getter_; /** * suggested length of string for making a control */ /** * maximum length of string */ constructor(subject: Subject, name: string, getter: () => string, setter: (value: string) => unknown, choices?: string[], values?: string[]); get name(): string; getSubject(): Subject; getValue(): string; nameEquals(name: string): boolean; setComputed(value: boolean): void; } /** * @hidden */ interface Subject { /** * Adds the given Observer to the Subject's list of Observers, so that the * Observer will be notified of changes in this Subject. Does nothing if the Observer * is already on the list. An Observer may call `Subject.addObserver` during its * `observe` method. * @param observer the Observer to add to list of Observers */ addObserver(observer: Observer): void; /** * Notifies all Observers that the Subject has changed by calling `observe` on each Observer. * An Observer may call `Subject.addObserver` or `Subject.removeObserver` during its `observe` method. * @param event a SubjectEvent with information relating to the change. */ broadcast(event: SubjectEvent): void; /** * Notifies all Observers that the Parameter with the given `name` has changed by * calling {@link myphysicslab.lab.util.Observer#observe} on each Observer. * @param name the universal or English name of the Parameter that has changed * @throws if there is no Parameter with the given name */ broadcastParameter(name: string): void; /** * Returns a copy of the list of Observers of this Subject. * @return a copy of the list of Observers of this Subject. */ getObservers(): Observer[]; /** * Returns the Parameter with the given name. * @param name the language-independent or English name of the Parameter * @return the Parameter with the given name * @throws {Error} if there is no Parameter with the given name */ getParameter(name: string): Parameter; /** * Returns a copy of the list of this Subject's available Parameters. * @return a copy of the list of available Parameters for this Subject */ getParameters(): Parameter[]; /** * Returns the ParameterBoolean with the given name. * @param name the universal or English name of the ParameterBoolean * @return the ParameterBoolean with the given name * @throws if there is no ParameterBoolean with the given name */ getParameterBoolean(name: string): ParameterBoolean; /** * Returns the ParameterNumber with the given name. * @param name the universal or English name of the ParameterNumber * @return the ParameterNumber with the given name * @throws if there is no ParameterNumber with the given name */ getParameterNumber(name: string): ParameterNumber; /** * Returns the ParameterString with the given name. * @param name the universal or English name of the ParameterString * @return the ParameterString with the given name * @throws if there is no ParameterString with the given name */ getParameterString(name: string): ParameterString; /** * Removes the Observer from the Subject's list of Observers. An Observer may * call `Subject.removeObserver` during its `observe` method. * @param observer the Observer to detach from list of Observers */ removeObserver(observer: Observer): void; } /** * @hidden */ interface SubjectEvent { /** * */ readonly name: string; /** * Returns the Subject to which this SubjectEvent refers. */ getSubject(): Subject; /** * */ nameEquals(name: string): boolean; } /** * @hidden */ interface Observer { observe(event: SubjectEvent): void; } /** * @hidden */ interface GraphVarsList { /** * Adds the given Observer to the Subject's list of Observers, so that the * Observer will be notified of changes in this Subject. Does nothing if the Observer * is already on the list. An Observer may call `Subject.addObserver` during its * `observe` method. * @param observer the Observer to add to list of Observers */ addObserver(observer: Observer): void; /** * */ getName(index: number): string; /** * */ getValue(index: number): number; /** * */ getSequence(index: number): number; /** * */ numVariables(): number; /** * Removes the Observer from the Subject's list of Observers. An Observer may * call `Subject.removeObserver` during its `observe` method. * @param observer the Observer to detach from list of Observers */ removeObserver(observer: Observer): void; /** * */ timeIndex(): number; } /** * Represents a variable with a numeric value; usually stored in a VarsList. * @hidden */ interface Variable extends Parameter { /** * Returns whether the Variable is broadcast when it changes discontinuously. * @return whether the Variable is broadcast when it changes discontinuously */ getBroadcast(): boolean; /** * Returns the sequence number of this Variable. The sequence number is incremented * whenever a discontinuity occurs in the value of the variable. For example, when the * variables are set back to initial conditions that is a discontinuous change. Then a * graph knows to not draw a connecting line between the points with the discontinuity. * * Another example of a discontinuity: if the value of an angle is kept within `0` to * `2*Pi` (by just adding or subtracting `2*pi` to keep it in that range), when the angle * crosses that boundary the sequence number should be incremented to indicate a * discontinuity occurred. * @return {number} the sequence number of this Variable. */ getSequence(): number; /** * Returns the value of this variable. */ getValue(): number; /** * Returns the unit of measure of this variable. */ getUnit(): Unit; /** * Increments the sequence number of this Variable, which indicates that a * discontinuity has occurred in the value of this variable. * This information is used in a graph to prevent drawing a line between points that have a discontinuity. */ incrSequence(): void; /** * Sets whether the Variable is broadcast when it changes discontinuously * @param {boolean} value whether the Variable is broadcast when it changes discontinuously */ setBroadcast(broadcast: boolean): void; /** * Sets the value of this Variable and increases the sequence number. */ setValueJump(value: number): void; /** * Sets the value of this Variable without changing the sequence number which means * it is a 'smooth' continuous change to the variable. */ setValueContinuous(value: number): void; /** * Sets the unit of measure of this variable. */ setUnit(unit: Unit): void; } /** * @hidden */ declare class AbstractSubject implements Subject { /** * */ private doBroadcast_; /** * */ private observers_; /** * */ private paramList_; /** * @hidden * @param observer */ addObserver(observer: Observer): void; /** * @hidden * @param observer */ removeObserver(observer: Observer): void; /** * Adds the Parameter to the list of this Subject's available Parameters. * @param parameter the Parameter to add * @hidden */ addParameter(parameter: Parameter): void; /** * Returns the Parameter with the given name, or null if not found * @param name name of parameter to search for * @return the Parameter with the given name, or null if not found */ private getParam; /** * * @param name * @returns * @hidden */ getParameter(name: string): Parameter; /** * * @param name * @returns * @hidden */ getParameterBoolean(name: string): ParameterBoolean; /** * * @param name * @returns * @hidden */ getParameterNumber(name: string): ParameterNumber; /** * * @param name * @returns * @hidden */ getParameterString(name: string): ParameterString; /** * * @returns * @hidden */ getParameters(): Parameter[]; /** * * @param event * @hidden */ broadcast(event: SubjectEvent): void; /** * * @param name * @hidden */ broadcastParameter(name: string): void; /** * Returns whether this Subject is broadcasting events. * @return {boolean} whether this Subject is broadcasting events * @hidden */ protected getBroadcast(): boolean; /** * @hidden */ getObservers(): Observer[]; } declare class VarsList extends AbstractSubject implements GraphVarsList { /** * This name cannot be used as a variable name. */ private static readonly DELETED; /** * This name is the reserved name for the time variable. */ static readonly TIME = "TIME"; /** * */ private static readonly VARS_MODIFIED; /** * The zero-based index of the time variable. */ private $timeIdx; /** * The variables that provide the data for this wrapper. */ private $variables; /** * A lazy cache of variable values to minimize creation of temporary objects. * This is only synchronized when the state is requested. */ private readonly $values; private readonly $units; /** * Whether to save simulation state history. */ private history_; /** * Recent history of the simulation state for debugging. * An array of copies of the vars array. */ private histArray_; /** * Initializes the list of variables. The names argument must contain the reserved, case-insensitive, 'time' variable. * @param names array of language-independent variable names; * these will be underscorized so the English names can be passed in here. */ constructor(names: string[]); /** * Returns index to put a contiguous group of variables. Expands the set of variables * if necessary. * @param quantity number of contiguous variables to allocate * @return index of first variable */ private findOpenSlot_; /** * Add a contiguous block of variables. * @param names language-independent names of variables; these will be * underscorized so the English name can be passed in here. * @return index index of first Variable that was added * @throws if any of the variable names is 'DELETED', or array of names is empty */ addVariables(names: string[]): number; /** * Deletes a contiguous block of variables. * Delete several variables, but leaves those places in the array as empty spots that * can be allocated in future with `addVariables`. Until an empty spot is * reallocated, the name of the variable at that spot has the reserved name 'DELETED' and * should not be used. * @param index index of first variable to delete * @param howMany number of variables to delete */ deleteVariables(index: number, howMany: number): void; /** * Increments the sequence number for the specified variable(s), which indicates a * discontinuity has occurred in the value of this variable. This information is used in a * graph to prevent drawing a line between points that have a discontinuity. * @param indexes the indexes of the variables; * if no index given then all variable's sequence numbers are incremented */ incrSequence(...indexes: number[]): void; /** * Returns the current value of the variable with the given index. * @param index the index of the variable of interest * @return the current value of the variable of interest */ getValue(index: number): number; getName(index: number): string; getSequence(index: number): number; /** * Returns an array with the current value of each variable. * The returned array is a copy of the variable values; changing the array will not change the variable values. * However, for performance, the array is maintained between invocations. */ getValues(): number[]; /** * Sets the value of each variable from the given list of values. When the length of * `vars` is less than length of VarsList then the remaining variables are not modified. * Assumes this is a discontinous change, so the sequence number is incremented * unless you specify that this is a continuous change in the variable. * @param vars array of state variables * @param continuous `true` means this new value is continuous with * previous values; `false` (the default) means the new value is discontinuous with * previous values, so the sequence number for the variable is incremented * @throws if length of `vars` exceeds length of VarsList */ setValues(vars: number[], continuous?: boolean): void; /** * @hidden */ setValuesContinuous(vars: number[]): void; /** * Sets the specified variable to the given value. Variables are numbered starting at * zero. Assumes this is a discontinous change, so the sequence number is incremented * unless you specify that this is a continuous change in the variable. * @param index the index of the variable within the array of variables * @param value the value to set the variable to * @param continuous `true` means this new value is continuous with * previous values; `false` (the default) means the new value is discontinuous with * previous values, so the sequence number for the variable is incremented * @throws if value is `NaN` */ setValue(index: number, value: number, continuous?: boolean): void; /** * @hidden */ setValueContinuous(index: number, value: number): void; /** * @hidden */ setValueJump(index: number, value: number): void; getUnits(): Unit[]; setUnits(units: Unit[]): void; setUnit(index: number, unit: Unit): void; /** * */ private checkIndex_; /** * Whether recent history is being stored, see `saveHistory`. * @return true if recent history is being stored */ getHistory(): boolean; getParameter(name: string): Variable; getParameters(): Variable[]; /** * Returns the value of the time variable, or throws an exception if there is no time variable. * * There are no explicit units for the time, so you can regard a time unit as any length * of time, as long as it is consistent with other units. * @return the current simulation time * @throws if there is no time variable */ getTime(): number; /** * Returns the Variable object at the given index or with the given name * @param id the index or name of the variable; the name can be the * English or language independent version of the name * @return the Variable object at the given index or with the given name */ getVariable(id: number | string): Variable; /** * Returns the number of variables available. This includes any deleted * variables (which are not being used and should be ignored). * @return the number of variables in this VarsList */ numVariables(): number; /** * Saves the current variables in a 'history' set, for debugging, to be able to * reproduce an error condition. See `printHistory`. */ saveHistory(): void; /** * Indicates the specified Variables are being automatically computed. * @param indexes the indexes of the variables */ setComputed(...indexes: number[]): void; /** * Sets whether to store recent history, see {@link #saveHistory}. * @param value true means recent history should be stored */ setHistory(value: boolean): void; /** * Sets the current simulation time. * @param time the current simulation time. * @throws {Error} if there is no time variable */ setTime(time: number): void; /** * Returns the index of the time variable, or -1 if there is no time variable. */ timeIndex(): number; /** * Returns the set of Variable objects in this VarsList, in their correct ordering. */ toArray(): Variable[]; } /** * A handle-body pattern abstraction of the conversion of the multivector to the system state vector. * An implementation of this interface provides the mapping from a specific multivector implementation to a vector of state variables. * Each state variable is a pair consisting of (number, Unit). This decomposition allows the solvers (integrators) to treat the whole * system as a single particle in a large vector space. */ interface Kinematics<T> { /** * */ speedOfLight: T; /** * The rate of change of position is the velocity (non-relativistic). * dX/dt = V = P / M * In the relativistic case, * dX/dt = P / sqrt(M * M + P * P), where P is the spatial part of the energy-momentum spacetime vector, M is the rest mass. * * @param rateOfChangeVals (output) * @param rateOfChangeUoms (output) * @param idx (input) * @param body (input) * @param uomTime (input) */ setPositionRateOfChangeVars(rateOfChangeVals: number[], rateOfChangeUoms: Unit[], idx: number, body: ForceBody<T>, uomTime: Unit): void; /** * Let Ω(t) be the (bivector) angular velocity. * Let R(t) be the (spinor) attitude of the rigid body. * The rate of change of attitude is given by: dR/dt = -(1/2) Ω R, * requiring the geometric product of Ω and R. * Ω and R are auxiliary and primary variables that have already been computed. * * @param rateOfChangeVals (output) * @param rateOfChangeUoms (output) * @param idx (input) * @param body (input) * @param uomTime (input) */ setAttitudeRateOfChangeVars(rateOfChangeVals: number[], rateOfChangeUoms: Unit[], idx: number, body: ForceBody<T>, uomTime: Unit): void; /** * * @param rateOfChangeVals (output) * @param rateOfChangeUoms (output) * @param idx (input) * @param body (input) * @param uomTime (input) */ zeroLinearMomentumVars(rateOfChangeVals: number[], rateOfChangeUoms: Unit[], idx: number, body: ForceBody<T>, uomTime: Unit): void; /** * * @param rateOfChangeVals (output) * @param rateOfChangeUoms (output) * @param idx (input) * @param body (input) * @param uomTime (input) */ zeroAngularMomentumVars(rateOfChangeVals: number[], rateOfChangeUoms: Unit[], idx: number, body: ForceBody<T>, uomTime: Unit): void; /** * * @param stateVals (input) * @param stateUoms (input) * @param idx (input) * @param body (output) * @param uomTime (input) */ updateBodyFromVars(stateVals: number[], stateUoms: Unit[], idx: number, body: ForceBody<T>, uomTime: Unit): void; /** * * @param body (input) * @param idx (input) * @param vars (output) */ updateVarsFromBody(body: ForceBody<T>, idx: number, vars: VarsList): void; /** * Adds the specified force to the rateOfChange variables for Linear Momentum. * @param rateOfChangeVals (input/output) * @param rateOfChangeUoms (input/output) * @param idx (input) * @param force (input) * @param uomTime (input) */ addForceToRateOfChangeLinearMomentumVars(rateOfChangeVals: number[], rateOfChangeUoms: Unit[], idx: number, force: T, uomTime: Unit): void; /** * Use when applying geometric constraints. * @param rateOfChangeVals (input) * @param rateOfChangeUoms (input) * @param idx (input) * @param force (output) */ getForce(rateOfChangeVals: number[], rateOfChangeUoms: Unit[], idx: number, force: T): void; /** * Used when applying geometric constraints. * @param rateOfChangeVals (output) * @param rateOfChangeUoms (output) * @param idx (input) * @param force (input) */ setForce(rateOfChangeVals: number[], rateOfChangeUoms: Unit[], idx: number, force: T): void; /** * Adds the specified torque to the rateOfChange variables for AngularMomentum. * @param rateOfChangeVals (input/output) * @param rateOfChangeUoms (input/output) * @param idx (input) * @param torque (input) * @param uomTime (input) */ addTorqueToRateOfChangeAngularMomentumVars(rateOfChangeVals: number[], rateOfChangeUoms: Unit[], idx: number, torque: T, uomTime: Unit): void; /** * Called by the Physics Engine during the epilog. * @param bodies (input) Provides intrinsic kinetic energy. * @param forceLaws (input) Provides potential energy. * @param potentialOffset (input) Provides a an offset in the potential energy. * @param vars (output) The list of variables containing the summary variables to be updated. */ epilog(bodies: ForceBody<T>[], forceLaws: ForceLaw<T>[], potentialOffset: T, vars: VarsList): void; /** * Called by the Physics Engine to determine the indices of all the variables that are affected by a * discontinuous change to the energy of the system. i.e., an "intervention" where the bodies in the * system are changed independently of the differential equations that are implemented by the Physics Engine. * @returns The indices into the variables list. */ discontinuousEnergyVars(): number[]; /** * Used by the Physics engine when adding a body to the system. * Returns the name of the kinematic variable at the specified index which * ranges over [0, numVarsPerBody - 1]. * * The name must be valid (isValidName) after having being munged (toName). */ getOffsetName(offset: number): string; /** * Used by the Physics class constructor to create a list of variables. * One of the names returned must be the (case-sensitive) "TIME" variable. */ getVarNames(): string[]; /** * Use by the Physics engine to add the correct number of variables for each body added. * The number of variables must be at least one. */ numVarsPerBody(): number; } /** * @hidden */ declare class SimList extends AbstractSubject { /** * */ static OBJECT_ADDED: string; /** * */ static OBJECT_REMOVED: string; /** * */ private $elements; /** * */ constructor(); /** * */ add(element: SimObject): void; /** * */ forEach(callBack: (simObject: SimObject, index: number) => unknown): void; /** * */ remove(simObject: SimObject): void; /** * Removes SimObjects from this SimList whose *expiration time* is less than the given time. * Notifies Observers by broadcasting the `OBJECT_REMOVED` event for each SimObject removed. * @param time the current simulation time */ removeTemporary(time: number): void; } /** * */ interface EngineOptions { method?: 'rk4'; } /** * A generic Physics Engine that may be specialized to a metric. */ declare class Engine<T> { private readonly kinematics; private readonly physics; private readonly strategy; /** * * @param metric * @param kinematics * @param options */ constructor(metric: Metric<T>, kinematics: Kinematics<T>, options?: Partial<EngineOptions>); /** * The speed of light. * For dimensionless simulations this will default to 1. * For S.I. Units, the speed of light may be set. */ get speedOfLight(): T; set speedOfLight(speedOfLight: T); get bodies(): ForceBody<T>[]; /** * Returns the state variables of the system. */ get varsList(): VarsList; get simList(): SimList; /** * Adds a body to the system. * The state variables of the body will become part of the state vector of the system. * The state variables of the body will be updated each time the system is advanced in time. * @param body The body to be added to the system */ addBody(body: ForceBody<T>): void; /** * Removes a body from the system. * @param body The body to be removed from the system. */ removeBody(body: ForceBody<T>): void; /** * Adds a force law to the system. * @param forceLaw The force law to be added to the system. */ addForceLaw(forceLaw: ForceLaw<T>): void; /** * Removes a force law from the system. * @param forceLaw The force law to be removed. */ removeForceLaw(forceLaw: ForceLaw<T>): void; /** * Adds a torque law to the system. * @param torqueLaw The torque law to be added to the system. */ addTorqueLaw(torqueLaw: TorqueLaw<T>): void; /** * Removes a torque law from the system. * @param torqueLaw The torque law to be removed from the system. */ removeTorqueLaw(torqueLaw: TorqueLaw<T>): void; /** * Adds a geometric constraint to the system. * Geometric constraints are applied after the force and torques have been computed and before drift forces and torques. * @param geometry The geometric constraint to be added to the system. */ addConstraint(geometry: GeometricConstraint<T>): void; /** * Removes a geometric constraint from the system. * @param geometry The geometric constraint to be removed from the system. */ removeConstraint(geometry: GeometricConstraint<T>): void; /** * Adds a force law that is designed to compensate for numerical drift in the system. * A drift law is usually small and may take the form of a spring and/or damping force. * The drift laws are applied after any geometric constraints have been applied. * @param driftLaw The drift force law to be applied. */ addDriftLaw(driftLaw: ForceLaw<T>): void; /** * Removes a force law that is designed to compensate for numerical drift in the system. * @param driftLaw The drift force law to be removed. */ removeDriftLaw(driftLaw: ForceLaw<T>): void; /** * Advances the Physics model by the specified time interval, Δt * uomTime. * @param Δt The time interval. * @param uomTime The optional unit of measure for the time interval. */ advance(Δt: number, uomTime?: Unit): void; /** * Updates the state vector of the simulation from the states of the bodies in the system. * It is necessary to call this method after an intervention which changes the state of * a body in the system. */ updateFromBodies(): void; /** * * @returns The total energy (kinetic and potential) of the system. */ totalEnergy(): T; get showForces(): boolean; set showForces(showForces: boolean); get showTorques(): boolean; set showTorques(showTorques: boolean); } declare class FaradayLaw<T> extends AbstractSimObject implements ForceLaw<T> { private body; private field; private readonly force; private readonly $forces; /** * force = Q * (v << F), where Q is the body charge, v is the ordinary spacetime velocity, F is the Faraday field at the body location. * @param body the body upon which the field acts. * @param field the Faraday field. This field that has a bivector value. */ constructor(body: Charged<T>, field: (position: T) => T); get forces(): Force<T>[]; updateForces(): Force<T>[]; disconnect(): void; potentialEnergy(): T; } /** * A ForceBody with a mass property, M. */ interface Massive<T> extends ForceBody<T> { M: T; } /** * */ declare class GravitationLaw<T> extends AbstractSimObject implements ForceLaw<T> { private body1; private body2; /** * The proportionality constant, Universal gravitational constant or Newton's constant. * The default value is one (1). */ private readonly $G; private readonly F1; private readonly F2; private readonly $forces; /** * Scratch variable for computing potential energy. */ private readonly potentialEnergy_; private potentialEnergyLock_; private readonly metric; /** * */ constructor(body1: Massive<T>, body2: Massive<T>); get G(): T; set G(G: T); get forces(): Force<T>[]; /** * Computes the forces due to the gravitational interaction. * F = G * m1 * m2 * direction(r2 - r1) / quadrance(r2 - r1) */ updateForces(): Force<T>[]; /** * */ disconnect(): void; /** * Computes the potential energy of the gravitational interaction. * U = -G m1 m2 / r, where * r is the center-of-mass to center-of-mass separation of m1 and m2. */ potentialEnergy(): T; } /** * */ declare class LinearDamper<T> extends AbstractSimObject implements ForceLaw<T> { private readonly body1; private readonly body2; /** * Friction Coefficient. */ private $frictionCoefficient; /** * The force information on body1 due to body2. */ private readonly F1; /** * The force information on body2 due to body1. */ private readonly F2; /** * */ private readonly $forces; /** * * @param body1 * @param body2 */ constructor(body1: ForceBody<T>, body2: ForceBody<T>); get forces(): Force<T>[]; get b(): T; set b(b: T); get frictionCoefficient(): T; set frictionCoefficient(frictionCoefficient: T); updateForces(): Force<T>[]; disconnect(): void; potentialEnergy(): T; } /** * */ declare class RigidBody<T> extends AbstractSimObject implements ForceBody<T>, Massive<T>, Charged<T> { readonly metric: Metric<T>; /** * A uniquie identifier assigned by applications. * This is not used internally. */ uuid: string; /** * Mass, M. Default is one (1). * Changing the mass requires an update to the inertia tensor, * so we want to control the mutability. The mass is locked by default */ private readonly $mass; /** * Charge, Q. Default is zero (0). */ private readonly $charge; /** * Inverse of the Inertia tensor in body coordinates. */ private $inertiaTensorInverse; /** * the index into the variables array for this rigid body, or -1 if not in vars array. */ private varsIndex_; /** * The position (vector). */ private readonly $X; /** * The attitude (spinor). */ private readonly $R; /** * The linear momentum (vector). */ private readonly $P; /** * The angular momentum (bivector). */ private readonly $L; /** * Scratch member variable used only during updateAngularVelocity. * The purpose is to avoid temporary object creation. */ private Ω_scratch; /** * Angular velocity (bivector). * The angular velocity is initially created in the unlocked state. */ private $Ω; /** * center of mass in local coordinates. */ private $centerOfMassLocal; /** * Scratch variable for rotational energy. */ private $rotationalEnergy; /** * Scratch variable for translational energy. */ private $translationalEnergy; /** * Scratch variable for calculation worldPoint. */ private readonly $worldPoint; /** * @param metric */ constructor(metric: Metric<T>); /** * The center of mass position vector in local coordinates. */ get centerOfMassLocal(): T; set centerOfMassLocal(centerOfMassLocal: T); /** * Mass (scalar). Default is one (1). * If dimensioned units are used, they must be compatible with the unit of mass. * M is immutable but the property may be reassigned. */ get M(): T; set M(M: T); /** * Charge (scalar). Default is zero (0). * If dimensioned units are used, they must be compatible with the unit of electric charge. * Q is immutable but the property may be reassigned. */ get Q(): T; set Q(Q: T); /** * Updates the angular velocity, Ω, bivector based upon the angular momentum. * Derived classes may override to provide more efficient implementations based upon symmetry. */ updateAngularVelocity(): void; /** * Derived classes should override. */ protected updateInertiaTensor(): void; /** * Inertia Tensor (in body coordinates) (3x3 matrix). * The returned matrix is a copy. * TODO: This copy should be locked. */ get I(): MatrixLike; /** * Sets the Inertia Tensor (in local coordinates) (3x3 matrix), and computes the inverse. */ set I(I: MatrixLike); /** * Inertia Tensor (in body coordinates) inverse (3x3 matrix). */ get Iinv(): MatrixLike; set Iinv(source: MatrixLike); /** * Position (vector). * If dimensioned units are used, they must be compatible with the unit of length. * X is mutable with copy-on-set. */ get X(): T; set X(position: T); /** * Attitude (spinor). * Effects a rotation from local coordinates to world coordinates. * R is mutable with copy-on-set. */ get R(): T; set R(attitude: T); /** * Linear momentum (vector). * If dimensioned units are used, they must be compatible with the unit of momentum. * P is mutable with copy-on-set. */ get P(): T; set P(linearMomentum: T); /** * Angular momentum (bivector) in world coordinates. * If dimensioned units are used, they must be compatible with the unit of angular momentum. * L is mutable with copy-on-set. */ get L(): T; set L(angularMomentum: T); /** * Angular velocity (bivector). * If dimensioned units are used, they must be compatible with the unit of angular velocity. * Ω is mutable with copy-on-set. */ get Ω(): T; set Ω(angularVelocity: T); /** * */