贡献指南¶
TensorMesh 规模不大,一个有的放矢的补丁就足以带来切实改变。本页介绍实际的工作流程:搭建开发环境、运行测试、构建文档,以及提交 PR。
如果您有想法但不确定它该归在何处,可在 GitHub Discussions(Ideas & RFCs 类别)中发帖,或在 Discord 上留言。对于已确认的缺陷和具体的功能请求,issue 跟踪器才是合适的入口——参见 GitHub Issues。
环境搭建¶
环境要求:
Python ≥ 3.10
PyTorch ≥ 2.0(若要运行 GPU 路径,则需带 CUDA)
其余所有依赖都可在下面的步骤中从 PyPI 安装——包括 torch-sla(>= 0.2.1),这是提供全部稀疏求解器后端的硬性依赖。无需 C++ 工具链或手动构建步骤。
克隆并以可编辑模式安装:
git clone https://github.com/camlab-ethz/TensorMesh.git
cd TensorMesh
pip install -e ".[test]"
可选附加项:cupy / cudss(GPU 稀疏直接求解器后端)、gpu(同时安装两者),以及 example(部分绘图脚本所需的 Plotly)。
运行随附的检查脚本对安装进行冒烟测试,它会在 CPU 上(以及在可用时在 GPU 上)求解一个极小的泊松方程问题,并报告哪些稀疏求解器后端已就绪:
python -m tensormesh.verify_install
如果 CPU 和 CUDA 两种求解相对于解析参考解都打印出合理的误差,那就说明一切正常。
运行测试¶
测试位于 tests/ 目录下,其结构与包的布局相对应(tests/element/、tests/sparse/、tests/ode/ 等)。它们使用原生 pytest:
pytest tests/ # full suite
pytest tests/sparse/test_spsolve.py -v # one file
pytest tests/element/test_basis.py::test_triangle_basis -v # one test
pytest tests/ --cov=tensormesh # coverage report
在编写新测试之前,有几条值得了解的约定:
新测试中默认使用 ``float64`` 和 ``cpu``;当您所测试的代码路径涉及设备/数据类型的处理时,请添加由
@pytest.mark.skipif(not torch.cuda.is_available())保护的 GPU 变体测试。避免在装配器的 ``forward()`` 方法内部使用 NumPy。 装配器在
torch.vmap下运行,而它与 NumPy 数组存在不会报错的隐性不兼容——请始终使用 torch。测试的命名应反映其所测试的内容,而非文件名。在不同测试文件中重复的函数名虽然能正常运行,却会使
pytest -k过滤变得混乱。
构建文档¶
文档使用 Sphinx 配合 pydata_sphinx_theme 主题。在本地构建:
cd docs
make html
渲染输出会生成到 docs/_build/html/;打开 docs/_build/html/index.html 即可查看。目前即使是干净的构建也会产生少量已存在的警告——example_gallery/wave.rst 中一个过时的 ExplicitRungeKutta 交叉引用,外加几处 NumPy 风格的文档字符串格式警告——因此实际的规则很简单:不要新增警告,而修复已有的警告则始终受欢迎。
本站点通过 Sphinx 的 gettext 工作流实现中英双语。权威的英文源是 .rst 文件;中文字符串位于 docs/source/locale/zh_CN/ 下的 .po 文件中。在编辑英文文本后,重新生成 .po 文件:
make gettext # extract strings
sphinx-intl update -p _build/gettext -l zh_CN # merge into .po
构建中文站点,或同时构建两个站点:
make zh # Chinese build only
make html-all # both EN and ZH
如果您的 PR 仅改动英文文本,可以不去动 .po 文件——维护者会批量处理国际化更新。
代码风格¶
目前 CI 中没有强制执行的自动格式化工具或代码检查工具,因此实际的规则是与您正在编辑的文件保持一致。具体而言,这意味着:
采用 4 个空格缩进,遵循 PEP 8 的精神,行长约为 88 至 100 个字符。
NumPy 风格的文档字符串,依次为 Summary → Parameters → Returns → Notes → Examples(按此顺序)。鼓励但不强制使用类型注解;如果您添加注解,请优先使用
torch.Tensor而非泛型的Any。对于与
nn.Module兼容的张量集合,请使用已有的 ``BufferDict`` / ``BufferList`` 容器(tensormesh.nn)。在跨越nn.Module边界时,不要自行使用普通的张量dict。请让
forward()方法保持为纯张量代码——不要基于张量值进行 Python 控制流操作,不要使用 NumPy,除非结果用于打印/日志,否则不要调用.item()。
提交拉取请求¶
具体操作流程:
从 ``main`` 派生并创建分支。 分支命名不拘形式;
feat/<short>/fix/<short>/docs/<short>与提交信息的风格相匹配。编写测试。 改动数值代码却没有相应测试的 PR 不太可能被合并。CPU +
float64是最低要求;如果所改动的代码会根据设备分支,请添加一个 GPU 变体测试。在本地运行相关测试并构建一次文档;两者都应没有问题。
提交 PR,用
Fixes #NN关联对应 issue(部分修复则用Refs #NN),并在正文中说明为什么这样做——而不仅仅是做了什么,因为后者已由 diff 体现。提交信息风格沿用项目其余部分的约定:
<type>(<scope>): <imperative summary>,例如fix(ode): propagate u0.dtype/device through step()。使用中的类型有:feat、fix、docs、test、refactor、perf、ci。
评审者会关注的要点:
覆盖您所改动路径的测试,并在适用时包含修复前的失败情形。
如果您改动了文档字符串或
.rst文件,不应引入新的 Sphinx 警告。不应出现意外的向后不兼容——如果某个公共符号被重命名或移除,PR 描述中应明确指出这一点。
数值方面的改动(新增单元、新增数值积分、新增求解器)应至少包含一项对照解析参考解的检验。
这是一个小规模的维护团队;响应时间为尽力而为。如果某个 PR 沉寂了一两周以上,欢迎在 Discord 的 #dev 频道礼貌地提醒一下。
签署声明与开发者原创证书(DCO)¶
进入 main 的每一次提交都必须依据 开发者原创证书(DCO)进行签署声明——这与 Linux 内核、PyTorch、vLLM 以及大多数采用 Apache 许可的项目所使用的轻量级贡献政策相同。完整文本位于代码仓库根目录的 DCO 文件中;其要点是,您声明这些代码是您有权贡献的(或来自一个许可正当的来源),并且您是在本项目的 Apache 2.0 许可下提交它的。
操作非常简单——向 git commit 传入 -s,Git 就会自动为您追加该行:
git commit -s -m "fix(ode): propagate dtype through step()"
从而生成如下形式的尾注(trailer):
Signed-off-by: Your Name <your@email>
请使用您的真实法定姓名和一个您能掌控的电子邮箱。如果某个拉取请求的提交缺少有效的 Signed-off-by 尾注,它将不会被合并。
如果您在已推送的提交上忘记了签署声明:
# for the latest commit only
git commit --amend -s --no-edit
git push --force-with-lease
# for an older commit, or the whole branch
git rebase --signoff main
git push --force-with-lease
维护者无法代您签署——签署声明是贡献者自身的证明。
项目结构¶
为新贡献者提供的一份各部分位置的大致地图:
路径 |
内容 |
|---|---|
|
|
|
单元类型( |
|
|
|
|
|
|
|
时间积分方案——显式/隐式线性欧拉法、中点法、龙格-库塔基类。 |
|
面向有限元方法的张量工具(Voigt 记法、梯度)。 |
|
批量网格生成,以及用于机器学习训练数据的 |
|
|
|
测试套件,其结构与包的布局相对应。 |
|
端到端的完整示例。 |
|
Sphinx 源文件、构建配置和翻译文件。 |
拿不准时,请用 grep 搜索附近的某个符号——本包规模不大,rg <SymbolName> tensormesh/ 通常就能把您引到正确的位置附近。