tmmcore 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -33
- package/package.json +12 -6
- package/src/build.ps1 +8 -2
- package/src/index.js +19 -2
- package/src/phase.js +522 -0
- package/src/taylorJet.js +261 -0
- package/src/tmm.js +4 -4
- package/src/tmmWasm.js +454 -13
- package/src/tmm_kernel.c +798 -7
- package/src/tmm_kernel.wasm +0 -0
package/README.md
CHANGED
|
@@ -5,26 +5,22 @@
|
|
|
5
5
|
srcset="https://raw.githubusercontent.com/aai2k/tmmcore/main/docs/img/banner-on-dark.png">
|
|
6
6
|
<img alt="tmmcore"
|
|
7
7
|
src="https://raw.githubusercontent.com/aai2k/tmmcore/main/docs/img/banner-on-light.png"
|
|
8
|
-
width="
|
|
8
|
+
width="320">
|
|
9
9
|
</picture>
|
|
10
10
|
|
|
11
11
|
**Transfer-matrix method for multilayer thin-film optics, with exact analytic derivatives.**
|
|
12
12
|
|
|
13
|
-
[](./LICENSE)
|
|
13
|
+
[](https://www.npmjs.com/package/tmmcore) [](./LICENSE)
|
|
14
|
+
|
|
15
|
+
**[Documentation](https://aai2k.github.io/tmmcore/)** · **[Getting started](https://aai2k.github.io/tmmcore/getting-started/)** · **[API](https://aai2k.github.io/tmmcore/api/)** · **[Validation](https://aai2k.github.io/tmmcore/validation/)**
|
|
14
16
|
|
|
15
17
|
</div>
|
|
16
18
|
|
|
17
|
-
Takes a stack of layers and returns reflectance, transmittance and absorptance
|
|
18
|
-
for absorbing and dispersive materials, at any angle of incidence, in s and p
|
|
19
|
-
polarization. Alongside the spectra it returns the exact thickness Jacobian, the
|
|
20
|
-
exact thickness Hessian, and the needle-insertion P-function, computed
|
|
21
|
-
analytically rather than by finite differences.
|
|
19
|
+
Takes a stack of layers and returns reflectance, transmittance and absorptance for absorbing and dispersive materials, at any angle of incidence, in s and p polarization. Alongside the spectra it returns the exact thickness Jacobian, the exact thickness Hessian, and the needle-insertion P-function, computed analytically rather than by finite differences.
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
has no dependencies and works on import. WebAssembly is opt-in and roughly an
|
|
25
|
-
order of magnitude faster.
|
|
21
|
+
It also computes phase, group delay, GDD and third-order dispersion, by carrying the same matrix in third-order Taylor arithmetic. Those come out analytically too, so they do not depend on the wavelength grid you sampled and there is no finite-difference step to tune. Their thickness gradients come along in the same call, which is what makes chirped-mirror design a gradient problem.
|
|
26
22
|
|
|
27
|
-
|
|
23
|
+
Ships as JavaScript, as C, and as a WebAssembly build of the C. The JavaScript has no dependencies and works on import. WebAssembly is opt-in and roughly an order of magnitude faster.
|
|
28
24
|
|
|
29
25
|
## Install
|
|
30
26
|
|
|
@@ -56,8 +52,7 @@ Layers run from the incident medium toward the substrate.
|
|
|
56
52
|
|
|
57
53
|
## Conventions
|
|
58
54
|
|
|
59
|
-
Mismatched conventions are the most common cause of two TMM codes disagreeing,
|
|
60
|
-
so check these first.
|
|
55
|
+
Mismatched conventions are the most common cause of two TMM codes disagreeing, so check these first.
|
|
61
56
|
|
|
62
57
|
| | |
|
|
63
58
|
|---|---|
|
|
@@ -68,31 +63,27 @@ so check these first.
|
|
|
68
63
|
| Complex numbers | `[re, im]` pairs |
|
|
69
64
|
| Layer order | incident medium → substrate |
|
|
70
65
|
|
|
71
|
-
This is the complex conjugate of Macleod's convention. R, T and A are identical
|
|
72
|
-
under conjugation; phase-sensitive quantities are not.
|
|
66
|
+
This is the complex conjugate of Macleod's convention. R, T and A are identical under conjugation; phase-sensitive quantities are not.
|
|
73
67
|
|
|
74
68
|
## Verify it yourself
|
|
75
69
|
|
|
76
|
-
|
|
70
|
+
Three commands, none needing anything but Node:
|
|
77
71
|
|
|
78
72
|
```bash
|
|
79
|
-
|
|
80
|
-
npm
|
|
73
|
+
node examples/01-single-layer.mjs # matches the closed-form solution
|
|
74
|
+
npm test # the JavaScript and the C agree
|
|
75
|
+
npm run compare # and both agree with an independent implementation
|
|
81
76
|
```
|
|
82
77
|
|
|
83
|
-
The first
|
|
84
|
-
|
|
85
|
-
64,416 comparisons, worst disagreement 4.4e-16.
|
|
78
|
+
The first tests the equations rather than agreement, and is the only one here that does. A single quarter-wave layer at normal incidence has an exact solution (Macleod §3.2); tmmcore reproduces it to 1.4e-17, inside double-precision epsilon of 2.2e-16.
|
|
79
|
+
|
|
80
|
+
The second drives both implementations with identical inputs across absorbing, dispersive and oblique-incidence cases and compares every returned quantity. 64,416 comparisons, worst disagreement 4.4e-16. This is two implementations by the same author, so it catches porting bugs and establishes nothing beyond that.
|
|
81
|
+
|
|
82
|
+
The third checks them against [Steven Byrnes' `tmm`](https://github.com/sbyrnes321/tmm), written independently in Python under the same complex-index convention, so only the mathematics is under test. 12,352 values, worst disagreement 8.6e-14, which is float64 accumulation noise over a forty-layer matrix product.
|
|
86
83
|
|
|
87
|
-
|
|
88
|
-
`tmm`](https://github.com/sbyrnes321/tmm), written independently in Python under
|
|
89
|
-
the same complex-index convention, so only the mathematics is under test. 12,352
|
|
90
|
-
values, worst disagreement 8.6e-14, which is float64 accumulation noise over a
|
|
91
|
-
forty-layer matrix product.
|
|
84
|
+
[Validation](https://aai2k.github.io/tmmcore/validation/) sets out what each level does and does not establish, and lists what is not tested at all.
|
|
92
85
|
|
|
93
|
-
|
|
94
|
-
[documentation](https://aai2k.github.io/tmmcore/comparison/), and need a Python
|
|
95
|
-
environment.
|
|
86
|
+
The [comparison with four other TMM packages](https://aai2k.github.io/tmmcore/comparison/) covers accuracy as well as speed, including which of them run in single precision. Reproducing the timings needs a Python environment; the accuracy table does not.
|
|
96
87
|
|
|
97
88
|
## Documentation
|
|
98
89
|
|
|
@@ -104,8 +95,7 @@ environment.
|
|
|
104
95
|
|
|
105
96
|
## Using the C directly
|
|
106
97
|
|
|
107
|
-
`src/tmm_kernel.c` is C99 with no dependencies beyond libm. Drop it into a
|
|
108
|
-
project and compile:
|
|
98
|
+
`src/tmm_kernel.c` is C99 with no dependencies beyond libm. Drop it into a project and compile:
|
|
109
99
|
|
|
110
100
|
```bash
|
|
111
101
|
cc -std=c99 -O2 -c src/tmm_kernel.c
|
|
@@ -115,5 +105,4 @@ cc -std=c99 -O2 -c src/tmm_kernel.c
|
|
|
115
105
|
|
|
116
106
|
[MIT](./LICENSE) © Andrey Achapovsky
|
|
117
107
|
|
|
118
|
-
Built for and used by [TFStudio](https://github.com/aai2k/TFStudio), an
|
|
119
|
-
open-source optical coating design application.
|
|
108
|
+
Built for and used by [TFStudio](https://github.com/aai2k/TFStudio), an open-source optical coating design application.
|
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tmmcore",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Transfer-matrix method for multilayer thin-film optics, with exact analytic derivatives. JavaScript, C and WebAssembly.",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Transfer-matrix method for multilayer thin-film optics, with exact analytic derivatives and phase dispersion. JavaScript, C and WebAssembly.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": "./src/index.js",
|
|
9
9
|
"./tmm.js": "./src/tmm.js",
|
|
10
|
+
"./phase.js": "./src/phase.js",
|
|
11
|
+
"./taylorJet.js": "./src/taylorJet.js",
|
|
10
12
|
"./tmmWasm.js": "./src/tmmWasm.js",
|
|
11
13
|
"./tmm_kernel.wasm": "./src/tmm_kernel.wasm",
|
|
12
14
|
"./tmm_kernel.c": "./src/tmm_kernel.c",
|
|
@@ -18,10 +20,10 @@
|
|
|
18
20
|
"LICENSE"
|
|
19
21
|
],
|
|
20
22
|
"scripts": {
|
|
21
|
-
"test": "node tests/equivalence.mjs",
|
|
23
|
+
"test": "node tests/equivalence.mjs && node tests/growing_equivalence.mjs && node tests/growing_eval_equivalence.mjs",
|
|
22
24
|
"compare": "node benchmarks/compare.mjs",
|
|
23
|
-
"examples": "node examples/01-single-layer.mjs && node examples/02-ar-coating.mjs && node examples/03-metal-mirror.mjs && node examples/04-refine.mjs",
|
|
24
|
-
"build:wasm": "emcc src/tmm_kernel.c -O3 --no-entry -sSTANDALONE_WASM=1 -sALLOW_MEMORY_GROWTH=1 -sEXPORTED_FUNCTIONS=_tmm_one,_tmm_spectrum,_tmm_jacobian,_tmm_needle_scan,_tmm_hessian,_malloc,_free -o src/tmm_kernel.wasm",
|
|
25
|
+
"examples": "node examples/01-single-layer.mjs && node examples/02-ar-coating.mjs && node examples/03-metal-mirror.mjs && node examples/04-refine.mjs && node examples/05-angle-map.mjs && node examples/06-needle.mjs && node examples/07-jacobian-map.mjs && node examples/08-group-delay.mjs",
|
|
26
|
+
"build:wasm": "emcc src/tmm_kernel.c -O3 --no-entry -sSTANDALONE_WASM=1 -sALLOW_MEMORY_GROWTH=1 -sEXPORTED_FUNCTIONS=_tmm_one,_tmm_spectrum,_tmm_jacobian,_tmm_needle_scan,_tmm_hessian,_tmm_phase_one,_tmm_phase_spectrum,_tmm_phase_jacobian,_tmm_monitor_curve,_tmm_deposition_spectra,_tmm_growing_eval_create,_tmm_growing_eval_set_top,_tmm_growing_eval_sample,_tmm_growing_eval_free,_malloc,_free -o src/tmm_kernel.wasm",
|
|
25
27
|
"build:native": "cc -std=c99 -pedantic -Wall -Wextra -O2 -c src/tmm_kernel.c -o tmm_kernel.o"
|
|
26
28
|
},
|
|
27
29
|
"keywords": [
|
|
@@ -34,7 +36,11 @@
|
|
|
34
36
|
"reflectance",
|
|
35
37
|
"transmittance",
|
|
36
38
|
"photonics",
|
|
37
|
-
"webassembly"
|
|
39
|
+
"webassembly",
|
|
40
|
+
"group-delay",
|
|
41
|
+
"dispersion",
|
|
42
|
+
"chirped-mirror",
|
|
43
|
+
"ultrafast"
|
|
38
44
|
],
|
|
39
45
|
"license": "MIT",
|
|
40
46
|
"author": "Andrey Achapovsky",
|
package/src/build.ps1
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
param([switch]$InstallEmsdk)
|
|
25
25
|
|
|
26
26
|
$ErrorActionPreference = 'Stop'
|
|
27
|
-
$root = Split-Path -Parent
|
|
27
|
+
$root = Split-Path -Parent $PSScriptRoot
|
|
28
28
|
Set-Location $root
|
|
29
29
|
|
|
30
30
|
# --- Try to activate emsdk from a known root (returns $true if emcc appears) ---
|
|
@@ -111,11 +111,17 @@ $emccArgs = @(
|
|
|
111
111
|
'--no-entry'
|
|
112
112
|
'-sSTANDALONE_WASM=1'
|
|
113
113
|
'-sALLOW_MEMORY_GROWTH=1'
|
|
114
|
-
'-sEXPORTED_FUNCTIONS=_tmm_one,_tmm_spectrum,_tmm_jacobian,_tmm_needle_scan,_tmm_hessian,_malloc,_free'
|
|
114
|
+
'-sEXPORTED_FUNCTIONS=_tmm_one,_tmm_spectrum,_tmm_jacobian,_tmm_needle_scan,_tmm_hessian,_tmm_phase_one,_tmm_phase_spectrum,_tmm_phase_jacobian,_tmm_monitor_curve,_tmm_deposition_spectra,_tmm_growing_eval_create,_tmm_growing_eval_set_top,_tmm_growing_eval_sample,_tmm_growing_eval_free,_malloc,_free'
|
|
115
115
|
'-o'
|
|
116
116
|
'src/tmm_kernel.wasm'
|
|
117
117
|
)
|
|
118
118
|
& emcc @emccArgs
|
|
119
|
+
if ($LASTEXITCODE -ne 0) { Write-Error "emcc failed with exit code $LASTEXITCODE."; exit 1 }
|
|
119
120
|
|
|
120
121
|
Write-Host "Built src/tmm_kernel.wasm"
|
|
121
122
|
node tests/equivalence.mjs
|
|
123
|
+
if ($LASTEXITCODE -ne 0) { Write-Error "equivalence tests failed with exit code $LASTEXITCODE."; exit 1 }
|
|
124
|
+
node tests/growing_equivalence.mjs
|
|
125
|
+
if ($LASTEXITCODE -ne 0) { Write-Error "growing_equivalence tests failed with exit code $LASTEXITCODE."; exit 1 }
|
|
126
|
+
node tests/growing_eval_equivalence.mjs
|
|
127
|
+
if ($LASTEXITCODE -ne 0) { Write-Error "growing_eval_equivalence tests failed with exit code $LASTEXITCODE."; exit 1 }
|
package/src/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* tmmcore
|
|
2
|
+
* tmmcore : transfer-matrix method for multilayer thin films.
|
|
3
3
|
*
|
|
4
4
|
* Two interchangeable implementations of the same physics:
|
|
5
5
|
*
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* The JavaScript path works immediately on import. WebAssembly is opt-in: load
|
|
10
10
|
* the `.wasm` bytes, instantiate, and call the instance methods. Results agree
|
|
11
|
-
* to float64 round-off either way
|
|
11
|
+
* to float64 round-off either way : see `tests/equivalence.mjs`.
|
|
12
12
|
*
|
|
13
13
|
* Conventions, which matter more than anything else here:
|
|
14
14
|
* ñ = n + ik k ≥ 0 for absorbing media
|
|
@@ -32,4 +32,21 @@ export {
|
|
|
32
32
|
matmul, rescaleMatrix, snellCosTheta, layerMatrix, cmatvec,
|
|
33
33
|
} from './tmm.js';
|
|
34
34
|
|
|
35
|
+
export {
|
|
36
|
+
// Phase, group delay, GDD and TOD
|
|
37
|
+
tmmPhaseDispersion,
|
|
38
|
+
tmmPhaseThicknessJacobian,
|
|
39
|
+
// Coefficient jets, for callers wanting r and t rather than the phase
|
|
40
|
+
tmmCoefficientJets,
|
|
41
|
+
tmmCoefficientThicknessJets,
|
|
42
|
+
coefficientPhaseDispersion,
|
|
43
|
+
coefficientPhaseThicknessDerivatives,
|
|
44
|
+
// Unit helpers
|
|
45
|
+
C_NM_PER_FS, omegaFromLambdaNm,
|
|
46
|
+
} from './phase.js';
|
|
47
|
+
|
|
48
|
+
// Taylor-jet arithmetic. The phase functions take refractive indices as jets;
|
|
49
|
+
// these compose one from any dispersion formula you can write.
|
|
50
|
+
export * from './taylorJet.js';
|
|
51
|
+
|
|
35
52
|
export * from './tmmWasm.js';
|