4492b4106a
1. 新增怀旧弹珠台、人性与投资、穿越三体、四维空间四个思想实验室项目 2. 为私有剪贴板添加业务层授权校验,优化上传进度显示与鉴权失败处理 3. 新增多个调试与单元测试脚本,覆盖三体积分、弹珠台物理、集成测试等场景 4. 补全穿越三体项目的完整HTML页面资源
54 lines
2.5 KiB
JavaScript
54 lines
2.5 KiB
JavaScript
// ============================================================
|
||
// test_three_body_integrator.js - 穿越三体 · 三体积分器校验
|
||
// 从 public/tools/thought_lab/labs/three_body_journey/index.html 抽取
|
||
// THREEBODY_MATH_BEGIN/END 之间的纯物理代码执行校验(测试对象 = 上线代码)。
|
||
// 校验:RK4 积分动量守恒、能量漂移极小、加速度满足牛顿第三定律对称性。
|
||
// 运行:node dev_test_scripts/unit/test_three_body_integrator.js
|
||
// ============================================================
|
||
'use strict'
|
||
const fs = require('fs')
|
||
const path = require('path')
|
||
const vm = require('vm')
|
||
|
||
const HTML = path.resolve(__dirname, '..', '..', 'public', 'tools', 'thought_lab', 'labs', 'three_body_journey', 'index.html')
|
||
const src = fs.readFileSync(HTML, 'utf8')
|
||
const m = src.match(/\/\/ ==== THREEBODY_MATH_BEGIN ====\n([\s\S]*?)\/\/ ==== THREEBODY_MATH_END ====/)
|
||
if (!m) { console.error('FAIL - 未找到 THREEBODY_MATH 标记块'); process.exit(1) }
|
||
|
||
const api = vm.runInNewContext(m[1] + ';({ tbAccel, tbStep, tbEnergy, tbMomentum })')
|
||
|
||
let pass = 0, fail = 0
|
||
const check = (name, cond) => {
|
||
if (cond) { pass++; console.log('PASS -', name) }
|
||
else { fail++; console.log('FAIL -', name) }
|
||
}
|
||
|
||
const masses = [1, 1, 1]
|
||
const eps2 = 0.02
|
||
let pos = [1, 0, -0.5, Math.sqrt(3) / 2, -0.5, -Math.sqrt(3) / 2]
|
||
let vel = [0, 0.42, -0.38, -0.2, 0.38, -0.22]
|
||
|
||
// 牛顿第三定律:Σ mᵢaᵢ = 0(作用力反作用力,任意位形)
|
||
{
|
||
const ms = [1, 2, 0.5]
|
||
const a = api.tbAccel([0, 0, 1, 0.3, -0.7, 1.2], ms, 0)
|
||
let sx = 0, sy = 0
|
||
for (let i = 0; i < 3; i++) { sx += ms[i] * a[2 * i]; sy += ms[i] * a[2 * i + 1] }
|
||
check('Σ mᵢaᵢ = 0(作用反作用)', Math.abs(sx) < 1e-12 && Math.abs(sy) < 1e-12)
|
||
}
|
||
|
||
// 动量守恒:跑 5000 步
|
||
const p0 = api.tbMomentum(vel, masses)
|
||
const E0 = api.tbEnergy(pos, vel, masses, eps2)
|
||
for (let i = 0; i < 5000; i++) [pos, vel] = api.tbStep(pos, vel, masses, 0.002, eps2)
|
||
const p1 = api.tbMomentum(vel, masses)
|
||
const E1 = api.tbEnergy(pos, vel, masses, eps2)
|
||
check('动量守恒(5000 步,|Δp|<1e-9)', Math.abs(p1[0] - p0[0]) < 1e-9 && Math.abs(p1[1] - p0[1]) < 1e-9)
|
||
check(`能量漂移小(|ΔE/E0|<1e-3,实际 ${Math.abs((E1 - E0) / E0).toExponential(2)})`, Math.abs((E1 - E0) / E0) < 1e-3)
|
||
|
||
// 有限性:5000 步后位置/速度均为有限数(软化避免奇点崩溃)
|
||
check('积分稳定(全部有限)', [...pos, ...vel].every(Number.isFinite))
|
||
|
||
console.log(fail === 0 ? `ALL PASS (${pass})` : `FAILED: ${fail} / ${pass + fail}`)
|
||
process.exit(fail === 0 ? 0 : 1)
|