输入文件生成(命令行模式)

简介

PASS 采用 JSON 文件 作为仿真输入。引擎( ConfigBeamCommandSequence )从 JSON 文件读取全部参数,包括粒子种类、束团分布、Lattice序列、监测器等。

参数系统 PASS/para/ 提供了一套基于 pydantic v2 的 schema 定义,用户通过 Python 脚本组装参数对象,调用 generate_input() 即可输出引擎兼容的 JSON 文件。这种方式相比手写 JSON 有以下优势:

  • 类型安全 :参数类型、范围在 schema 中声明,非法值在生成时即被拦截;

  • 别名映射 :Python 代码使用简洁属性名(如 circumference ),JSON 输出自动使用引擎期望的 key(如 "Circumference (m)" );

  • 可复用 :schema 对象可 model_copy(update={...}) 快速派生变体,适合参数扫描;

  • GUI 可扩展 :schema 自带 JSON Schema 导出,未来 GUI 可自动渲染表单。

Note

本文档介绍命令行模式下的输入文件生成方式。GUI 模式将在未来版本中提供。

架构概览

参数系统分为五层,各层职责清晰、互不依赖:

PASS/para/
├── schema/       参数定义(唯一数据源)
│   ├── main.py         MainConfig:全局仿真参数
│   ├── bunch.py        BunchConfig + OffsetConfig + InjectionItem
│   ├── twiss.py        TwissPoint:twiss 传输点
│   ├── elements.py     12 种元件(Drift→RFCavity)
│   ├── monitors.py     StatMonitor / DistMonitor / PhaseMonitor
│   ├── space_charge.py SpaceChargeConfig
│   └── sequence.py     Sequence:有序容器 + 自动排序
├── readers/      外部格式 → schema 对象
│   ├── madx_twiss.py   MADX twiss TFS → TwissPoint 列表
│   ├── madx_element.py MADX twiss TFS → Element 列表
│   ├── madx_error.py   MADX error TFS → 场误差
│   └── smooth_approx.py 解析平滑近似 twiss
├── writers/      schema → 输出
│   └── json_writer.py  schema → 引擎兼容 JSON
├── tools/        外部数据 → PASS TFS
│   ├── data_converter.py 通用数据转换流水线
│   ├── ramping.py         元件 ramping 文件生成
│   ├── rf_data.py         RF 数据文件生成
│   └── exciter_data.py    Exciter 数据文件生成
├── toolkit.py    sort_sequence + class_map
└── api.py        高级 API

数据流如下:

MADX TFS / 用户参数 / 外部数据文件
           │
           ▼
     readers/ + tools/        → schema 对象 / TFS 文件
           │
           ▼
      schema/ (pydantic)     ← 唯一数据源:验证 + 别名
           │
           ▼
     writers/json_writer     → beam0.json
           │
           ▼
      PASS 引擎 (Config → Beam → CommandSequence → Executor)

快速开始

最简示例

以下脚本生成一个包含注入 + 平滑近似 twiss + 统计监测器的完整输入文件:

from PASS.para.api import generate_input
from PASS.para.schema.main import MainConfig
from PASS.para.schema.bunch import BunchConfig, InjectionItem
from PASS.para.schema.sequence import Sequence
from PASS.para.schema.monitors import StatMonitor
from PASS.para.readers.smooth_approx import generate_smooth_twiss

# 1. 全局参数
main = MainConfig(
    beam_name="proton",
    num_proton=1, num_neutron=0, num_electron=1,
    gamma_t=4.8, circumference=251.327,
    num_turns=1000, backend="cpu",
)

# 2. 束团
bunch = BunchConfig(
    kinetic_energy=45e6,
    num_real_particles=int(1e11),
    num_macro_particles=int(1e5),
    beta_x=0.5, beta_y=0.5,
    alpha_x=-2.61, alpha_y=1.57,
    emit_x=200e-6, emit_y=100e-6,
    sigma_z=30, dp=0.005,
    dist_trans="gaussian", dist_longi="matchz",
    rf_voltage=100e3, rf_phase=0.5236,
)

# 3. Lattice序列
items, circum = generate_smooth_twiss(
    circumference=main.circumference,
    qx=4.8, qy=4.4, num_points=100,
)
main.circumference = circum

seq = Sequence()
seq.add("injection", InjectionItem(s=0.0, bunches=[bunch]))
for i, item in enumerate(items):
    seq.add(f"twiss_{i:04d}", item)
seq.add("stat1", StatMonitor(s=0.0))

# 4. 生成 JSON
generate_input(main, seq, "beam0.json")

运行方式:

cd C:\Users\changmx\Documents\PASS
python input/generate_beam0.py

输出文件: input/beam0.json

JSON 文件结构

生成的 JSON 文件结构如下:

{
    "Beam Name": "proton",
    "Number of Protons": 1,
    "Number of Neutrons": 0,
    "Number of Charges": 1,
    "Transition Gamma": 4.8,
    "Circumference (m)": 251.327,
    "Number of turns": 1000,
    "Backend (gpu/cpu)": "cpu",
    "Number of GPU devices": 1,
    "Device Id": [0],
    "Output directory": "./output",
    "Is plot figure": true,
    "Is space charge": false,
    "Is beam-beam": false,
    "Sequence": {
        "injection": {
            "S (m)": 0.0,
            "Command": "Injection",
            "bunch0": {}
        },
        "twiss_0000": {
            "S (m)": 0.0,
            "Command": "Twiss",
            "S previous (m)": 0.0,
            "Beta x (m)": 8.333
        },
        "stat1": {
            "S (m)": 0.0,
            "Command": "StatMonitor"
        }
    }
}

Note

JSON 的 key 名称是引擎的硬性契约。schema 层通过 pydantic 的 alias 机制自动处理 Python 属性名到 JSON key 的映射,用户无需手写。

引擎在读取时会先调用 convert_keys_to_lower() 将所有 key 转为小写,因此 JSON key 的大小写不影响读取。

核心组件

MainConfig(全局参数)

属性名

JSON key

类型

说明

beam_name

Beam Name

str

束流标签

num_proton

Number of Protons

int

每粒子质子数(0 表示电子/正电子)

num_neutron

Number of Neutrons

int

每粒子中子数(>0 表示离子)

num_electron

Number of Charges

int

每粒子电荷数(可负,不可为 0)

gamma_t

Transition Gamma

float

过渡 gamma

circumference

Circumference (m)

float

环周长 (m)

num_turns

Number of turns

int

仿真圈数

backend

Backend (gpu/cpu)

str

计算后端: cpugpu

num_gpu

Number of GPU devices

int

GPU 数量

gpu_id

Device Id

list[int]

GPU 设备 ID 列表

output_dir

Output directory

str

输出目录

is_plot

Is plot figure

bool

是否生成图表

is_space_charge

Is space charge

bool

是否启用空间电荷

is_beambeam

Is beam-beam

bool

是否启用束流-束流相互作用

BunchConfig(束团参数)

属性名

JSON key

类型

说明

kinetic_energy

Kinetic Energy per Nucleon (eV/u)

float

每核子动能 (eV/u)

num_real_particles

Number of Real Particles

int

每束团真实粒子数

num_macro_particles

Number of Macro Particles

int

每束团宏粒子数

beta_x / beta_y

Beta x (m) / Beta y (m)

float

Twiss β 函数

alpha_x / alpha_y

Alpha x / Alpha y

float

Twiss α 函数

emit_x / emit_y

Emittance x (m'rad)

float

发射度

sigma_z

Sigma z (m)

float

束团长度

dp

Sigma dp/p

float

动量展宽

dist_trans

Transverse dist

str

横向分布: kv / gaussian / uniform / waterbag / parabolic

dist_longi

Longitudinal dist

str

纵向分布: gaussian / coasting / matchz / matchdp

rf_voltage

RF Voltage (V)

float

RF 电压(matchz/matchdp 模式使用)

rf_phase

RF Phase (rad)

float

RF 相位

Sequence(序列容器)

Sequence 是一个有序容器,存储所有按位置 s 排列的序列项。添加顺序不影响最终结果——导出时自动按 (s, command priority) 排序。

seq = Sequence()
seq.add("injection", InjectionItem(s=0.0, bunches=[bunch]))
seq.add("qd1", QuadrupoleElement(s=1.0, k1l=0.2, length=0.5))
seq.add("stat1", StatMonitor(s=0.0))

支持的序列项类型:

  • InjectionItem — 注入点(必须 s=0

  • TwissPoint — twiss 传输点

  • DriftElementQuadrupoleElementSBendElement 等 — 物理元件

  • StatMonitorDistMonitorPhaseMonitor — 监测器

Lattice来源

PASS 支持三种Lattice序列生成方式,可根据需要选择或混合使用:

方式一:从 MADX twiss 文件读取

读取 MADX 生成的 twiss TFS 文件,每个元件转为一个 TwissPoint 传输点。适用于 逐 twiss 传输 模式。

from PASS.para.readers.madx_twiss import read_madx_twiss

items, circum = read_madx_twiss(
    twiss_file="lattice.tfs",
    error_file="errors.tfs",       # 可选
    muz=0.001,                      # 纵向 tune
    dqx=0.0,                        # 色品(或 "from_file")
    dqy=0.0,
    is_field_error=False,           # 是否读取场误差
    insert_patterns=["QD.*"],      # 正则匹配,插入为薄透镜元件
)

方式二:从 MADX twiss 文件读取为元件

读取 twiss 文件,但每个元件转为对应的物理元件对象( QuadrupoleElementSBendElement 等)。适用于 逐元件追踪 模式。

from PASS.para.readers.madx_element import read_madx_elements

items, circum = read_madx_elements(
    twiss_file="lattice.tfs",
    is_merge_drift=True,            # 合并相邻漂移节
    is_field_error=True,
    error_file="errors.tfs",
)

方式三:平滑近似 twiss

无需 MADX 文件,用解析公式生成恒定 β 函数的 twiss 点。 \(\beta = C / (2\pi Q)\) 。适用于快速测试。

from PASS.para.readers.smooth_approx import generate_smooth_twiss

items, circum = generate_smooth_twiss(
    circumference=569.1,
    qx=9.47, qy=9.43,
    num_points=100,
    muz=0.001,
)

混合模式

twiss 传输点和物理元件可以在同一个序列中混合使用。例如在 twiss 序列中插入一个 RF 腔:

from PASS.para.schema.elements import RFCavityElement

seq = Sequence()
seq.add("injection", InjectionItem(s=0.0, bunches=[bunch]))

# twiss 传输点
for i, item in enumerate(twiss_items):
    seq.add(f"twiss_{i:04d}", item)

# 插入 RF 腔(在 s=0 处)
seq.add("rf1", RFCavityElement(s=0.0, voltage=100e3, harmonic=1, phase=0.5236))

外部数据文件转换

PASS 使用 TFS 格式 作为所有 ramping/RF/exciter 数据文件的统一格式。 tools/data_converter.py 提供了通用转换流水线,将各种外部文件(CSV/TXT/TFS)转为 PASS TFS。

四步流水线

外部文件 → load_raw_data → time_to_turn → interpolate → write_tfs
  1. load_raw_data :读取外部文件,自动检测 turn/time 列

  2. time_to_turn :如外部文件给的是时间而非圈数,用回旋频率转换

  3. interpolate_to_continuous_turns :圈数不连续时自动插值

  4. write_tfs_ramping :写入 PASS 统一 TFS 格式

一步到位

from PASS.para.tools.data_converter import convert_external_to_tfs

convert_external_to_tfs(
    input_path="external_ramp.csv",     # 外部文件
    output_path="k1l_ramping.tfs",      # PASS TFS
    data_cols=["k1l", "k1sl"],          # 数据列名
    revolution_freq=1.76e6,             # 回旋频率 (Hz)
    num_turns=5000,                     # 目标圈数
    method="linear",                    # 插值方法
)

预置封装

针对常见元件类型的薄封装:

from PASS.para.tools.ramping import convert_k1l_ramping, convert_k2l_ramping
from PASS.para.tools.rf_data import convert_rf_data

# 四极铁 ramping
convert_k1l_ramping("external.csv", "k1l_ramping.tfs", revolution_freq=1.76e6)

# RF 数据
convert_rf_data("llrf.csv", "rf_data.tfs", revolution_freq=1.76e6)

分步调用

外部文件格式特殊时,可分步调用各函数:

from PASS.para.tools.data_converter import (
    interpolate_to_continuous_turns, write_tfs_ramping,
)
import numpy as np

# 自行准备数据
turn_arr = np.array([1, 50, 100, 500, 1000])
k2l = np.array([0.0, 0.5, 1.0, 2.5, 4.4])

turn_cont, data_cont = interpolate_to_continuous_turns(
    turn_arr, {"K2L": k2l},
    start_turn=1, end_turn=1000, method="linear",
)
write_tfs_ramping("k2l_ramping.tfs", turn_cont, None, data_cont)

API 参考

from PASS.para.api import generate_input, load_input

# 生成 JSON
generate_input(
    main: MainConfig,
    sequence: Sequence,
    output_path: str,
    space_charge: SpaceChargeConfig | None = None,
    extra_modules: dict | None = None,
) -> str

# 加载已有 JSON(用于修改后重新生成)
main, seq_dict = load_input("beam0.json")

完整示例

项目内置的示例脚本位于 input/generate_beam0.py ,可直接运行:

cd C:\Users\changmx\Documents\PASS
python input/generate_beam0.py

该脚本演示了完整的端到端流程:全局参数 → 多束团配置 → 平滑近似 twiss → Lattice 序列组装 → JSON 输出。生成的 beam0.json 可直接被 PASS 引擎读取执行。