
做微磁学模拟的人应该都有过这种经历文献里的结构看着并不复杂材料参数也就那几个结果自己一上手Mumax3不是给你抛个NaN就是磁矩怎么转都转不到目标状态。Mumax3是目前微磁学模拟里非常主流的GPU加速工具相比OOMMF的CPU计算它在脚本书写、批量扫描和大网格模拟上有明显优势我自己主要拿它做磁性纳米结构里的磁涡旋、磁畴壁和斯格明子动力学。这篇内容准备分享一套我从基础设置到材料参数优化一直在用的Mumax3代码模板同时把单位、网格、交换长度这些“新手重灾区”一次性讲清楚。内容更适合已经有最小模拟经验、正准备系统化调整材料参数的研究生和工程师当然刚入门但愿意啃代码的人也能跟着跑完一遍。1. Mumax3到底解决什么问题为什么值得花时间学1.1 微磁学模拟的核心逻辑微磁学模拟说白了就是求解微磁学中的Landau-Lifshitz-GilbertLLG方程磁矩在有效场作用下进动、弛豫最终达到平衡态或稳定动力学状态。有效场里包含交换场、退磁场、外磁场、各向异性场如果做自旋电子学还得加上自旋转移矩、自旋轨道矩这些贡献。Mumax3就是把这些场和力矩全部集成好的有限差分求解器你用脚本定义网格、材料、初始磁矩和外场它自动解方程给出磁矩随时间的演化。这相当于你把“样品”在电脑里建出来然后“做实验”加磁场、看响应、扫参数、提取曲线。对于磁性随机存储器、磁传感器、赛道存储器这类器件设计这种数值实验能提前暴露很多问题省下大量流片和实验成本。1.2 为什么是Mumax3而不是OOMMF或NmagOOMMF是学术界的老牌工具稳定文档全但它主要跑CPU网格一大就非常慢。Nmag的脚本灵活但上手门槛不低。Mumax3选择把计算放到GPU上CUDA加速效果明显很多原本要跑一整天的模型换成Mumax3之后可能半小时就出结果。更重要的是Mumax3的脚本语言非常贴近“实验记录”思维变量、循环、字段操作都直白批量扫描时我可以直接在外部生成无数个mx3脚本扔给GPU跑这个流程对参数优化来说太友好了。当然Mumax3也不是没有缺点。它是有限差分方法网格和样品边界都是矩形阶梯复杂曲面形状需要靠足够细的网格去逼近。但绝大多数纳米磁性结构和薄膜器件都是接近长方体或圆柱形状阶梯近似可以接受。这个权衡我认为是值得的。2. 一套能直接跑的基础代码模板2.1 写脚本前先搞明白的三件事网格、单位、几何任何Mumax3脚本开头三件事必须先理顺网格划分、单位制、几何形状。网格划分就是决定仿真区域用多少个有限差分元胞。Mumax3里有两个关键命令setgridsize(Nx, Ny, Nz)设置三个方向的元胞数量setcellsize(dx, dy, dz)设置每个元胞的物理尺寸。仿真区域总尺寸就是两者逐项相乘。举个例子Nx256、Ny128、Nz1cell尺寸是2nm、2nm、5nm那么样品就是512nm乘256nm的一块厚度5nm的薄膜。单位制上Mumax3全部走国际单位制。饱和磁化强度Ms用A/m交换刚度Aex用J/m各向异性常数Ku1用J/m³外加磁场Bext用T特斯拉时间t用秒。很多人第一次都会在这里翻车尤其是把外加磁场的单位混淆成A/m或者把Ms直接填成文献里的emu/cm³不去换算。这个问题后面我还会反复强调。几何形状用setgeom定义。最简单的矩形是rect(512e-9, 256e-9)Mumax3会根据网格自动把它转成对应的磁矩掩模。几何尺寸必须和网格设置对应否则会出现“尺寸对不上内部还留了空隙”的尴尬情况。2.2 最小可运行模板复制改参数就能用下面这套模板是我平时常用的起点包含了网格、几何、材料、初始磁矩、外场、输出和求解设置直接存成mx3文件就能运行// 1. 网格设置 Nx : 256 Ny : 128 Nz : 1 dx : 2e-9 dy : 2e-9 dz : 5e-9 setgridsize(Nx, Ny, Nz) setcellsize(dx, dy, dz) // 2. 几何形状 setgeom(rect(512e-9, 256e-9)) // 3. 材料参数 Ms : 800e3 // 饱和磁化强度A/m Aex : 1.3e-11 // 交换刚度J/m alpha : 0.01 // 阻尼系数无单位 Ku1 : 0.0 // 单轴各向异性常数J/m^3 anisU : vector(0, 0, 1) // 各向异性轴方向 // 4. 初始磁矩与外场 m uniform(1, 0, 0.1) // 初始磁矩大致指向 x 方向 Bext vector(0, 0, 0) // 外磁场单位 T // 5. 输出设置 tableadd(Bext) tableadd(m) tableadd(E) autosave(m, 0.5e-12) // 6. 求解设置 MaxDt : 1e-13 // 限制最大时间步防止发散 run(1e-9) save(m)这段模板别看简单已经足够做很多基础模拟了只要改材料参数、几何、外场就可以跑磁化动力学、磁滞回线、涡旋弛豫等常见问题。我会在下面逐段拆一下说明每个参数实际影响什么。2.3 模板逐段拆解从网格到求解器网格设置为什么要放在最前面因为后续的几何、交换长度校验、显存占用估算全都要用到它。如果你还不清楚自己的cell尺寸是否合适先回去算一下交换长度这个我在第3节会详细展开。几何那行setgeom(rect(512e-9, 256e-9))决定了磁性材料实际分布在哪些网格里。如果你跑出来的磁矩状态总是“多出一圈”或者“少了边上一行”几何和网格一定有一个没对上。跑完第一次模拟后我习惯先用save(m)存一次初态直接看图确认几何区域正确再开始正式计算。材料参数里Ms、Aex、alpha是最核心的三个Ku1和anisU是各向异性项。对于没有特别易轴的薄膜样品可以先把Ku1设成0靠形状各向异性来稳定面内磁矩。初始磁矩m uniform(1, 0, 0.1)的意思是让每个元胞的磁矩方向都初始化为(1,0,0.1)然后归一化制造一个微弱的面外扰动。这个扰动对于有些动力学过程是必要的否则磁矩可能卡在完全对称的鞍点上。输出设置里tableadd记录的是随时间变化的标量或矢量最终汇总到table.txt。autosave(m, 0.5e-12)是每隔0.5ns自动存一次磁矩空间分布。注意单位这里是秒所以0.5e-12就是0.5ps。模拟总时长run(1e-9)是1ns。求解设置里我习惯加一行MaxDt : 1e-13限制最大时间步长。Mumax3默认有自适应时间步但有些参数组合下它容易放飞自我导致发散手动限制之后就稳很多。3. 材料参数逐一拆解Ms、Aex、alpha、Ku13.1 饱和磁化强度Ms所有磁场项的“底座”饱和磁化强度指的是材料在饱和状态下单位体积的磁矩。它直接影响退磁场、外磁场力矩的大小也影响铁磁共振频率。Ms在Mumax3里用A/m作单位常见坡莫合金大约在8e5 A/m左右钴铁硼在1.2e6 A/m左右铁在1.7e6 A/m左右。一个容易踩的坑是Mumax3内部有些量实际以T为单位存储比如外加磁场Bext但Ms的输入仍然用A/m。你如果非要把Ms填成以T为单位的数值比如把800kA/m写成1.0整个模拟的磁化动力学、开关场都会差一个数量级。这个单位换算关系是磁极化强度J μ0 × Msμ0约等于1.2566e-6所以800kA/m大约对应1.006T。Ms调大退磁场也随之变大这对薄膜器件的形状各向异性影响非常敏感。你在做参数优化时如果发现矫顽力、磁畴结构对Ms特别敏感先想想是不是退磁场效应主导了体系而不仅仅是单个参数在起作用。3.2 交换刚度Aex和网格尺寸直接挂钩的参数交换刚度Aex描述的是相邻磁矩之间的平行排列倾向单位是J/m它决定磁畴壁宽度、涡旋核心尺寸、斯格明子大小。坡莫合金的Aex通常在1.0e-11到1.5e-11 J/m量级铁大概在2.1e-11 J/m左右。Aex越大磁矩越不容易剧烈变化磁畴壁就越宽涡旋核心也越大。做参数扫描时你会发现Aex一改很多“结构尺寸”都跟着变。它和网格尺寸有直接关系如果你设的cell尺寸远大于交换长度那交换作用在数值上根本分辨不出来结果会粗得没法看。所以网格设计之前一定要用公式估算交换长度。交换长度的公式是lex sqrt(2 × Aex / (μ0 × Ms²))以坡莫合金为例Aex1.3e-11Ms800e3那么分母μ0×Ms²约等于1.2566e-6 × 6.4e11 8.04e5分子2×1.3e-11就是2.6e-11相除后大约是3.2e-17开根号就是5.7e-9米也就是5.7nm。这意味着你的cell至少要比5.7nm小很多才有希望分辨涡旋核心或畴壁细节实际使用中取2nm就很常见。如果只模拟大尺度的磁化翻转cell粗糙一点也可以但准静态特性会偏硬。3.3 阻尼alpha控制弛豫速度和结果形态阻尼系数alpha是无量纲参数描述磁矩向有效场弛豫的快慢。金属磁性材料通常在0.005到0.05之间绝缘体磁性材料或某些特殊合金可以低到0.001甚至更低。alpha越小磁矩就在进动轨道上来回绕得越久弛豫到平衡态的时间就越长你需要更长的模拟时间才能等到稳定结果。alpha也是铁磁共振谱线宽度的来源。实验上通过FMR可以反推出alpha而做动力学模拟时alpha会影响磁矩翻转路径和开关时间。例如模拟磁化翻转alpha太小可能翻转时间拉长出现明显的进动振荡alpha太大虽然稳定得快但可能掩盖一些真实的动力学行为。做参数优化时我常把alpha当成一个“并行扫描变量”它经常不直接影响稳态磁结构但会影响到达稳态所需的时间和动态响应。比如跑涡旋弛豫先开一个中等alpha快速弛豫再换成小alpha做精确动力学这样能省不少GPU时间。3.4 各向异性Ku1与anisU调矫顽力和易轴的钥匙单轴各向异性由两个量控制各向异性常数Ku1单位J/m³和各向异性轴方向anisU。它描述磁矩倾向沿某个特定方向排列。对垂直磁化薄膜anisU通常设成(0,0,1)对应厚度方向易轴对于面内易轴材料改成(1,0,0)或(0,1,0)。各向异性常数直接影响矫顽力。用Stoner-Wohlfarth模型做近似估计单畴颗粒在零温下的各向异性场是Hk 2 × Ku1 / (μ0 × Ms)。这个公式特别适合做参数优化的“数量级校准”如果你的模拟开关场比这个估算值大或小得离谱多半是模拟哪里出了问题。一个常见误区是把各向异性和形状各向异性混在一起看。薄膜样品即使Ku1设成0退磁场也会让面内比面外更有利这就是形状各向异性。这时候如果你的目标是“模拟垂直记录介质”就必须把Ku1调到足够大否则磁矩不会被钉扎在垂直方向。另外Mumax3还支持立方各向异性对应的是磁场储能与晶轴的关系需要的参数是Kc1、Kc2这些。基础模板里先用单轴各向异性就够了等真正遇到立方材料比如铁单晶再扩展。3.5 别忘了交换长度一个公式帮你定网格我已经在前面算过一遍交换长度这里还要强调它是网格设计的“第一约束条件”。交换长度太小的体系如果网格不够细就会出现局部磁矩翻转被数值抹平、涡旋核心失真、斯格明子消失这类假象。你调材料参数调了半天其实问题出在网格精度上。实际模拟中cell尺寸一般取交换长度的三分之一到二分之一比较稳妥。比如交换长度5.7nmcell取2nm左右。若cell取得比交换长度还大交换作用项基本失效磁畴壁会人为变窄这会让你的参数优化结果彻底失真。除了交换长度还要看一眼磁畴壁宽度大概可以用π×sqrt(Aex/Ku1)来估计。如果你调大Ku1导致畴壁变窄原本足够的网格可能又不够了必须回头重新检查cell尺寸。这就是为什么我建议把“网格校验”写进每一轮参数优化的检查清单而不是只做一次。4. 参数优化三步走手动、批量、自动4.1 先定目标拿开关场当优化指标参数优化前必须先有一个明确的量化指标。如果只是想“看看磁矩长什么样”那不叫优化叫探索。真正优化时要有目标函数比如尽量降低矫顽力、提高热稳定性、缩短翻转时间、获得特定尺寸的磁畴或者涡旋。我第二个常用例子是纳米点阵列的开关场优化。开关场也叫翻转场就是从饱和态沿相反方向加磁场磁矩发生不可逆翻转的最小外场。这个量既受Ms、Aex影响也受各向异性Ku1影响很适合用来演示参数扫描流程。具体操作上可以在一个脚本里分阶段改变外场每次跑一段足够长的弛豫时间再记录此时磁矩的平均分量。比如初始沿x饱和到100mT然后逐段降到0、再到反方向观察平均磁化Mx什么时候发生符号翻转。4.2 批量扫描参数用Python脚本一次跑几十组Mumax3本身没有内置优化器但它的脚本语法特别适合外部批量生成。我自己常用的做法是把mx3模板里的关键参数用占位符标记然后用Python循环生成多个输入文件在每个子目录里调用mumax3运行。下面是一个扫描Ms的示例脚本import os import subprocess cases [ (Ms_600k, 600e3), (Ms_700k, 700e3), (Ms_800k, 800e3), (Ms_900k, 900e3), (Ms_1000k, 1000e3), ] with open(template.mx3, r) as f: template f.read() for name, ms in cases: os.makedirs(name, exist_okTrue) content template.replace(MS_PLACEHOLDER, f{ms:.1e}) with open(os.path.join(name, input.mx3), w) as f: f.write(content) print(frunning {name} ...) subprocess.run([mumax3, input.mx3], cwdname)这里的技巧是模板里写Ms : MS_PLACEHOLDER运行时用Python替换成具体数值。每个case各自建一个子目录输出文件互不覆盖之后整理数据也方便。如果你要扫描多个参数比如Ms和alpha的组合就往cases列表里多放几组一跑就是一个二维参数网格。批量跑的时候注意GPU资源。单卡上同时跑多个mumax3进程不一定快因为显存和流处理器会被抢。我一般是串行跑或者按显存大小同时跑两到三个具体看卡的性能和模型规模。4.3 提取结果从table.txt里自动算指标Mumax3跑完后每个子目录里会生成table.txt记录时间、外场、平均磁化、总能量等信息。我写参数优化脚本时会专门写一个“结果提取”函数把每个参数组合对应的指标取出来汇总成一张表。import pandas as pd import glob rows [] for name, _ in cases: path os.path.join(name, table.txt) df pd.read_csv(path, sep\t) # 打印列名实际列名以你 tableadd 顺序为准 print(name, df.columns.tolist()) # 取最后一行的平均磁化 x 分量 last df.iloc[-1] rows.append({name: name, mx_final: last[m_0]}) result pd.DataFrame(rows) print(result)要注意Mumax3输出的“m”是归一化磁矩而不是以A/m为单位的实际磁化强度。列名的具体写法可能因版本略有差异可能是m_0、m_1、m_2也可能是m_x、m_y、m_z所以先打印df.columns看一眼最保险。拿到最后一行的平均磁化分量之后我就能画出“扫描参数–响应指标”的曲线。比如扫Ku1时可以把每个Ku1对应的开关场整理出来和Stoner-Wohlfarth估算的Hk曲线放在一起比对检查数值模拟是否符合物理预期。这一步非常能暴露脚本里的隐藏错误。4.4 更进一步把优化写成自动化循环手动扫描虽然直观但参数多了就很累。如果你已经有一个明确的目标函数比如让模拟磁滞回线和实验曲线尽量接近那完全可以把Mumax3的模拟流程包装成一个子函数交给数值优化库去自动迭代。from scipy.optimize import minimize def simulate(params): ms, ku params[0], params[1] # 生成脚本、运行、读取结果返回一个标量误差 return error res minimize(simulate, [800e3, 1e4], methodNelder-Mead) print(res.x)每次迭代都会启动一次新的Mumax3计算所以这个方案对单次模拟时间非常敏感。我建议前面先用较粗的网格和较短的模拟时间做粗优化等找到大致最优区域后再拿到细网格上复算。不然一次模拟一分钟几百次迭代就是大半天。另外一个更省事的思路如果参数空间本身就是两三个变量直接生成一个规整的网格扫描然后可视化结果热力图很多时候一眼就能看出最优区在哪。比如横轴Ms、纵轴Ku1、颜色代表开关场这种“扫描热图”比数字表格直观得多。5. 我踩过的坑常见报错和排查方法5.1 NaN、发散、跑一半崩了NaN问题基本是所有微磁学初学者的噩梦。我遇到的最常见原因是最大时间步长放太宽导致数值不稳定其次就是初始磁矩设置得太极端比如直接让相邻元胞反向排列交换场巨大一开跑直接爆掉。解决办法也比较简单。第一给MaxDt设一个比较保守的值比如MaxDt : 1e-13先跑通再逐步放大。第二初始磁矩尽量用平缓的状态比如uniform(1,0,0)不要一开始就弄出尖锐的磁畴壁。第三如果用了温度模块或者随机场记得检查随机种子和热涨落幅度有限温度下出现意外翻转不代表发散要区分清楚物理涨落和数值爆掉。另一个隐蔽原因是把Bext填得过大比如填了10T以上磁矩进动频率极高自适应时间步也扛不住。做磁场扫描时注意磁场范围和MaxDt的匹配关系。5.2 显存不足先少算一点再慢慢加显存不足在网格稍大的模型里太常见了。Mumax3在GPU上要同时存磁矩、有效场、交换场、退磁场辅助场等多个三维数组单精度下每个量都不小。比如256×128×32的网格光三维场就几十MB叠加多个中间变量、再考虑CUDA的临时缓存显存很容易吃满。我的经验是先跑一个最小的网格验证流程正确再逐步放大。比如先Nx64、Ny64、Nz1跑通然后放大到256×128、Nz4最后再上真正的大模型。不要一上来就把Nz设成32炸了还不好定位问题。如果确实需要大网格可以考虑缩小cell尺寸返回来减少网格数或者切分模拟区域分步计算。Mumax3的优势是GPU加速但GPU显存是硬上限学会“用小模型调参数、用大模型出结果”是省时间的重要技巧。5.3 结果和实验差很多先检查这四处参数优化最让人崩溃的不是跑不出来而是跑出来和实验对不上。我一般先按这个顺序排查一是网格密度是否满足交换长度约束。如果cell尺寸大于交换长度模拟会人为“变硬”畴壁变窄、开关场偏高。二是弛豫时间是否足够。有时候磁矩还在慢悠悠地转你就认为它达到稳态了提取的指标自然不对。看table.txt里的磁矩曲线尾部必须是平的才算稳定。三是温度因素。Mumax3默认是0K模拟没有热涨落所以零温矫顽力通常会比室温实验值偏高。如果你拿模拟结果直接和室温实验比关不上门很正常。可以开有限温度模拟但有限温度下结果有随机性需要多跑几次取平均。四是几何边缘和实际样品的差异。矩形阶梯近似会让边缘出现非物理钉扎尤其尺寸很小的纳米结构。这种情况下可以加密网格或者用更接近实验的真实形状文件导入几何。Mumax3支持从图片读取几何文件你可以用一张带抗锯齿的掩模图来定义样品形状效果会好很多。5.4 常见问题速查表现象大概率原因排查方向NaN或计算发散时间步过大、初始磁矩太尖锐、外场过大降低MaxDt改用平缓初态检查Bext量级GPU显存不足三维网格过大先降低Nz或整体网格再逐级放大翻转场偏大0K模拟、网格太粗、未弛豫充分检查交换长度延长run时间开温度模拟能量曲线不平滑几何与网格不匹配、磁矩有钉扎保存初态图检查setgeom区域表格里列名对不上不同版本的Mumax3输出命名有差异先print columns再取对应列这张表是我每次给新模型排错时都会过一遍的清单。优先处理网格和单位其次才怀疑物理参数。6. 一点个人经验参数优化前先让模型“正常”最后分享两个我认为最值得记住的教训。第一个教训是别在模型还没跑稳的时候就开始大规模调参数。我见过不少人拿着一个会偶尔出NaN的脚本去跑几百组扫描最后数据一堆能用的没几条。正常的操作顺序永远是先用小网格、短时间把单次模拟跑通跑稳确认磁矩演化行为符合物理直觉再扩大参数扫描范围。哪怕第一次只能跑一个小尺寸模型也好过跑出一个全是假象的大模型。第二个教训是参数优化不是“把文献参数抄一遍”。文献给的Ms、Aex、alpha通常来自特定厚度、特定衬底、特定制备工艺的样品和你自己模拟的几何条件很可能不匹配。真正靠谱的做法是先用文献值做初始点然后围绕目标指标做小范围扫描找到符合自己体系的最优值。扫描结果如果和解析估算偏差很大先怀疑脚本和网格而不是马上怀疑物理模型。顺手再分享一个小技巧做完一批参数扫描后我会把所有table.txt合并成一个大表用Python画几条关键的响应曲线保存成一张图存在工作目录里。这样三个月后回来看项目不用重新跑模拟一眼就能想起当时的数据规律。这个习惯帮我省了大量重复劳动。Mumax3的门槛其实不在软件本身而在你能不能把单位、网格、物理参数这三件事串起来。只要基础设置扎实参数优化就是一次有章法的系统扫描而不是靠感觉盲调。希望这套模板和排查思路能帮你少走点弯路。