davinci-newton
Version:
Physics Modeling and Engine using Geometric Algebra
1,649 lines (1,614 loc) • 184 kB
TypeScript
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);
/**
*
*/