diff --git a/src/scgenerator/data/materials.toml b/src/scgenerator/data/materials.toml index f79930d..08478db 100644 --- a/src/scgenerator/data/materials.toml +++ b/src/scgenerator/data/materials.toml @@ -43,6 +43,7 @@ reference = ["CDGM Zemax catalog 2017-09 (obtained from http://www.cdgmgd.com)"] [air] a = 0.1358 b = 3.64e-5 +atomic_mass = 4.809e-26 [air.sellmeier] B = [57921050000.0, 1679170000.0] @@ -60,6 +61,7 @@ source = "Pigeon, J. J., Tochitsky, S. Y., Welch, E. C., & Joshi, C. (2016). Mea [nitrogen] a = 0.137 b = 1.709e-5 +atomic_mass = 2.3259e-26 [nitrogen.sellmeier] B = [32431570000.0] @@ -80,6 +82,7 @@ a = 0.00346 b = 2.38e-5 ionization_energy = 3.9393356074281e-18 atomic_number = 2 +atomic_mass = 6.646477e-27 [helium.sellmeier] B = [2.16463842e-5, 2.10561127e-7, 4.7509272e-5] @@ -115,6 +118,7 @@ n2 = 3.1e-25 [hydrogen] a = 0.02453 b = 2.651e-5 +atomic_mass = 1.674e-27 [hydrogen.sellmeier] B = [0.0148956, 0.0049037] @@ -135,6 +139,7 @@ a = 0.02135 b = 1.709e-5 ionization_energy = 3.45501365359425e-18 atomic_number = 10 +atomic_mass = 3.35092e-26 [neon.sellmeier] B = [1281450000.0, 22048600000.0] @@ -154,6 +159,7 @@ a = 0.1355 b = 3.201e-5 ionization_energy = 2.5249661793774e-18 atomic_number = 18 +atomic_mass = 6.6338e-26 [argon.sellmeier] B = [2501410000.0, 500283000.0, 52234300000.0] @@ -211,6 +217,7 @@ a = 0.2349 b = 3.978e-5 ionization_energy = 2.2429831039374e-18 atomic_number = 36 +atomic_mass = 1.3915e-25 [krypton.sellmeier] B = [2536370000.0, 2736490000.0, 62080200000.0] @@ -230,6 +237,7 @@ a = 0.425 b = 5.105e-5 ionization_energy = 1.94342415157935 atomic_number = 54 +atomic_mass = 2.18017e-25 [xenon.sellmeier] B = [3228690000.0, 3553930000.0, 60676400000.0] @@ -247,6 +255,7 @@ source = "Wahlstrand, J. K., Cheng, Y. H., & Milchberg, H. M. (2012). High field [vacuum] a = 0 b = 0 +atomic_mass = 0 [vacuum.sellmeier] B = [] diff --git a/src/scgenerator/physics/materials.py b/src/scgenerator/physics/materials.py index 8d8e073..c8cd186 100644 --- a/src/scgenerator/physics/materials.py +++ b/src/scgenerator/physics/materials.py @@ -2,6 +2,7 @@ import functools from typing import Any import numpy as np +from dataclasses import dataclass, field from .. import utils from ..cache import np_cache @@ -10,6 +11,76 @@ from . import units from .units import NA, c, kB, epsilon0 +@dataclass +class Sellmeier: + B: list[float] = field(default_factory=list) + C: list[float] = field(default_factory=list) + pressure_ref: float = 101325 + temperature_ref: float = 273.15 + kind: int = 2 + constant: float = 0 + + def chi(self, wl: np.ndarray, temperature=None, pressure=None) -> np.ndarray: + """n^2 - 1""" + chi = np.zeros_like(wl) # = n^2 - 1 + if self.kind == 1: + for b, c_ in zip(self.B, self.C): + chi += wl ** 2 * b / (wl ** 2 - c_) + elif self.kind == 2: # gives n-1 + for b, c_ in zip(self.B, self.C): + chi += b / (c_ - 1 / wl ** 2) + chi += self.constant + chi = (chi + 1) ** 2 - 1 + elif self.kind == 3: # Schott formula + for i, b in reversed(list(enumerate(self.B))): + chi += b * wl ** (-2 * (i - 1)) + chi = chi - 1 + else: + raise ValueError(f"kind {self.kind} is not recognized.") + + if temperature is not None: + chi *= self.temperature_ref / temperature + + if pressure is not None: + chi *= pressure / self.pressure_ref + return chi + + +class GasInfo: + sellmeier: Sellmeier + n2: float + atomic_number: int + atomic_mass: float + + def __init__(self, gas_name: str): + self.mat_dico = utils.load_material_dico(gas_name) + self.n2 = self.mat_dico["kerr"]["n2"] + self.atomic_mass = self.mat_dico["atomic_mass"] + self.atomic_number = self.mat_dico["atomic_number"] + + s = self.mat_dico.get("sellmeier", {}) + self.sellmeier = Sellmeier( + **{ + newk: s.get(k, None) + for newk, k in zip( + ["B", "C", "pressure_ref", "temperature_ref", "kind", "constant"], + ["B", "C", "P0", "T0", "kind", "const"], + ) + if k in s + } + ) + + def pressure_from_density(self, density: float, temperature: float = None) -> float: + temperature = temperature or self.sellmeier.temperature_ref + return kB * temperature * density / self.atomic_mass + + def get(self, key, default=None): + return self.mat_dico.get(key, default) + + def __getitem__(self, key): + return self.mat_dico[key] + + @np_cache def n_gas_2( wl_for_disp: np.ndarray, gas_name: str, pressure: float, temperature: float, ideal_gas: bool @@ -82,7 +153,7 @@ def number_density_van_der_waals( b = material_dico.get("b", 0) if b is None else b pressure = material_dico["sellmeier"].get("P0", 101325) if pressure is None else pressure temperature = ( - material_dico["sellmeier"].get("t0", 273.15) if temperature is None else temperature + material_dico["sellmeier"].get("T0", 273.15) if temperature is None else temperature ) else: a = 0 if a is None else a