PulseCore

Chapter 4 · Section 8

The Direct Pull and the Particle–Particle Split

The BPT law

BPT does not state this; it is a game method that serves two things the book does state. The first is the pull and the horizon. BPT Part 2.4 (Event Horizons and Null Wells) takes Newtonian gravity as given and reads the horizon at the "event horizon scale r_s = 2GM/c²" as the boundary where a well's Pulse activity falls to null; Part 3.11 sets the G it uses. The second is the sites. BPT Part 3.14 (Proto Wells: Where Wells Will Form) says "a Proto Well is not a well. Formed in the data before the physical layer, it is the deepest place of the Data Matter, the seed of a halo (Part 3.13), and at the Physical Nova it becomes a site: where the gas will gather, where the first stars will light, and where a well will be born." A site therefore has no horizon and no point mass of its own: in the code it is the heart of the matter round it, and it pulls only through the grid, as that matter does (ruling 2026-10-29, matter.js:242–245). The direct pull below is how the game resolves Newton's law near a real well, where the mesh is too coarse.

The established physics

  • Newton's law with Plummer softening, a = GM·r̂/(r² + ε²), the softening "every N-body code uses" (matter.js:322); the P³M split of a short-range direct force and a long-range mesh force (Hockney & Eastwood 1988, cited at matter.js:335).
  • The Schwarzschild radius r_s = 2GM/c² (BPT Part 2.4).

The game's math

accel(b, wells, isWell) matter.js:331:

  • A site (b.site) feels the bodies' field alone, interpolated (matter.js:336–338). Sites pull nothing directly (if (w.site) continue).
  • A body feels the bodies' mesh field, plus each non-site well within three blocks directly, faded by near = max(0, 1 − d/(2B)) to nothing at two blocks (matter.js:352).
  • A well feels the wells' mesh field (matter, Data Matter, sites) plus every other non-site well directly at full strength, unless more than 256 wells pull (nPull > 256): then it is treated as a body (whole grid with wells included, plus direct pulls within two blocks, faded). Ruling 2026-10-29, after 15,000 sites at level 202 made 2 × 10⁸ pairs a sub-step and a step took 53 s.

The direct term (matter.js:351–354):

d² = dr² + dc² + ε²,   a = near · G · max(1, M) / d²,   along (dr, dc)/d
ε  = reach(w) = max(1, r_s, (10·G·max(1, M))^(1/3))        matter.js:324
r_s = horizon(w) = 2·G·max(1, M) / c²   (0 for a site)    matter.js:318

The (10GM)^(1/3) term: inside it one flip's pull would bend a path by more than a tenth of the distance, which a one-flip step cannot follow (matter.js:319–323). The softening is computed once per binning (w._soft).

Binning (also read from the wells' side in Chapter 3, Part 3.12). binWells() matter.js:272 sorts non-site wells into mesh blocks. If more than 8 pull and the mesh has more than 7 blocks a side, every well writes itself into the 7 × 7 blocks round it once, so a body's near list is one lookup (profiled 2026-10-28: 14 % of a physical step was rebuilding those lists). wellsNear() matter.js:291 returns every puller when there are 8 or fewer, or when the reach wraps the torus. binBodies() and bodiesNear() matter.js:304–316 do the same for bodies.

Worked case, desktop at level 6 or deeper with G_F ≈ 4.3 × 10⁻⁷ and c = 128: a well of 10⁴ cells has r_s = 2 × 4.3 × 10⁻⁷ × 10⁴ / 16,384 ≈ 5 × 10⁻⁷ cells, (10GM)^(1/3) = (0.043)^(1/3) ≈ 0.35, so ε = 1 cell: the softening is the one-cell floor, not the horizon.

In the game

The direct pull is what the player sees near the wells: clumps swinging round a well and on past it, or falling in (Part 4.12), and wells drifting through the matter toward each other until they merge (the merger of wells and its finds are in Chapter 3). In 3D every well is drawn where its pull has carried it, moved each slice by moveWells() (app.js:1312); a well inside a drawn galaxy is drawn small, a third of its mark, "a horizon is tiny next to its galaxy" (setWells() scene3d.js:1471–1475). The HUD's Wells line counts the sites still waiting for their wells: "… · N sites waiting" (app.js:2141–2142). No control changes the pull.

The scale model

The direct pull covers what the mesh cannot resolve, within two blocks. Beyond the 256-well switch, well–well pulls past two blocks come from the mesh, at its resolution. Both are numerical resolution, not physics, and change nothing at the level of the law: the same G and the same masses.

Fixed numbers

Number Where What it is Kind
3 accel() matter.js:349; binWells() matter.js:283 Blocks searched for a body's direct wells (7 × 7) METHOD (covers the 2-block fade)
2 accel() matter.js:352 Direct pull fades to zero at 2B METHOD (P³M split)
256 accel() matter.js:339 Wells pulling directly before wells go on the grid METHOD (P³M switch for cost)
8 binWells() matter.js:281; wellsNear() matter.js:293 Few enough wells to skip bins METHOD
7 binWells() matter.js:281 Mesh must exceed 7 blocks for the cache METHOD
10 reach() matter.js:324 Softening (10GM)^(1/3): a tenth of the distance bent a flip METHOD (resolution)
1 reach() matter.js:324 Softening floor, cells METHOD
1 accel() matter.js:353; horizon() matter.js:318 Floor on a well's mass METHOD
2 horizon() matter.js:318 r_s = 2GM/c² PHYSICS (Schwarzschild 1916; BPT Part 2.4)