Skip to content

About

从反射光谱反推多层光学薄膜厚度,并从生产记录里找出系统性偏差规律 · Infer multilayer thin-film thickness from reflectance spectra (single-file, offline)

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

镀膜反推 · coating-reverse

从一条反射光谱,反推多层光学薄膜的每一层厚度;再从生产记录里找出系统性偏差的规律。

给镀膜工程师用的计算工具。单文件网页,双击即开,所有计算在本机浏览器里完成,不向任何服务器发送数据(工业光谱数据通常是保密的)。

👉 在线试用:https://y-ian-0729.github.io/coating-reverse/

反推膜厚

经验库


它解决什么问题

1. 从光谱反推膜厚

镀完一批膜,用分光光度计扫一条反射曲线。曲线的形状由每层厚度和折射率共同决定。已知材料顺序和折射率,能不能把厚度反解出来?

数学上这是非线性最小二乘。难点不在「算」,而在「算出来的数可不可信」:7 层以上时代价函数有大量局部极小值,随便起个点往下走就会掉进一个「也能拟合得不错」的假解——这是这类工具最常见的坑。

所以这个工具的重点是不给你假的自信:

情况 工具的反应
拟合不上 🔴 红色,并说明该改什么(层数、层序、折射率、基底)
有多组厚度同样能拟合 🟡 黄色,把每一组都列出来,建议补一个斜入射测量
某几层没被数据定住 🟡 黄色,指出是第几层、为什么不唯一
全部定住 🟢 绿色

做法是三层防护:多起点 + 盆地跳跃(跳局部坑)、定向搜索竞争解(主动把单层推开再收敛)、逐层可信区间扫描(残差在噪声水平内的厚度范围)。

2. 从生产记录里找规律

单次偏差好查,反复出现的偏差难查。把每炉的目标厚度和实测厚度记下来,工具会分离出:

  • 整体偏差——有一半偏厚,是监控标定还是速率漂移
  • 夹具偏差——某个夹具恒定偏厚(这是最常见的偏差来源,逐夹具单独统计)
  • 监控方式差异——晶振 vs 光学,两者偏得不一样说明其中一种标定有问题
  • 时间漂移——随炉次/日期单向变化
  • 层位置偏差——总是第 1 层或最后一层出问题
  • 材料偏差——TiO₂ 偏而 SiO₂ 不偏,指向折射率假设

少于 8 条记录时它只显示「还差 N 条」,不出任何结论、不画图。 从几个点里归纳规律必然是想当然,宁可不说。


快速开始

不需要安装任何东西,不需要联网。

  1. 下载 index.html
  2. 双击打开
  3. 点「填入示例光谱」,再点「开始反推」

示例数据是模拟生成的(页面上有标注),不是真实测量。它用同一套膜系计算代码正向生成,所以能验证反推结果是真能收敛回真值的。

用自己的数据

支持三种输入:

  • 粘贴文本:每行 波长,反射率,波长单位 nm 或 μm(自动识别),逗号/空格/制表符分隔
  • 导入 CSV / TXT:直接选文件
  • 手动输入膜系:逐层选材料和初值,加/减层

精度与局限(重要)

这是实测结论,不是免责声明。

能做到:7 层 TiO₂/SiO₂ 膜系,在 0.42–0.90 μm、96 个点、0.3% 测量噪声下,单角度正入射反推误差约 1 nm 量级。

做不到:

  • 不能替代椭偏仪。反射率只有幅度没有相位,椭偏测两个量,信息量是它的两倍以上。
  • 不能反推折射率。折射率必须给定,它只解厚度。而且库里的数据是电子束蒸发非晶膜;如果你用溅射或离子辅助,实际折射率会差 1~3%,这个误差会原样传导成厚度误差。拟合总是差一点点又下不去时,先怀疑折射率而不是算法。
  • 层数未知时不能猜层数。材料顺序必须由你声明。
  • 厚吸收层精度有限。k 值误差同样会传导。
  • 经验库的结论不是因果。它只能说「这批数据里 F3 夹具系统性偏厚 1.8%」,不能证明是夹具造成的——因果要回产线验证。

折射率数据来源

来自 refractiveindex.info 数据库(CC0 公共领域,Polyanskiy, Sci. Data 11, 94 (2024)),已下载并压缩为本地文件,共 32 个材料条目,覆盖 0.2–25 μm。

包含 TiO₂、SiO₂、Ta₂O₅、Nb₂O₅、Al₂O₃、ZrO₂、HfO₂、Y₂O₃、MgF₂、ZnS、CaF₂、AlN、Si、Ge、BK7、熔石英、钠钙玻璃,以及 Ta/Al/Ag/Au/Cr/Ti/Cu/Ni/W/Pt 等金属。

注意:同一材料常有多个条目(例如 TiO₂ 有 Siefke 电子束膜和 Franta 两个版本,SiO₂ 有熔石英和溅射膜两个版本),它们的色散曲线不同,选错会算出不同的厚度。下拉框按材料分组,条目名保留原始文献信息。


技术实现

app/core.js       特征矩阵法前向计算(多层膜反射率/透射率)· 零依赖
app/solve.js      反推求解器:多起点 + 盆地跳跃 + LM + 竞争解搜索 + 可信区间
app/diagnose.js   生产记录偏差分析(含 t 分布区间估计)
app/ui.js         光谱解析、绘图、格式化
app/app.js        界面装配
src/template.html 页面骨架
tools/build.js    把所有 JS 和数据内联成单文件 index.html
tools/fetch_nk.py 从 refractiveindex.info 抓取并压缩折射率数据
tools/make-demo.js 生成模拟示例数据
tools/screenshot.js 驱动页面跑一遍示例并截图(README 里的图)

构建:

node tools/build.js     # → index.html(单文件,约 356 KiB)
node tests/verify-tmm.mjs    # 前向计算 10 项校验
node tests/verify-solve.mjs  # 反推求解器 9 项校验
node tests/diagnose.test.js  # 记录分析 79 项校验
node tests/verify-page.mjs   # 无头驱动页面 22 项校验

前向计算的正确性怎么保证

不是「跑起来没报错」就算对。tests/verify-tmm.mjs 校验的是物理:

  • 裸界面反射率 == Fresnel 公式 ((n₁−n₂)/(n₁+n₂))²(误差 < 1e-12)
  • 60° 入射分别等于 Rs 和 Rp(< 1e-10)
  • 非偏振 == (s+p)/2(< 1e-14)
  • MgF₂ 四分之一波长减反膜的最低反射点落在设计波长 ±10 nm
  • 无损耗单层 R + T == 1(< 1e-9)
  • 厚吸收层不产生 R > 1(能量守恒)
  • 正入射下半波层不改变反射率,四分之一波层必须显著改变

其中「厚吸收层 R > 1」这个检查抓到过一个真实 bug:特征矩阵的相位符号用错,导致厚吸收膜内部指数增长。这个错误在薄层上看不出来,只有把 Si 做成 2000 nm 才暴露。

求解器的测试不用真值当起点

早期版本的测试把真实厚度直接当迭代起点传给求解器,于是「7 层内误差 < 2 nm」是假绿——真值都喂进去了自然能收敛。现已重写:所有测试从空白或故意偏离的初值出发,并带反向断言(例如「声明 7 层但数据只有 5 层时必须报失败」)。


已知的工程取舍

  • 单文件、无构建、零依赖。代价是 index.html 356 KiB(内联了折射率库),换来的是双击即开、断网可用、不会因为 CDN 挂了而白屏。
  • 求解在浏览器主线程跑,7 层约 1.6 秒,期间界面会卡住(已提前一帧渲染提示)。
  • 折射率不外推。超出数据波长范围时返回 null 而不是猜一个值。

License

MIT。折射率数据来自 refractiveindex.info,CC0。

About

从反射光谱反推多层光学薄膜厚度,并从生产记录里找出系统性偏差规律 · Infer multilayer thin-film thickness from reflectance spectra (single-file, offline)

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages