Skip to content

Commit fdaad9b

Browse files
Closes: #16 Add the ability to control the simulation from JS (#24)
* Add the ability to control the simulation from JS * Remove unnecessary #ifdef __EMSCRIPTEN__ * Move all generate files into dist * Improve and fix CI * Remove js file * Simple updated readme * Clean up the new interface a bit * fix js async callbacks for run/minimize + compute scalar sync, add tests * Rename async method * Change example to control simulation speed only through the async method * Bumped version --------- Co-authored-by: Anders Hafreager <anders.hafreager@cognite.com>
1 parent 14a2b2f commit fdaad9b

27 files changed

Lines changed: 2613 additions & 594 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,4 @@ coverage
120120
cpp/lammps
121121
cpp/obj
122122
cpp/.emscripten_cache
123+
cpp/build_emscripten

README.md

Lines changed: 88 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,90 @@
33
[![CI](https://github.com/lammps/lammps.js/actions/workflows/ci.yml/badge.svg)](https://github.com/lammps/lammps.js/actions/workflows/ci.yml)
44
[![npm version](https://img.shields.io/npm/v/lammps.js.svg)](https://www.npmjs.com/package/lammps.js)
55

6-
Run LAMMPS directly in the browser — a WebAssembly build with TypeScript-ready bindings.
7-
The package exports the compiled `lammps.js` module together with a modern interface (`LAMMPSWeb`) that exposes snapshots for particles, bonds and simulation box data.
6+
LAMMPS in the browser. WebAssembly build + a small TS-friendly client.
87

9-
## Usage
8+
## Install
9+
10+
```bash
11+
npm install lammps.js
12+
```
13+
14+
## Usage (main flow: `runScriptAsync`)
15+
16+
`runScriptAsync()` is the main API.
17+
It works with `run ...` and `minimize ...`.
18+
Your callback is called every `N` steps (`every`).
19+
LAMMPS waits for the callback Promise before going to the next step.
20+
If the Promise never resolves, simulation stays paused.
1021

1122
```ts
1223
import { LammpsClient } from "lammps.js/client";
1324

25+
const lammps = await LammpsClient.create();
26+
lammps.start();
27+
28+
await lammps.runScriptAsync(
29+
`
30+
units lj
31+
atom_style atomic
32+
lattice fcc 0.8442
33+
region box block 0 3 0 3 0 3
34+
create_box 1 box
35+
create_atoms 1 box
36+
mass 1 1.0
37+
pair_style lj/cut 2.5
38+
pair_coeff 1 1 1.0 1.0 2.5
39+
run 5000
40+
`,
41+
async (data) => {
42+
console.log("step", data.step, "count", data.particles?.count);
43+
await new Promise(requestAnimationFrame);
44+
},
45+
{ every: 50 }
46+
);
47+
```
48+
49+
You can control speed from JS (no `run 1` loop):
50+
51+
```ts
52+
let speed = 5; // UI-controlled value
53+
54+
await lammps.runScriptAsync(
55+
"run 100000",
56+
async () => {
57+
const delayMs = Math.max(0, 100 - speed * 10);
58+
await new Promise((resolve) => setTimeout(resolve, delayMs));
59+
},
60+
{ every: 1 }
61+
);
62+
```
63+
64+
You can also include compute scalars in callback data:
65+
66+
```ts
67+
await lammps.runScriptAsync(
68+
`
69+
compute ctemp all temp
70+
compute cke all ke
71+
minimize 0.0 1.0e-6 100 1000
72+
uncompute ctemp
73+
uncompute cke
74+
`,
75+
async (data) => {
76+
console.log("step", data.step);
77+
console.log("temp", data.computeScalars?.ctemp);
78+
console.log("ke", data.computeScalars?.cke);
79+
},
80+
{
81+
every: 5,
82+
computeScalars: ["ctemp", "cke"],
83+
}
84+
);
85+
```
86+
87+
## Usage (manual stepping, optional)
88+
89+
```ts
1490
const lammps = await LammpsClient.create();
1591

1692
lammps.start().runScript(`
@@ -29,31 +105,6 @@ lammps.start().runScript(`
29105
const particles = lammps.syncParticles({ copy: true });
30106
console.log(`atoms: ${particles.count}`);
31107

32-
const wrapped = lammps.syncParticles({ wrapped: true, copy: true });
33-
console.log(`wrapped positions length: ${wrapped.positions.length}`);
34-
35-
lammps.dispose();
36-
```
37-
38-
Advance the solver (via `advance(stepCount, applyPre?, applyPost?)`) between snapshots to receive new frames.
39-
40-
Advance the solver (`advance(stepCount, applyPre?, applyPost?)`) before sampling to obtain subsequent frames.
41-
The TypeScript definitions are shipped with the package under
42-
`types/index.d.ts`, so IDEs receive auto-complete everywhere.
43-
44-
45-
### High-level client
46-
47-
For a more ergonomic API, use the helpers in `lammps.js/client`:
48-
49-
```ts
50-
import { LammpsClient } from "lammps.js/client";
51-
52-
const lammps = await LammpsClient.create();
53-
await fetch("/in.lj")
54-
.then(res => res.text())
55-
.then(script => lammps.runInput("in.lj", script));
56-
57108
for (let frame = 0; frame < 10; frame += 1) {
58109
lammps.advance(1, false, false);
59110
const { positions, count } = lammps.syncParticles({ copy: true });
@@ -63,47 +114,29 @@ for (let frame = 0; frame < 10; frame += 1) {
63114
lammps.dispose();
64115
```
65116

66-
Advance the solver (via `advance(stepCount, applyPre?, applyPost?)`) between snapshots to receive new frames.
67-
68-
Use `syncParticles({ wrapped: true })` and `syncBonds({ wrapped: true })` to access
69-
raw periodic coordinates while the default returns minimum-image data, ready for rendering.
70-
71-
Install via npm:
72-
73-
```bash
74-
npm install lammps.js
75-
```
76-
77-
## Building the wasm bundle
117+
## Build
78118

79119
```bash
80-
npm run build:wasm
120+
npm run build
81121
```
82122

83-
This calls `cpp/build.py`, which keeps the upstream LAMMPS checkout in
84-
`cpp/lammps` fresh and emits `cpp/lammps.js` (single-file ES module).
85-
86-
## Test suite
123+
Outputs go straight into `dist/`:
124+
- `dist/cpp/lammps.js` (single-file wasm module)
125+
- `dist/client.js`
126+
- `dist/**/*.d.ts`
87127

88-
The Vitest suite spins up a jsdom environment, instantiates the wasm module,
89-
loads a miniature Lennard-Jones sample and validates the public interface.
128+
## Tests
90129

91130
```bash
92131
npm test
93132
```
94133

95-
> The build step fetches the LAMMPS sources on first run. Subsequent runs are
96-
> incremental thanks to the cached checkout and Emscripten cache.
97-
98-
## Examples
99-
100-
A ready-to-run Three.js demo lives in `examples/threejs`:
134+
## Example
101135

102136
```bash
103137
cd examples/threejs
104138
npm install
105139
npm run dev
106140
```
107141

108-
It links against the local workspace copy of `lammps.js` and renders the
109-
Lennard-Jones sample (`tests/fixtures/lj.mini.in`).
142+
It uses `tests/fixtures/lj.mini.in`.

client.js

Lines changed: 0 additions & 165 deletions
This file was deleted.

0 commit comments

Comments
 (0)