文档

DSL 基础

理解场景、实体、连接、约束和展示语句。

PhysLoom DSL 追求描述物理模型,而不是描述 SVG。一个模型通常由五层信息组成:场景、实体、连接、物理参数和展示要求。

场景

每个模型从 scene 开始:

scene inclined_plane

// 后面依次写实体和关系

场景名用于识别模型,不会自动成为图上的标题。

实体

实体是模型中的对象。常见实体包括 body、support、pulley、surface、spring、charge 和电路元件。

load crate 8kg
support ceiling orientation=horizontal
surface ramp incline 30deg
spring S 120N/m

标识符应简短且唯一。显示给读者的文字可以另外设置,不必把一整句塞进标识符。

连接和路径

连接说明对象之间的关系。对于常见滑轮系统,只声明滑轮的附着关系就够了:

load A 2kg
load B 3kg
pulley P
support ceiling

P <-> ceiling

编译器会推导经过 P 且与轮缘相切的绳路,并把它纳入绳长约束。只有多根绳或特殊路径使拓扑产生歧义时,才需要显式声明具名绳路。

参数和单位

数值应带单位:

量示例
质量mass=2kg
距离distance=0.5m
角度angle=30deg
劲度系数stiffness=120N/m

编译器会把单位归一化后再求解。不要用名称代替单位,也不要把 1kg 写成图上的纯文本来规避模型参数。

导轨上的导体棒可以穿过一段有限磁场:

field B magnetic 1T direction=into_page x_min=1.5m x_max=3.5m

两个端点都以导轨左端为原点,必须位于导轨范围内。区间外 B 为零;省略两个端点则表示 磁场覆盖整个装置。当前只支持一根棒向右运动、闭合纯电阻回路,不表示任意粒子或波的边界模型。 可以打开穿过磁场的综合题,只修改 x_max 做对比。

定义一次,显式复用

同一数值用于不同声明时,用 let 定义,用 $name 引用:

scene matched_lamp
let supply = 6V

source V $supply
lamp L $supply 3W
V <-> L <-> V

修改 supply 会同时改变电源电压和灯泡额定电压。若只想改变供电电压,灯泡额定值应独立填写。 共享参数表示作者主动声明的数值相等,不表示编译器自动推断了物理耦合。

引用可用于具名属性、简写和动作数值,例如 motor M rated_voltage=$supply no_load_speed=60rad/s resistance=1ohm。 电动起重机综合题 已使用这种跨领域写法。

参数只属于当前场景,可以在引用后声明,也可以写 let nominal = $supply 作为别名。 重复定义、未知引用和循环引用都会报错。值仅支持有限数字、物理量或另一个参数; 不支持字符串、宏、循环和算术表达式。实际使用处仍检查量纲及范围,质量不能当作透镜焦距。 量纲相同而含义不同的属性仍须具名,不能依靠参数名称猜测物理含义。

$F 明确引用已定义的数值,裸写 F 在支持符号的模型里仍是待求量。 实体名称、引号内的文字和颜色不做参数替换。格式化、分享和源码导出都会保留 let 和 $name。

属性和值的类型

属性名写在 = 左边,运行时语言定义会约束右边可以填写的值。编辑器的校验、自动补全和速记参数解析都读取同一份定义。

值类型接受的内容示例
枚举 enum定义中列出的有限选项state=closed
标识符 identifier对象名称、方向名称或其他可引用名称field=EM、direction=down
物理量 quantity数值和匹配量纲的单位mass=2kg、angle=30deg
物理量或符号 quantity-or-symbol具体物理量,或暂不求值的符号wavelength=500nm、wavelength=lambda
无单位数字 number不带单位的数值amplitude=0.5
文本 text普通标识符或带引号的文字label="main lamp"
任意值 any扩展语句暂未收窄的值通常不需要直接依赖

enum 和 identifier 不同:枚举只接受列出的选项;标识符是开放名称。编辑器可以为标识符提供常用建议,但建议列表不会把它变成枚举。

力学、光学、电路、波、热学流体及现代物理的实体使用同一套领域定义驱动的简写。只有一个待填的简写属性时,输入会直接归给它并进行校验;有多个候选时,编译器根据值类型和物理量纲寻找唯一匹配,因此下面两种写法等价:

lamp L 6V 3W
lamp L 3W 6V

同样的规则也能省去常见模型中重复的属性名:

body block 1kg
pendulum P 0.6m 10deg
lens L converging 10cm
object candle 4cm subject=candle
fluid water 1000kg/m3
reservoir hot 600K

lens L 10cm converging 与上面的透镜定义等价,也可以混用具名属性。 值的先后顺序不决定物理含义;只有语言参考中列出的简写属性参与匹配,并非所有属性都省略名称。

在 Studio 中,将鼠标悬停在属性值上,或把光标放在值内按 F1,可查看其绑定的属性和说明。 例如灯泡的 6V 显示 rated_voltage=6V;$supply 还会显示当前解析出的数值。 按 Escape 关闭说明;编辑源码时旧提示自动关闭。说明读取已有语言定义,不改写源码, 也不会为无效输入猜测属性绑定。

有歧义的量仍然具名:弹簧原长与位移都是长度,导轨长度与间距也都是长度; 静摩擦和动摩擦因数都没有单位。应该写 spring S 16N/m rest_length=1m displacement=0.2m, 不能写 spring S 16N/m 1m 0.2m。name=value 是正常 DSL 写法,不是旧语法兼容层。

展示要求

show 对象名 请求已声明对象的常用展示信息,不改变物理模型,也不会启动动画:

load cargo
rope R

show cargo R

对绳子而言,show R 请求显示张力。课程需要特定结果时,可写 show cargo.displacement 或 show cargo.force_diagram。这些信息来自同一份求解结果,关闭展示不会改变绳长约束或受力关系。不写 show 也会绘制对象本身。

样例中的展示选择统一写成一行,例如 show cargo R。默认详情符合需要时直接写对象名; 只需要部分详情时保留 .feature。默认图示已经满足课程需要时,不必添加 show, 也不要仅为缩短源码而改成 .all。

用 show cargo.all 请求该对象全部可用的详情;多个对象可用空格或逗号分隔,例如 show cargo.all, R.all。只显示当前模型和渲染器支持的内容,不补造缺失结果,也不启动动画。 输入 show cargo. 后,编辑器会提示 cargo.all 和各个单项详情;悬停在选择项上可查看含义。

用颜色突出对象

在实体末尾添加颜色即可改变它的视觉强调,不会改变材料或物理参数:

load cargo 20kg #gold
pulley M #blue
force effort 100N direction=down #red

可用颜色由 语言参考 自动列出。只有需要给绳子的不同线段分别着色时,才需要显式写出具名绳路。

写得更短,物理含义不变

场的类型和强度可以省去属性名:

field B magnetic 1T direction=into_page
field E electric 200V/m direction=right

1T 按单位映射到 magnetic_strength,200V/m 映射到 electric_strength。 类型和物理量可以交换顺序,也可以继续写完整的 name=value。

声明可以直接带上常用的 on 关系:

force pull 1N direction=right on bar
body crate 1kg on ramp

这些是片段,需要在同一场景中声明 bar 和 ramp。第一句等价于 force pull 1N direction=right 加上 pull on bar。 实体属性放在 on 前,作用位置等关系参数(如 position=1cm)放在目标后。

其他关系写成独立的结构行或具名物理模型:

body ball 1kg
launch flight body=ball origin=ground speed=20m/s angle=45deg

object candle 4cm
imaging view object=candle optic=L object_distance=30cm

还需在同一场景中声明 ground 和光学元件 L。flight、view 是模型名称, 不能与实体或其他模型重名。body、origin、object、optic 等参与者角色名 由各模型的语言定义规定。已声明物体和透镜时,也可用 candle -> L object_distance=30cm 表达成像关系。 滚动使用具名 rolling 模型,trajectory 的重复阶段写成 stages=(ramp, floor, S)。完整模型见模型配方。

统一的动画写法

所有动画都使用 animate。duration 表示实验运行多久,speed 表示播放倍速:

animate duration=3s speed=0.5

这表示实验运行 3 秒,以 0.5 倍速观看,屏幕播放 6 秒。speed=1 是正常速度, speed=2 是两倍速;省略时默认为 1。倍速不改变轨迹、受力或实验读数。

无目标的时间区间适用于直线运动、小角度摆、弹簧振子、导体棒综合案例、 电动提升和叠块装置。一个连通系统只写一条区间动画,各物体共享同一物理时钟。

如果想看“滑到 1 米为止”,不需要事先知道要多久:

scene incline_arrival
surface ramp incline 12deg smooth
body crate 1kg on ramp
animate crate until crate.displacement == 1m speed=1
show crate.motion crate.forces

until 表示首次满足条件就结束。这一例从静止开始,重力决定加速度,约 0.99 秒后到达; speed=0.5 只把观看速度减半。位移相对初始位置计算,沿斜面向下为正,向上为负。 0m 在起点已满足,因此保持静态;静摩擦阻止运动或方向不对时会报错。 目前此条件支持斜面上的单个滑动或滚动物体(包括纯滚动和滑移滚动);滚动终点暂只支持顺坡方向。 水平直线运动可用 animate car until car.displacement == 40m speed=1;位移相对初始 x,向右为正。若物体折返,动画在首次到达时结束;达不到的终点会报错。双物体共用同一时钟,例如 animate A until A.displacement == 60m speed=1 会同时观察 A、B 到 A 首次移动 60 米;不写 until 的 animate A 仍在相遇时结束。 固定轴转动可用 animate wheel until wheel.turn == 360deg speed=1 表示累计转过一圈;turn 不是圆盘朝向,转动方向和到达时间由力矩决定。 小角单摆从静止释放时,可用 animate P until P.angle == 8deg speed=1 观察首次到达 8°。 这里的角度是相对竖直向下的绝对角度,向右为正,终值必须在起始振幅内;animate P speed=1 仍表示观察完整自然周期。 无阻尼自由弹簧振子可用 animate weight until weight.offset == 0m speed=1, 首次到达平衡位置时结束,历时四分之一个周期。offset 是相对平衡位置的有符号距离, 向下为正,不是相对起点的 displacement。目前只支持单弹簧、无阻尼、无外力且无刚度调制的情形。 光电效应可用 animate electron until electron.displacement == 10nm 指定电子逸出后的观察距离;光子到达材料的时间也计入动画。0nm 表示不播放动画。未列出的模型暂不支持。 输入 until 后编辑器会提示可用物理量和单位;终值也可引用 $参数。 until 和 duration 二选一,条件后只写可选的 speed,不能再指定运动轨迹。 删除动画语句,物体仍处于相同的初始位置。

也可以指定对象,观察模型已有的事件或周期,或给出一个支持的参数终值:

animate P speed=0.5
animate candle object_distance=15cm duration=3s speed=1
animate R.free distance=1m duration=2s speed=1

以上是三个独立示例:分别观察摆的一个周期、改变物距、规定绳端运动。 不写 duration 时,模型决定结束时刻,例如落地、相遇或一个周期。相遇本身不代表碰撞。 若模型已经决定事件时长,显式时长必须与之相符,不能强迫物体提前落地; 要改变观看节奏,只改 speed。

弹簧由阻尼、外力和刚度调制决定响应;周期外力目前使用稳态响应,不含启动瞬态。 变刚度振子没有保证的周期终点,需要 animate duration=3s speed=1 指定观察区间。 自由、阻尼和受迫弹簧振子相对平衡位置的读数跟随模型轨迹,不做线性估算。

场线、电流、波形和能量账本也使用同一个命令和倍速。静态场线与直流电流点是示意进度, 不是粒子运动,不接受物理 duration;speed=1 使用默认的演示节奏。波和交流相位保留 频率决定的真实周期,因此高速现象可能需要很小的倍速,如 speed=1e-8。 热机账本沿已声明的时序展示能量收支,不是热力学路径仿真。

旧稿的动作和 playback 暂时兼容;新内容统一使用 animate 与 speed。

何时指定布局

默认先让布局器寻找清楚且不重叠的位置。只有题目确实依赖特定构图时,再添加布局提示。布局提示应该表达相对关系,例如“在右侧”或“保持竖直”,而不是依赖某个屏幕尺寸的绝对像素。

这条边界很重要:模型说物理事实,布局说怎样看清这些事实。

要看不同物理领域如何复用这套结构,可以继续阅读 常用模型写法。