English | 中文
A Python + COMSOL skill for 2-D rectangular grating diffraction simulations, producing total R/T and per-order R_m/T_m efficiencies via the validated full-field + Periodic Port + Floquet + TE recipe.
🏆 Validation: 66-case sweep (N_teeth=5..26, θ ∈ {±66.36°, 0°}) with energy conservation R+T = 1.00000 to better than 1×10⁻⁵ in every case.
comsol-grating-skill/
├── README.md / readme_zh.md ← human-facing quick start
├── SKILL.md ← agent-facing usage spec
├── LICENSE ← MIT
├── scripts/
│ ├── comsol_grating_template.py ← the engine (run/dry-run/sweep/preflight)
│ ├── example_config.json ← minimal example: edit and run
│ ├── example_run.bat ← double-click to run on Windows
│ └── requirements.txt ← Python deps
├── examples/
│ └── grating_N1_theta0.00_orders.csv ← known-good reference output
├── references/
│ ├── BUGS_AND_FIXES.md ← 9 known API gotchas with fixes
│ └── legacy/COMSOL_MATLAB_Pitfalls_Guide.md ← historical notes
└── tests/ ← COMSOL-free unit tests
-
COMSOL Multiphysics 6.x with the Wave Optics module license, installed on the local machine (the script talks to it via mph).
-
Python 3.8+ with
mph,jpype1,numpy,scipy:pip install -r scripts/requirements.txt
Clone into your skills directory (folder name = skill name):
git clone https://github.com/aikkkkko/comsol-grating-skill ~/.claude/skills/comsol-grating-simulationOn Windows: %USERPROFILE%\.claude\skills\comsol-grating-simulation.
-
Preflight (first time on a machine — verifies COMSOL + license):
python scripts/comsol_grating_template.py --preflight
-
Edit
scripts/example_config.jsonto your simulation case:lambda_nm,theta_degperiod_nm,duty_cycle,d_groove_nm,n_toothlayer_stack: list of[thickness_nm, n, label]from substrate up (labels: unique ASCII identifiers, notair/groove)
All refractive indices must be real (lossless recipe — complex n is rejected by the validator).
-
Dry-run (validates the config and prints propagating orders / ports without starting COMSOL — no license needed):
python scripts/comsol_grating_template.py --config scripts/example_config.json --dry-run
-
Run:
python scripts/comsol_grating_template.py --config scripts/example_config.json
Or on Windows: double-click
scripts/example_run.bat. -
Sweep a wavelength or angle range (single COMSOL session for all cases):
python scripts/comsol_grating_template.py --config my.json --sweep lambda_nm=1000:1100:10 python scripts/comsol_grating_template.py --config my.json --sweep theta_deg=0,15,30,45
-
Read results:
<prefix>_orders.csv— open in Excel for a quick per-order look<prefix>_sweep_<key>.csv— value, R, T, R+T per line (plot this)<prefix>.mat— load in MATLAB or Python for further analysis<prefix>.mph— open in COMSOL GUI for field visualization
For one input config, three files. Example with out_prefix="grating",
N_teeth=1, theta_deg=0:
| File | Size | Purpose |
|---|---|---|
grating_N1_theta0.00.mph |
~10–25 MB | Solved COMSOL model |
grating_N1_theta0.00.mat |
~50 KB–7 MB | Efficiencies + spectrum (+ Ez field if enabled) |
grating_N1_theta0.00_orders.csv |
~1 KB | Plain-text per-order table |
Console output for the shipped example_config.json (λ=1053 nm > Λ=500 nm,
so only m=0 propagates — see examples/ for the committed reference):
[INFO] === Grating: N_teeth=1, theta=0.0 deg, lambda=1053.0 nm, W=500.0 nm ===
[INFO] propagating orders: top air=1 (0..0), bot substrate n=1.46: 1 (0..0)
[INFO] total ports: 2
[INFO] mesh elements: ...
[INFO] solving ...
[INFO] solved.
[RESULT] R=0.11866 T=0.88134 R+T=1.00000
[INFO] top-3 reflected orders:
m= +0 eta=0.11866 sin_t=+0.0000
[CHECK] Poynting net flux: top=-0.8813 W/m, bot=-0.8813 W/m
The R+T = 1.00000 line is your sanity check: for lossless materials it
must be 1.0 to ~5 digits. If it isn't, something is wrong — see
references/BUGS_AND_FIXES.md or rerun with a finer mesh (hmax_factor).
It corrects 9 distinct bugs documented in references/BUGS_AND_FIXES.md that
affect naive implementations of grating models in COMSOL via mph. Most
importantly:
- It uses full-field + Periodic Port instead of scattered-field + SBC (the old route loses 5–25% of energy at large angles).
- It correctly switches the physics interface to TE via
ewfd.prop("components").set("components", "outofplane")(lowercase!) — a typicalewfd.property("Components", "OutofPlane")call silently fails on mph and runs TM instead. - It explicitly sets each Port's
E0 = [0, 0, 1]to force E along z. The defaultE0 = "t1x"puts E in-plane = TM. - It validates the config before starting COMSOL (bad layer labels, out-of-range duty cycle, complex refractive indices, etc. fail fast with readable messages instead of cryptic Java errors mid-build).
2-D, TE polarization, lossless real refractive indices, rectangular (binary) tooth profile, in-plane incidence from the air side. For anything else (3-D, TM, metals, blazed/sinusoidal profiles, conical incidence) use the COMSOL GUI or another tool — see SKILL.md "When NOT to use" for the reasoning.
python -m unittest discover -s tests -vCovers config validation, propagating-order math, and sweep parsing; no COMSOL or mph installation required.
SKILL.md— full agent-facing usage spec, with input fields, output schema, four concrete config examples, and a troubleshooting map.references/BUGS_AND_FIXES.md— every known API gotcha that the template defends against, with symptom / cause / fix triples.references/legacy/COMSOL_MATLAB_Pitfalls_Guide.md— older notes (predates the v4_TE recipe). Its header states section-by-section what is still valid; §2 was corrected in 2026-07 (unit-suffixed literals DO work in Box selectors; only parameter-name expressions fail).