简介这是一份面向核工程与深度学习交叉领域学习者的机器学习实战资源聚焦物理信息神经网络PINN在中子学中的应用覆盖有效增殖因子计算、多维中子扩散方程无网格求解、中子输运微分阶理论建模等核心问题。资源共39个文件以28个Python脚本为主体按功能拆分为反应堆临界计算、扩散方程正问题/逆问题、硬边界约束、并行超参数搜索等多个模块同时附有5个xml工程配置、3个dat损失或训练数据、1个README说明及.gitignore等辅助文件便于读者快速定位并复用。整个压缩包仅269KB代码结构清晰且轻量特别适合用于毕业设计、课程设计或期末大作业的代码基础与实验范本。目前已有46人学习适合具备一定机器学习或核物理基础的研究者对照源码理解PINN建模思路也可作为后续研究多物理耦合、智能核能计算方向的起点。1. 先把话说在前头这份 PINN 中子学资源到底解决了谁的什么问题做核工程或物理方向毕业设计的学生最头疼的往往不是蒙特卡洛跑不出结果而是导师随口一句“能不能用机器学习和中子学结合一下”。这句话落到实地上就是 PINN用物理信息神经网络去求解中子扩散方程输入材料截面和源项输出堆芯通量分布。这份基于机器学习的中子学PINN研究.zip就是干这个的它省去你从零搭框架、查文献、调损失函数的时间把一条能跑通的路直接给你铺好了。适合三类人核工程、物理系拿它做毕设计算机方向做人工智能交叉学科课程设计以及期末大作业想快速出图又不愿意只交个分类任务的工科生。下面我按“原理—复现—踩坑”的顺序拆一遍。2. 中子学为什么需要 PINN先把扩散方程和训练数据讲明白2.1 稳态中子扩散方程PINN 要拟合的物理约束到底是什么PINN 这类方法的本质是把偏微分方程的残差直接写进损失函数让神经网络在满足数据拟合的同时也让方程本身尽可能成立。在中子学里最常见的简化模型是稳态中子扩散方程-∇·(D∇φ) Σa·φ S其中 φ 是中子标量通量单位是 n·cm⁻²·s⁻¹D 是扩散系数单位是 cmΣa 是宏观吸收截面单位是 cm⁻¹S 是源项代表单位体积内每秒产生的中子数。对毕业设计和课程设计来说用扩散近似而不是完整的玻尔兹曼输运方程是完全合理的因为这个方程已经把中子与介质的相互作用压缩成了两个宏观参数而这两个参数恰好又能从核数据库和蒙特卡洛程序里直接拿到。PINN 在这里要做的是学习一个函数 φ(x, y)让它同时满足扩散方程的残差为零、堆芯几何边界上的条件成立、以及已知位置的源项或通量采样值吻合。边界条件一般分两类真空边界用外推距离处理即在堆芯外推一个距离后通量降为零最常见的写法是 φ(边界外推点) 0反射边界则是对称面其法向导数为零。这个物理约束直接决定了网络输出在边界的形状处理不好后面训练必翻车。这里要明确一个概念PINN 不是物理模型的替代品而是物理模型的代理求解器。传统数值方法需要把堆芯离散成上万甚至几十万个网格点每个点都求解一次代数方程PINN 只需要在一个连续坐标域上采样用反向传播去迭代优化网络权重。网格分辨率越高、维度越大的问题PINN 在训练完成后的推理效率优势就越明显。2.2 蒙特卡洛数据生成与截面参数采样再来回答一个新手必问的问题训练 PINN 的“标签”从哪来严格来说PINN 的物理残差项是不需要外部标签的方程本身就是监督信号。但要保证网络学到的是真实中子学响应而不是某个数学上成立但物理上荒谬的解还得用少量参考解来校准。常见做法是先用蒙特卡洛程序生成一组“稀疏的真值样本”只在这些样本点上给网络强约束其他点完全靠物理残差来约束。我一般用 OpenMC 做数据生成因为它开源、有 Python API、并且能直接输出网格通量分布。做法是建立一个简化的二维堆芯或栅格模型给定不同材料的截面参数运行固定源计算获取稳态通量分布。采样时把 D、Σa、S 都当作可变参数每组参数跑一次蒙特卡洛就可以得到一组通量场。对毕设规模来说跑 2050 组工况就够用了因为 PINN 的主损失来自物理残差真值样本只起到锚点作用。参数物理含义采样范围示例量纲D扩散系数0.5 ~ 3.0cmΣa宏观吸收截面0.01 ~ 0.2cm⁻¹S固定源强100 ~ 1000n·cm⁻³⁻¹s⁻¹几何宽度堆芯半宽度20 ~ 60cm蒙特卡洛跑出来的通量标签本身带有统计涨落这个噪声水平取决于粒子数和网格划分。如果粒子数太少PINN 会把统计噪声当成真实的通量起伏学进去后面我会在避坑章节专门讲这个。2.3 为什么是 PINN 而不是纯数据驱动有读者会问既然我已经用蒙特卡洛算出了一批通量分布为什么不直接用个全连接网络或 CNN 做监督回归还要绕一圈加物理损失答案是样本成本。单个蒙特卡洛工况从建模到跑完统计收敛需要几十分钟到几小时纯监督学习至少需要上千组工况才能让网络泛化这个数据采集成本对毕设周期来说基本不可接受。PINN 把数据需求压到了几十组内部点用方程残差约束边界和稀疏采样点用真实数据校准。另一个优势是网格无关性。CNN 的输入输出是固定分辨率的图像想换一套网格就得重新训练PINN 输出的是连续坐标函数任意位置都能直接推理通量值这对后续做参数敏感性分析特别友好。它天然的连续输出特性和物理一致性正是这个课题选它当主方法的核心理由。提示如果你打算答辩时被问“为什么不用有限差分”答案的核心不是 PINN 收敛更快而是 PINN 给出的是一个可微的连续代理函数可以直接对它求梯度做敏感性分析也可以跟其他物理场做联合推理这是网格类方法做不到的。3. 把资源跑起来网络结构、损失函数和训练循环的落地写法3.1 工程代码结构先搞清楚拿到手的是什么这份资源拿到手解压之后的典型工程组织大致是四块数据生成脚本、模型定义、训练入口、可视化分析。数据生成脚本通常是用 OpenMC 或预处理好的文本格式数据批量生成截面参数和通量场的这部分跑完会产出一个 h5 或 csv 文件模型定义文件里是这个 PINN 的网络结构和损失函数训练入口负责采样坐标点、组织训练循环可视化则是把预测通量面和蒙特卡洛参考面画在一起对比。我习惯在训练前把所有参数集中放在一个 yaml 或 py 文件里管理包括几何尺寸、截面取值、网络层数宽度、学习率和迭代步数。这份资源里大概率也有类似的配置模块拿到手第一件事就是改这一段其他地方不要乱动。如果你拿到手的代码结构不完全一样也别慌——只要认准“数据、模型、训练、可视化”四个职责模块就能快速定位到对应文件。3.2 网络结构与物理损失残差项怎么算、权重怎么设PINN 的骨干网络不宜太深四到六层全连接足够。输入是两个坐标 (x, y)输出是一个标量 φ。激活函数选 tanh 而不是 ReLU原因很直接物理损失里需要对 φ 求二阶导数ReLU 的一阶导是分段常数、二阶导恒为零这样扩散算子那一项根本学不到信息。tanh 是光滑的非线性函数二阶导存在且有意义是 PINN 场景里最稳妥的激活函数。下面这段是物理损失函数的核心逻辑你可以拿它对照资源里的实现来理解import torch import torch.nn as nn def physics_loss(model, coords_pde, D, Sigma_a, S): # 坐标归一化到 [-1, 1]避免激活饱和 coords_pde.requires_grad_(True) phi model(coords_pde) # 一阶梯度 grad torch.autograd.grad(phi, coords_pde, grad_outputstorch.ones_like(phi), create_graphTrue)[0] # 二阶梯度需要分别在 x 和 y 方向求导 grad_x, grad_y grad[:, 0], grad[:, 1] phi_xx torch.autograd.grad(grad_x, coords_pde, grad_outputstorch.ones_like(grad_x), create_graphTrue)[0][:, 0] phi_yy torch.autograd.grad(grad_y, coords_pde, grad_outputstorch.ones_like(grad_y), create_graphTrue)[0][:, 1] # 稳态扩散方程残差 -D*(phi_xx phi_yy) Sigma_a * phi - S 0 residual -D * (phi_xx phi_yy) Sigma_a * phi - S return torch.mean(residual ** 2)逻辑说明requires_grad_(True)让输入坐标进入计算图这样后续才能对坐标求梯度autograd.grad求一阶导数时设置了create_graphTrue目的是让求导结果也带着计算图从而支持对二阶导数的继续反推。残差的形状是在每个内部采样点上计算方程的左右偏差值取平方和平均就得到了物理损失。参数说明D、Sigma_a、S 是每个训练批次里当前工况的材料参数你可以把它当常数传入也可以把它们和坐标一起当作输入让网络学会跨工况泛化。后者的网络输入就变成 (x, y, D, Σa, S)模型复杂度会上升但能力更强这也是这份资源可能有不同变体的地方——先跑通前者再试后者。3.3 训练循环多目标损失的组合与观察方法PINN 的总损失是三项之和边界损失、稀疏真值损失、物理残差损失。边界损失约束外推边界上 φ≈0真值损失把蒙特卡洛算出的采样点兜住物理残差保证整场满足扩散方程。实际训练里常遇到的问题是边界和真值损失数值很小、物理损失数值很大导致训练前期网络只顾着把方程残差压下来而完全忽略边界条件。一个有效的做法是给边界和真值损失乘上权重系数让它们在损失总值里的初始占比达到 10% 左右optimizer torch.optim.AdamW(model.parameters(), lr1e-3) for step in range(total_steps): optimizer.zero_grad() coords_pde sample_interior(batch_size_pde) coords_bc sample_boundary(batch_size_bc) coords_label, phi_label sample_mc_points(batch_size_label) L_physics physics_loss(model, coords_pde, D, Sigma_a, S) L_bc boundary_loss(model, coords_bc) L_label nn.MSELoss()(model(coords_label).squeeze(), phi_label) # 权重设定原则边界与真值损失初始占比约 10% total_loss L_physics w_bc * L_bc w_label * L_label total_loss.backward() optimizer.step()这里的采样逻辑是每次迭代从三个不同区域采一批点内部点用均匀随机采样边界点沿堆芯外边界采样真值点从蒙特卡洛结果里随机抽取固定数量的坐标。每步迭代只用一小批点参与计算所以显存压力不大20000 步以内在一张消费级显卡上就能跑完。权重参数一般从 w_bc10、w_label10 起步训练中观察三项损失的数值量级。如果你的物理损失已经降到 1e-4 以下但边界损失还停在 1e-2说明边界权重太小需要调大。反过来如果边界损失压得很低但通量场形状不对就是边界权重过犹不及、把内场带偏了。损失曲线判断的总体经验是三项损失应该同步下降任何一项单独“躺平”都意味着权重失衡。注意判断收敛不要只看总损失一定要同时看预测通量场的形状。PINN 有时会出现总损失很低但通量在局部区域振荡的“假收敛”这时需要增加物理残差点的数量或者加快坐标空间的采样密度。4. 避坑指南五个让 PINN 在中子学上翻车的真实细节4.1 损失函数权重失衡边界条件被物理残差淹没现象训练前几千步物理损失降得很快但预测通量在边界处完全不等于零通量场向外泄漏。原因内部采样点数量远多于边界点而物理残差值的初始数量级又在 1e-1 到 1e-3 之间。边界损失算出来的偏差可能就是 0.1乘上权重之后对总损失的贡献很小梯度被物理残差主导。解决先把边界损失和真值损失的权重各调到 10 起步观察边界损失曲线是否真实下降。我自己的习惯是每 500 步打印一次三项损失的绝对值如果边界损失占比长期低于总损失的 5%就把权重翻倍。还有一种做法是把边界采样点数量提高到内部点的一半牺牲一点物理约束强度来换边界刚性。4.2 坐标和通量不归一化tanh 饱和导致梯度消失现象网络训练完全不动损失稳定在一个常数模型输出恒等于某个固定值。原因堆芯尺寸如果是 60cmx 坐标直接输入 30、60 这种数值激活函数 tanh 的输入会落到饱和区梯度接近零。通量也一样如果标签是绝对通量量级到 1e14这种量级差会让 MSE 损失爆炸网络直接学不动。解决几何坐标全部线性映射到 [-1, 1]比如 x_norm 2 * x / L - 1。通量也做归一化通常除以堆芯中心附近的最大通量参考值 φ_ref让真值标签落在 [0, 1] 区间。这个归一化不是可选项是 PINN 能不能训练的硬前提。如果你看到训练初期 loss 就是 nan八成是这里没做。4.3 激活函数选错ReLU 让扩散算子变成零现象物理损失项始终等于一个很大的常数怎么调学习率都降不下去但同样的网络换成数据拟合任务却正常。原因物理损失里含对通量的二阶导数项。ReLU 在定义域内是线性的一阶导为常数、二阶导为零。网络所有隐藏层都用 ReLU输出 φ 对坐标的二阶导数就退化成零扩散算子那一项直接变成 -0 Σa·φ - S方程约束变成代数约束而非微分约束模型永远不可能满足扩散方程。解决把全部隐藏层激活函数换成 tanh。如果非要保留 ReLU 类变体可以用 Swish 或 SiLU它们的二阶导不为零。这个问题在普通分类任务里根本看不出来属于 PINN 特有的暗坑很多第一次写的同学会卡在这里好几天。4.4 单位不统一模型收敛但数值差了四个量级现象训练过程非常顺利损失曲线漂亮但预测通量与蒙特卡洛真值的形状一致、数值对不上差了好几个数量级。原因扩散系数 D 用的是厘米但截面数据从核数据库里读出来可能混用了米制或者方程里把 Σa 的单位换算错了导致物理残差计算里 D 和 Σa 的相对比例失真。PINN 的损失函数里D 乘以二阶导数、Σa 乘以 φ这两项单位如果不匹配网络能学出形状却学不对幅值。解决在做数据预处理时统一厘米单位制写一个单位检查函数把 D、Σa、S 的量纲打出来人工确认。最简单的检查方式是先不用神经网络手算一个均匀介质的解析解看 φ ≈ S / Σa 是否成立。这个值做一次快速验算能把所有单位错误挡在训练之前。4.5 蒙特卡洛统计噪声被当成真实物理现象预测通量在真值采样点附近出现局部扭曲看起来像过拟合但测试集误差很大。原因OpenMC 固定源计算的通量标签带有统计涨落粒子数设少了网格通量的相对误差可能到 5% 以上。PINN 是真值点处做了强约束网络为了逼近带噪声的标签把局部形状学弯了。解决真值标签只用于校准而不用于主导训练把真值损失权重限制在比物理损失低一到两个数量级的水平让方程约束去平滑掉标签噪声。另外蒙特卡洛计算尽量跑足粒子数让网格通量的相对误差控制在 1% 以内。如果机器时间不够可以合并多次独立计算的统计结果而不是只跑一次就收工。5. 让 PINN 结果写进论文验证、敏感性分析和瞬态拓展5.1 参考解验证有限差分与蒙特卡洛双交叉验证答辩时最怕被问“你这个结果凭什么是对的”。PINN 是近似求解器必须用独立方法交叉验证。我通常用有限差分离散扩散方程做一个粗网格参考解跟 PINN 预测比对通量形状。有限差分实现很直接中心差分就能满足精度import numpy as np def fd_solve(D, Sigma_a, S, L, N200): dx 2 * L / (N - 1) phi np.zeros((N, N)) # 中心差分迭代求解泊松型方程 for _ in range(10000): phi_new phi.copy() for i in range(1, N - 1): for j in range(1, N - 1): laplacian (phi[i1, j] phi[i-1, j] phi[i, j1] phi[i, j-1] - 4 * phi[i, j]) / (dx ** 2) phi_new[i, j] (S - D * laplacian) / Sigma_a phi phi_new return phi这段是雅可比迭代求解稳态扩散方程对同一组 D、Σa、S 参数把有限差分解和 PINN 预测的面画成三维对比图。通量形状误差用相对 L2 范数计算误差在 5% 以内就可以在论文里写“PINN 与数值参考解吻合良好”。然后再跟稀疏的蒙特卡洛采样点对比一次三重验证就齐了。5.2 做参数敏感性分析把 PINN 当代理模型用PINN 训练完成后最大的实用价值是即时推理。蒙特卡洛每换一组截面参数都要重跑几小时而 PINN 如果把截面参数也放在输入里换参数后推理只需要一次前向传播。做敏感性分析时我把 Σa 从标称值上下浮动 10%密集采样 100 组PINN 几秒就能全部算完再统计通量对截面的偏导数这就是物理上反应性系数的近似。这个能力是网格方法不具备的写论文时可以作为创新点单独成节。5.3 往非稳态拓展加时间维度的最小改动如果你的毕设想再往上够一够稳态扩散方程可以拓展成含时间项的瞬态方程1/v · ∂φ/∂t - ∇·(D∇φ) Σa·φ S。改动非常小网络输入从 (x, y) 变成 (x, y, t)损失函数里加一项时间偏导 ∂φ/∂t再给初始条件加一个损失项即可。时间项比较温和不需要改损失权重方案原来的避坑经验仍然适用。这个方向再往下就是中子动力学配一个缓发中子模型就能贴近反应堆物理的前沿话题作为毕设的深化方向足够了。最后说一句我的真实教训第一次跑通 PINN 时我没做归一化产物里全是 nan当时不懂梯度饱和这回事浪费了整整两天。从那以后我每次跑 PINN 都强制走一遍流程——先归一化坐标和通量再检查 D 和 Σa 的单位量纲是否一致最后才看损失曲线。这套顺序救了我很多次希望帮到你。本文还有配套的精品资源点击获取