清华园的盛夏,阳光热烈,蝉鸣聒噪,空气里浮动着栀子花甜腻的香气。但对于“学术新星”们而言,季节的更迭与校园的闲适仿佛已是另一个世界。他们如同投入深海的潜水者,在各自导师课题组的特定“海域”中,开始了真正的、高浓度的探索。
许源在天体物理中心的日子,被数据和代码精确地切割。
他面对的,首先是天书般的二进制数据文件。陈教授课题组多年积累的广义相对论磁流体力学(GRMHD)模拟输出,包含数十个物理变量(密度、压力、速度、磁场分量、熵等)在三维网格和数十万时间步上的海量信息。
这些文件没有直观的扩展名,内部格式特殊。杨博士给他的第一个“下马威”,就是学会用课题组内部封装好的 Python 脚本库来读取它们。
最初的几天,许源几乎是在不断的“报错-查文档-调试-再报错”循环中度过的。环境变量没设对,依赖库版本冲突,文件路径有空格,内存溢出……每一个细小的问题都足以让他卡壳数小时。
公共区域的其他师兄师姐似乎对此习以为常,偶尔有学姐看到他对着满屏红色错误信息发愣,会走过来瞥一眼,给出简洁的指点:“这里,脚本需要指定数据块的大小,你参数给错了。” 或者,“试试用 h5dump 命令先看看这个文件的内部结构。”
他逐渐明白,科研中的“编程”与课程作业截然不同。
没有现成的题目和明确的要求,你需要自己理解数据的组织结构,明确想要提取什么信息,然后编写脚本来实现。他花了一天时间,终于成功读取了一个小规模模拟的密度场数据,并将其投影为二维图像。当屏幕上第一次显示出那个熟悉而又陌生的、围绕中心致密天体的、扁平的吸积盘结构时,尽管图像粗糙,分辨率低下,许源的心头还是涌起一阵难以言喻的激动——这是“真实的”模拟数据,来自前沿的研究,而非教科书上的示意图。
然而,这仅仅是第一步。杨博士给他的任务是“做基本的可视化,并计算一些全局量”。
绘制密度温度分布图还算简单,但要计算“吸积率”(物质落入中心天体的速率)和“喷流功率”(从两极区域输出的能量流),就需要理解这些物理量在模拟数据中是如何定义的,涉及到对速度场、磁场、能量密度等变量的复杂组合和积分。他需要查阅模拟代码的文档,理解其数值格式和单位制,确保自己的计算与模拟内部保持一致。
这个过程,让他深刻体会到理论与数值实践之间的鸿沟。课本上简洁的公式,在离散化的网格和有限精度的数值解面前,变得复杂而微妙。他必须小心翼翼地处理边界条件,注意守恒性,验证结果的量级是否合理。
一次,他计算出的吸积率比文献中类似模型的结果高了好几个数量级,百思不得其解。最后是杨博士在检查他的脚本时发现,他错误地将模拟中采用的“几何单位制”(G=c=1)下的结果,直接当成了国际单位制下的数值。
挫折是家常便饭。
但每解决一个问题,他对整个模拟流程的理解就更深一层。他开始能看懂那些贴在墙上的、复杂的演化曲线图大致代表什么,能在组会听到师兄师姐讨论“磁旋转不稳定性(MRI)的饱和水平”或“喷流的准直机制”时,脑海中浮现出相应的数据图像。
除了数据处理,杨博士给的“Bondi 吸积”简化模拟任务,则是另一场硬仗。这是纯牛顿引力下的球对称气体吸积,忽略磁场、角动量、辐射等所有复杂因素,是吸积物理中最简单的玩具模型。但即使如此,要自己从头用有限体积法实现一维球坐标下的流体力学方程组(连续性、动量、能量方程),并稳定求解,对大一学生而言依然是巨大的挑战。
许源翻出了《计算物理》教材中关于流体模拟的章节,查阅了关于“黎曼求解器”、“通量限制器”、“CFL条件”的详细资料。他决定采用最简单的 Lax-Friedrichs 格式。编写代码,设置初始条件(均匀静态的冷气体云),边界条件(内边界为吸收边界,外边界固定),然后运行。
第一次运行,程序在几步之内就因数值爆炸而崩溃。他检查了时间步长,确保满足 CFL 条件。
第二次,程序能跑,但结果完全不对,密度在中心奇点处没有如预期那样升高,反而变得混乱。他怀疑是边界条件处理有误,或者通量计算出了问题。他加入了详细的输出,一步步追踪每一个网格点的物理量变化。连续几天,他宿舍的灯光都亮到深夜,草稿纸上写满了对离散格式的推导和验证。
就在他几乎要放弃,准备向杨博士承认失败时,在一次仔细检查中,他发现了一个极其隐蔽的错误:在计算球坐标下的面积因子时,他把半径的平方误写成了半径。这个微小的错误,导致通量计算完全错误。修正之后,再次运行。屏幕上,代表密度的曲线,终于开始随着时间的推移,在中心点附近稳定地堆积、升高,形成了 Bondi 吸积流的经典轮廓。
那一刻的成就感,几乎不亚于他得知通过“学术新星”初审。虽然只是一个简化到极致的模型,但这是他自己从物理方程出发,推导离散格式,编写代码,调试运行,最终得到了符合理论预期的结果。他第一次真切地触摸到了“用计算探索物理”的脉搏。
与此同时,徐嘉庆在计算物理与复杂系统实验室的“潜水”,则进入了另一个维度的深海。
张老师给的第一个任务——系统学习 PyTorch 和 PyG,并复现经典模型——听起来很“学习”,实则充满陷阱。
PyTorch 的动态计算图和自动求导机制虽然强大灵活,但对他这样习惯了编写严格过程式代码的人来说,需要转变思维。理解张量操作、神经网络模块的搭建、损失函数和优化器的使用,是基础。更复杂的是理解 PyG 中“图”这种数据结构如何表示分子,以及“消息传递”这种计算范式如何运作。
他选择了 SchNet 这个相对经典、结构清晰的图神经网络模型作为切入点。下载代码,配置环境,准备数据(QM9 数据集,包含约 13 万个小分子的几何结构和多种量子化学性质)。第一步,让代码跑起来,在训练集上开始迭代。然而,损失函数下降缓慢,验证集上的表现远低于论文报告的水平。
是过拟合?欠拟合?学习率不合适?模型架构不对?还是数据预处理出了问题?徐嘉庆没有盲目调参,而是开始系统地排查。
他仔细阅读了 SchNet 的原论文,理解了其设计的核心思想:用连续的滤波卷积来学习原子间的相互作用,用原子距离的高斯展开作为边特征。他检查了数据加载部分,确保原子类型、坐标、距离矩阵等输入正确无误。他对比了不同批次大小、学习率、优化器(Adam vs. SGD)的影响。他甚至写了一个简单的脚本,可视化训练过程中损失和精度的变化曲线。
在反复尝试和与王瀚师兄讨论后,他发现了一个关键问题:原论文在预处理分子坐标时,对距离进行了一个特定的截断和缩放,而他在复现时忽略了这个细节,导致输入特征分布异常。修正之后,模型的训练曲线立刻变得“健康”了许多,验证集上的精度也开始向论文报告值靠拢。
复现成功,仅仅是开始。
接下来是 DimeNet,一个更复杂、引入了方向性信息的模型。然后是 GemNet,进一步考虑了更高阶的相互作用。每一个模型,都有其独特的架构设计和技巧。
徐嘉庆不仅要让代码运行,更要理解其背后的动机:为什么在这里引入距离和角度的嵌入?这种注意力机制是如何捕捉不同原子对之间相互作用的相对重要性的?这些设计,如何与物理化学中的概念(如键长、键角、空间位阻)相对应?
他将这些理解,整理成详细的笔记,绘制出每个模型的架构图,标注出关键模块和数据流的走向。这个过程枯燥而烧脑,但就像拼图一样,随着一块块碎片的归位,一幅关于“如何用机器学习表示分子并预测其性质”的完整图景,在他脑海中逐渐清晰起来。
参加每周的组会,则是另一种维度的“沉浸式”学习。
第一次参加时,徐嘉庆几乎完全听不懂。师兄师姐们汇报的内容,涉及复杂的自由能计算方法、稀有事件采样算法、蛋白质折叠路径分析、新型力场在材料界面中的应用……满屏幕的公式、算法流程图、和令人眼花缭乱的各类图表。但他强迫自己集中注意力,努力抓住报告的核心问题:他们想解决什么科学难题?用了什么方法?得到了什么结果?还存在什么困难?
他注意到,即使是最资深的博士生,在报告时也会被张老师和其他组员尖锐地提问:“你这个收敛性判据是否充分?”“控制实验是怎么设计的?”“有没有考虑过另一种可能的机制?”“这个性能提升,是来自模型改进,还是只是调参的结果?”
这些问题,直指科研工作的核心:严谨性、可重复性、逻辑的自洽性。没有想当然,每一步都需要论证。这与他平时在课程学习中追求“得到正确答案”的思维模式截然不同。在这里,“答案”往往不是唯一的,甚至不是最重要的;重要的是你如何提出问题,如何设计实验(或计算)去验证或否定它,以及如何解释你的结果。
几次组会下来,徐嘉庆开始能跟上一些技术性不那么强的讨论,也能从师兄师姐们的报告中,窥见这个领域真正的前沿挑战是什么——比如,如何提高机器学习力场在远离训练数据区域(外推)的可靠性?如何有效地对高维自由能面进行采样,以研究那些发生概率极低但对功能至关重要的构象变化?如何将物理先验知识(如对称性、守恒律)更自然地融入到深度学习模型中?
这些宏观的问题,与他正在复现的那些具体模型,开始产生关联。他意识到,自己复现的不仅仅是代码,更是这个领域为解决这些根本挑战所走过的、具体的、技术性的足迹。
夜晚,回到集训营的宿舍,往往是两人一天中唯一能长时间交流的时刻。
灯光下,他们各自对着电脑,有时是继续白天未完成的工作,有时则是整理笔记,阅读相关文献。空气里弥漫着疲惫,但更浓的是一种全神贯注后的沉静。
“今天又被一个单位制坑了。”许源揉着发酸的眼睛,对徐嘉庆吐槽,“模拟里用的自然单位制,我自己算的时候混进去了国际单位,结果差了好多。”
“正常。”徐嘉庆头也不抬,手指在键盘上飞快地敲击,调试一段损失函数,“我刚把 DimeNet 的精度调到了论文的 95%,发现是数据增强策略没完全复现。”
“你们组会都讲些什么?听着很高深。”许源好奇。
“今天王瀚师兄讲了他用强化学习做增强采样的新思路,在几个模型蛋白上效果不错,但计算量巨大。”徐嘉庆简略总结,“张老师问了他很多关于探索-利用平衡和奖励函数设计的问题。感觉强化学习在这块很有潜力,但可解释性和稳定性还是大问题。”
“我们组下周要报 Bondi 吸积的结果,杨师兄说让我试试加个角动量,看看会不会形成盘。”许源说,语气里带着一丝挑战的兴奋。
“加角动量?那方程要变,还得处理旋转带来的离心力项和可能的激波。”徐嘉庆终于从代码中抬起头,看向许源,“数值格式可能要调整,Lax-Friedrichs 可能不够了。”
“嗯,我知道。打算先看看文献,有没有现成的解法器参考。”许源点头。他们之间的对话,越来越像两个初级研究者在交流技术细节,分享遇到的困难和可能的思路。那些属于恋人的温存私语,在繁重的科研任务面前,被压缩到了最短的间隙——比如递一杯水时指尖的短暂触碰,比如深夜同去食堂吃夜宵时并肩而行的沉默陪伴,又比如在对方终于解决一个棘手问题后,交换的那个带着疲惫笑意的眼神。
日子就在这种高强度的、近乎单调的“学习-实践-调试-讨论”循环中飞速流逝。他们像两块被投入不同熔炉的生铁,承受着高温和锻打。挫折是日常,进步是阶梯,而前方那隐约显现的、关于各自领域更深处的奥秘,则是驱动他们不断向前的、最原始也最强大的动力。
窗外的蝉鸣依旧,盛夏正浓。而两个年轻探索者的科研初航,在数据、代码、公式和无数个深夜灯光的陪伴下,正平稳而坚定地,驶向未知的深海。
进入七月中旬,清华园的暑气达到顶峰,烈日炙烤着红墙绿瓦,连树荫下的蝉鸣都带着几分嘶哑的倦意。然而,在空调全力运转的实验室和办公室内,年轻的探索者们却仿佛感受不到季节的燥热,他们的世界里,只有代码的温度、数据流淌的轨迹,和思维碰撞的微光。
许源的 Bondi 吸积简化模拟,在加入了微小的、均匀的初始角动量后,情况骤然复杂。正如徐嘉庆所料,旋转的引入彻底改变了流体的动力学。原先简单的球对称径向内流,在离心力的作用下,开始“拒绝”直接落入中心点,在某个临界半径(大致相当于角动量支撑形成的“驻点”)外围堆积、减速,并试图寻找平衡。
理论上,这应该形成一个大致的、旋转的、扁平的“盘”状结构,物质通过盘内的某种粘滞过程(在模拟中通常用“α-粘滞”唯象描述)缓慢向内输运。
然而,许源的模拟一开始就遭遇了数值不稳定。物质在中心区域附近剧烈震荡,甚至出现非物理的“空洞”和“尖峰”。他检查了边界条件,调整了粘滞系数α的取值,甚至尝试了不同的空间离散格式(从一阶迎风到 WENO 重构),但问题依旧。
连续两天的挫败让他有些焦躁。
杨博士似乎察觉到了他的困境,在一次午餐时随口提道:“Bondi 吸积加角动量,最简单的做法是假设一个‘α-盘’模型,但那个模型的稳态解是已知的。你有没有想过,不从零开始模拟整个时间演化,而是先设一个接近稳态的初始条件,然后看它的小扰动如何演化?或者,用你的程序,先验证一下无角动量 Bondi 流的稳态解是否正确,确保你的代码在最简单情况下是可靠的?”
一语惊醒梦中人。
许源意识到自己太急于求成,跳过了关键的验证步骤。他立刻回头,重新仔细调试无角动量的 Bondi 吸积程序。
这次,他加入了更详细的诊断输出,在每个时间步都计算质量、动量和能量的守恒误差。他发现,在靠近内边界的几个网格上,由于数值耗散和边界处理的耦合,确实存在微小的质量不守恒。虽然对整体演化影响不大,但在高精度要求下,这可能是后续不稳定性的种子。