@galihru/mnp-material 0.1.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 +24 -0
- package/package.json +27 -0
- package/src/complex.js +35 -0
- package/src/index.js +2 -0
- package/src/material.js +64 -0
package/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# @galihru/mnp-material
|
|
2
|
+
|
|
3
|
+
Scientific dielectric-response models for plasmonic simulations.
|
|
4
|
+
|
|
5
|
+
Implemented formulation (Drude model):
|
|
6
|
+
|
|
7
|
+
$$
|
|
8
|
+
\varepsilon(\omega)=\varepsilon_\infty-\frac{\omega_p^2}{\omega(\omega+i\gamma)}
|
|
9
|
+
$$
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @galihru/mnp-material
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
import { drudeEpsilon } from "@galihru/mnp-material";
|
|
21
|
+
|
|
22
|
+
const epsAu = drudeEpsilon("Au", 548.1);
|
|
23
|
+
console.log(epsAu);
|
|
24
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@galihru/mnp-material",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Material dielectric models for plasmonic electrodynamics.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./src/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./src/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"src",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"author": "GALIH RIDHO UTOMO <g4lihru@students.unnes.ac.id>",
|
|
15
|
+
"license": "GPL-2.0-only",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/galihru/mnpbem.git"
|
|
19
|
+
},
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"registry": "https://registry.npmjs.org/",
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"test": "node --test"
|
|
26
|
+
}
|
|
27
|
+
}
|
package/src/complex.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export function complex(re = 0, im = 0) {
|
|
2
|
+
return { re: Number(re), im: Number(im) };
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function add(a, b) {
|
|
6
|
+
return complex(a.re + b.re, a.im + b.im);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function sub(a, b) {
|
|
10
|
+
return complex(a.re - b.re, a.im - b.im);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function mul(a, b) {
|
|
14
|
+
return complex(a.re * b.re - a.im * b.im, a.re * b.im + a.im * b.re);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function div(a, b) {
|
|
18
|
+
const denom = b.re * b.re + b.im * b.im;
|
|
19
|
+
if (denom === 0) {
|
|
20
|
+
throw new Error("Division by zero complex number");
|
|
21
|
+
}
|
|
22
|
+
return complex((a.re * b.re + a.im * b.im) / denom, (a.im * b.re - a.re * b.im) / denom);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function sqrtComplex(z) {
|
|
26
|
+
const r = Math.hypot(z.re, z.im);
|
|
27
|
+
const re = Math.sqrt((r + z.re) / 2);
|
|
28
|
+
const imSign = z.im < 0 ? -1 : 1;
|
|
29
|
+
const im = imSign * Math.sqrt(Math.max((r - z.re) / 2, 0));
|
|
30
|
+
return complex(re, im);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function fromReal(x) {
|
|
34
|
+
return complex(x, 0);
|
|
35
|
+
}
|
package/src/index.js
ADDED
package/src/material.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { add, complex, div, fromReal, mul, sqrtComplex, sub } from "./complex.js";
|
|
2
|
+
|
|
3
|
+
export const EV_TO_NM = 1.0 / 8.0655477e-4;
|
|
4
|
+
export const HARTREE_EV = 27.2116;
|
|
5
|
+
|
|
6
|
+
const MATERIAL_TABLE = {
|
|
7
|
+
au: { rs: 3.0, eps0: 10.0, gammadAu: (0.66 / HARTREE_EV) / 10.0 },
|
|
8
|
+
gold: { rs: 3.0, eps0: 10.0, gammadAu: (0.66 / HARTREE_EV) / 10.0 },
|
|
9
|
+
ag: { rs: 3.0, eps0: 3.3, gammadAu: (0.66 / HARTREE_EV) / 30.0 },
|
|
10
|
+
silver: { rs: 3.0, eps0: 3.3, gammadAu: (0.66 / HARTREE_EV) / 30.0 },
|
|
11
|
+
al: { rs: 2.07, eps0: 1.0, gammadAu: 1.06 / HARTREE_EV },
|
|
12
|
+
aluminum: { rs: 2.07, eps0: 1.0, gammadAu: 1.06 / HARTREE_EV }
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
function mapInput(values, fn) {
|
|
16
|
+
if (Array.isArray(values)) {
|
|
17
|
+
return values.map(fn);
|
|
18
|
+
}
|
|
19
|
+
return fn(values);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function makeDrudeMaterial(name) {
|
|
23
|
+
const key = String(name).toLowerCase();
|
|
24
|
+
const row = MATERIAL_TABLE[key];
|
|
25
|
+
if (!row) {
|
|
26
|
+
throw new Error(`Unknown material '${name}'. Expected one of: Au, Ag, Al.`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const density = 3.0 / (4.0 * Math.PI * row.rs ** 3);
|
|
30
|
+
const wpAu = Math.sqrt(4.0 * Math.PI * density);
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
name,
|
|
34
|
+
eps0: row.eps0,
|
|
35
|
+
gammad: row.gammadAu * HARTREE_EV,
|
|
36
|
+
wp: wpAu * HARTREE_EV
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function drudeEpsilon(materialName, wavelengthNm) {
|
|
41
|
+
const m = makeDrudeMaterial(materialName);
|
|
42
|
+
return mapInput(wavelengthNm, (wl) => {
|
|
43
|
+
const w = EV_TO_NM / Number(wl);
|
|
44
|
+
const numerator = fromReal(m.wp ** 2);
|
|
45
|
+
const denom = mul(fromReal(w), add(fromReal(w), complex(0, m.gammad)));
|
|
46
|
+
return sub(fromReal(m.eps0), div(numerator, denom));
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function constantEpsilon(value, wavelengthNm) {
|
|
51
|
+
return mapInput(wavelengthNm, () => complex(value, 0));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function wavenumberInMedium(wavelengthNm, epsilonComplex) {
|
|
55
|
+
const computeOne = (wl, eps) => {
|
|
56
|
+
const factor = (2.0 * Math.PI) / Number(wl);
|
|
57
|
+
return mul(fromReal(factor), sqrtComplex(eps));
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
if (Array.isArray(wavelengthNm)) {
|
|
61
|
+
return wavelengthNm.map((wl, i) => computeOne(wl, epsilonComplex[i]));
|
|
62
|
+
}
|
|
63
|
+
return computeOne(wavelengthNm, epsilonComplex);
|
|
64
|
+
}
|