Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add nbody wrapper functionality #307

Merged
merged 2 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions modules.json
Original file line number Diff line number Diff line change
Expand Up @@ -111,5 +111,10 @@
},
"communication": {
"tabs": []
},
"nbody": {
"tabs": [
"Nbody"
]
}
}
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
"@types/plotly.js-dist": "npm:@types/plotly.js",
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
"@types/three": "^0.161.2",
"@types/three": "^0.163.0",
"@vitejs/plugin-react": "^4.0.4",
"acorn": "^8.8.1",
"acorn-jsx": "^5.3.2",
Expand Down Expand Up @@ -109,6 +109,7 @@
"js-slang": "^1.0.55",
"lodash": "^4.17.21",
"mqtt": "^4.3.7",
"nbody": "^0.1.1",
"os": "^0.1.2",
"patch-package": "^6.5.1",
"phaser": "^3.54.0",
Expand All @@ -122,7 +123,7 @@
"save-file": "^2.3.1",
"source-academy-utils": "^1.0.0",
"source-academy-wabt": "^1.0.4",
"three": "^0.162.0",
"three": "^0.163.0",
"tslib": "^2.3.1",
"uniqid": "^5.4.0",
"url": "^0.11.3"
Expand Down
75 changes: 75 additions & 0 deletions src/bundles/nbody/CelestialBody.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { CelestialBody, type Vector3 } from 'nbody';

/**
* Create a new celestial body.
* @param label label of the body.
* @param mass mass of the body.
* @param position position of the body.
* @param velocity velocity of the body.
* @param acceleration acceleration of the body.
* @returns A new celestial body.
* @category Celestial Body
*/
export function createCelestialBody(label: string, mass: number, radius?: number, position?: Vector3, velocity?: Vector3, acceleration?: Vector3): CelestialBody {
return new CelestialBody(label, mass, radius, position, velocity, acceleration);
}

/**
* Get the label of a celestial body.
* @param body The celestial body.
* @returns The label of the celestial body.
* @category Celestial Body
*/
export function getLabel(body: CelestialBody): string {
return body.label;
}

/**
* Get the mass of a celestial body.
* @param body The celestial body.
* @returns The mass of the celestial body.
* @category Celestial Body
*/
export function getMass(body: CelestialBody): number {
return body.mass;
}

/**
* Get the radius of a celestial body.
* @param body The celestial body.
* @returns The radius of the celestial body.
* @category Celestial Body
*/
export function getRadius(body: CelestialBody): number {
return body.radius;
}

/**
* Get the position of a celestial body.
* @param body The celestial body.
* @returns The position of the celestial body.
* @category Celestial Body
*/
export function getPosition(body: CelestialBody): Vector3 {
return body.position;
}

/**
* Get the velocity of a celestial body.
* @param body The celestial body.
* @returns The velocity of the celestial body.
* @category Celestial Body
*/
export function getVelocity(body: CelestialBody): Vector3 {
return body.velocity;
}

/**
* Get the acceleration of a celestial body.
* @param body The celestial body.
* @returns The acceleration of the celestial body.
* @category Celestial Body
*/
export function getAcceleration(body: CelestialBody): Vector3 {
return body.acceleration;
}
41 changes: 41 additions & 0 deletions src/bundles/nbody/Force.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { CentripetalForce, CombinedForce, Gravity, type CelestialBody, type Force, type Vector3, LambdaForce } from 'nbody';

/**
* Create a force that applies to all bodies using the provided higher order/lambda/arrow/anonymous function.
* @param fn A function that takes an array of bodies and returns an array of forces of the same length.
* @returns A new lambda force.
* @category Forces
*/
export function createForce(fn: (bodies: CelestialBody[]) => Vector3[]): Force {
return new LambdaForce(fn);
}

/**
* Create a force that applies to all bodies.
* @param G The gravitational constant.
* @returns A new gravity force.
* @category Forces
*/
export function createGravity(G?: number): Gravity {
return new Gravity(G);
}

/**
* Create a centripetal force that pulls bodies towards a center.
* @param center The center of the centripetal force.
* @returns A new centripetal force.
* @category Forces
*/
export function createCentripetalForce(center?: Vector3): CentripetalForce {
return new CentripetalForce(center);
}

/**
* Create a combined force that is an additive combination of all the given forces.
* @param forces The forces to combine.
* @returns A new combined force.
* @category Forces
*/
export function createCombinedForce(forces: Force[]): CombinedForce {
return new CombinedForce(forces);
}
14 changes: 14 additions & 0 deletions src/bundles/nbody/Misc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { CelestialBody, State, Universe, Vector3 } from 'nbody';

/**
* Deep clone an object.
* @param obj The object to clone.
* @returns The cloned object.
* @category Celestial Body
* @category State
* @category Universe
* @category Vector
*/
export function clone(obj: CelestialBody | State | Universe | Vector3): CelestialBody | State | Universe | Vector3 {
return obj.clone();
}
52 changes: 52 additions & 0 deletions src/bundles/nbody/SimulateFunction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { ExplicitEulerSim, LambdaSim, RungeKutta4Sim, SemiImplicitEulerSim, VelocityVerletSim, type Force, type State } from 'nbody';

/**
* Create an explicit euler integrator to be used as the simulation function.
* @param force The force that applies to the nbody system.
* @returns A new explicit Euler simulation.
* @category Simulate Functions
*/
export function createExplicitEulerSim(force?: Force): ExplicitEulerSim {
return new ExplicitEulerSim(force);
}

/**
* Create a numerical integrator that uses the Runge-Kutta 4 method to simulate the nbody system.
* @param force The force that applies to the nbody system.
* @param weights The weights to be used for the weighted sum of the k values.
* @returns A new Runge-Kutta 4 simulation.
* @category Simulate Functions
*/
export function createRungeKutta4Sim(force?: Force, weights?: number[]): RungeKutta4Sim {
return new RungeKutta4Sim(force, weights);
}

/**
* Create a numerical integrator that uses the semi-implicit Euler method to simulate the nbody system.
* @param force The force that applies to the nbody system.
* @returns A new semi-implicit Euler simulation.
* @category Simulate Functions
*/
export function createSemiImplicitEulerSim(force?: Force): SemiImplicitEulerSim {
return new SemiImplicitEulerSim(force);
}

/**
* Create a numerical integrator that uses the velocity Verlet method to simulate the nbody system.
* @param force The force that applies to the nbody system.
* @returns A new velocity Verlet simulation.
* @category Simulate Functions
*/
export function createVelocityVerletSim(force: Force): VelocityVerletSim {
return new VelocityVerletSim(force);
}

/**
* Create a simulate function (usually a numerical integrator) that is used to simulate the nbody system using the provided higher order/lambda/arrow/anonymous function.
* @param fn The function to be used as the simulate function.
* @returns A new lambda simulation.
* @category Simulate Functions
*/
export function createLambdaSim(fn: (deltaT: number, prevState: State, currState: State) => State): LambdaSim {
return new LambdaSim(fn);
}
86 changes: 86 additions & 0 deletions src/bundles/nbody/Simulation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import context from 'js-slang/context';
import { RecordingVisualizer, RecordingVisualizer3D, Simulation, type Universe, type VisType } from 'nbody';

/**
* Create a new simulation.
* @param universes The universes to simulate.
* @param visType The visualization type.
* @param record Whether to record the simulation.
* @param looped Whether to loop the simulation.
* @param showTrails Whether to show trails.
* @param showDebugInfo Whether to show debug info
* @param maxTrailLength The maximum length of trails.
* @returns A new simulation.
* @category Simulation
*/
export function createSimulation(universes: Universe[],
visType: VisType,
record?: boolean,
looped?: boolean,
showTrails?: boolean,
maxTrailLength?: number): Simulation {
return new Simulation(universes, {
visType,
record,
looped,
controller: 'code',
showTrails,
maxTrailLength,
});
}

const simulations: Simulation[] = [];
const recordInfo = {
isRecording: false,
recordFor: 0,
recordSpeed: 0,
};

context.moduleContexts.nbody.state = {
simulations,
recordInfo
};

function isRecordingBased(sim: Simulation): boolean {
return sim.visualizer instanceof RecordingVisualizer || sim.visualizer instanceof RecordingVisualizer3D;
}

/**
* Play a simulation.
* @param sim The simulation to play.
* @category Simulation
*/
export function playSim(sim: Simulation): void {
while (simulations.length > 0) {
simulations.pop()!.stop();
}
if (isRecordingBased(sim)) {
throw new Error(
'playSim expects non-recording simulations'
);
}
recordInfo.isRecording = false;
simulations.push(sim);
}

/**
* Record and play a simulation.
* @param sim simulation to record and play.
* @param recordFor time to record for.
* @param recordSpeed speed to record at.
* @category Simulation
*/
export function recordSim(sim: Simulation, recordFor: number, recordSpeed: number): void {
while (simulations.length > 0) {
simulations.pop()!.stop();
}
if (!isRecordingBased(sim)) {
throw new Error(
'recordSim expects recording simulations'
);
}
recordInfo.isRecording = true;
recordInfo.recordFor = recordFor;
recordInfo.recordSpeed = recordSpeed;
simulations.push(sim);
}
21 changes: 21 additions & 0 deletions src/bundles/nbody/State.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { type CelestialBody, State } from 'nbody';

/**
* Create a new state snapshot of the universe.
* @param bodies The bodies in the state.
* @returns A new state.
* @category State
*/
export function createState(bodies: CelestialBody[]): State {
return new State(bodies);
}

/**
* Get the bodies in a state.
* @param state The state.
* @returns The bodies in the state.
* @category State
*/
export function getBodies(state: State): CelestialBody[] {
return state.bodies;
}
Loading
Loading