removed auto computation, renamed some stuff

This commit is contained in:
Benoît Sierro
2023-07-26 10:18:56 +02:00
parent 693646fd51
commit e2cbe3a8ac
12 changed files with 174 additions and 351 deletions

View File

@@ -94,7 +94,7 @@ effective_mode_diameter = 10.1e-6
name = "PM2000D_2" name = "PM2000D_2"
length = 0.01 length = 0.01
n2 = 3.4e-20 n2 = 3.4e-20
A_eff_file = "PM2000D/PM2000D_A_eff_marcuse.npz" effective_area_file = "PM2000D/PM2000D_A_eff_marcuse.npz"
dispersion_file = "PM2000D/Dispersion/PM2000D_1 extrapolated 0 4.npz" dispersion_file = "PM2000D/Dispersion/PM2000D_1 extrapolated 0 4.npz"
[Fiber.variable] # this variable parameter will be applied to PM2000D_2 [Fiber.variable] # this variable parameter will be applied to PM2000D_2
@@ -133,9 +133,9 @@ and specify the parameters it needs
pcf : pcf :
pitch: float pcf_pitch: float
distance between air holes in m distance between air holes in m
pitch_ratio: float 0.2 < pitch_ratio < 0.8 pcf_pitch_ratio: float 0.2 < pcf_pitch_ratio < 0.8
ratio hole diameter/pich ratio hole diameter/pich
marcatili, marcatili_adjusted, hasan : marcatili, marcatili_adjusted, hasan :
@@ -189,11 +189,11 @@ effective_mode_diameter : float, optional
n2 : float, optional n2 : float, optional
non linear refractive index in m^2/W non linear refractive index in m^2/W
A_eff : float, optional effective_area : float, optional
effective mode field area effective mode field area
A_eff_file : str, optional effective_area_file : str, optional
file containing an A_eff array (in m^2) as function of a wavelength array (in m) file containing an effective_area array (in m^2) as function of a wavelength array (in m)
length: float, optional length: float, optional
length of the fiber in m. default : 1 length of the fiber in m. default : 1

View File

@@ -1,25 +0,0 @@
## add parameter
- add it to ```utils.parameters```
- add it to README.md
- add the necessary Rules in ```utils.parameters```
- optional : add a default value
- optional : add to mandatory_parameters
## complicated Rule conditions
- add the desired parameters to the init of the operator
- raise OperatorError if the conditions are not met
## operators
There are 3 kinds of operators
- `SpecOperator(spec: np.ndarray, z: float) -> np.ndarray` : operate on the spectrum
- Envelope nonlinear operator used in the solver
- Full field nonlinear operator used in the solver
- `FieldOperator(field: np.ndarray, z: float) -> np.ndarray` : operate on the field
- SPM
- Raman
- Ionization
- `VariableQuantity(z: float) -> float | np.ndarray` : return the value of a certain quantity along the fiber depending on z
- dispersion
- refractive index
- full field nonlinear prefactor
- nonlinear parameter (chi3, n2, gamma)

View File

@@ -12,7 +12,7 @@ z_num = 128
length = 0.3 length = 0.3
dispersion_file = "PM2000D_2 extrapolated 4 0.npz" dispersion_file = "PM2000D_2 extrapolated 4 0.npz"
interpolation_degree = 12 interpolation_degree = 12
A_eff_file = "PM2000D_A_eff_marcuse.npz" effective_area_file = "PM2000D_A_eff_marcuse.npz"
n2 = 4.5e-20 n2 = 4.5e-20

57
playground.py Normal file
View File

@@ -0,0 +1,57 @@
from __future__ import annotations
import inspect
import os
import numpy as np
def make_grid(
dt: float | None = None,
period: float | None = None,
t_num: float | None = None,
wl_min: float | None = None,
):
...
class Root:
dt: float = Param()
period: float
t_num: int
fiber: Fiber
pulses: PulseTrain
def __init__(self, name: str):
...
@dt.register
def dt_from_lmin(wavelength_max: float, wavelength_pump: float):
return 1 / 6e8 * 1 / (1 / wavelength_pump - 1 / wavelength_max)
class PulseTrain:
pulse_width: float
shape: str = "gaussian"
peak_power: float
quantum_noise: bool = True
def load_noise_spectrum(self, path: os.PathLike):
...
class Fiber:
beta2_arr: np.ndarray
length: float
params = Root(dt=2e-15, t_num=1024)
pulses = params.pulse_train
pulses.pulse_width = 50e-15
pulses.shape = "sech"
pulses.load_noise_spectrum(dBm="./some_noise.csv", v_ref=3)
fiber = params.fiber
fiber.length = 0.2

View File

@@ -1,21 +0,0 @@
{
"lambda0": 835e-9,
"P0": 10e3,
"T0": 28.4e-15,
"z_targets": [0, 1, 128],
"chirp": 0,
"alpha": 0,
"fiber_type": "PCF",
"pitch": 1.55e-6,
"pitch_ratio": 0.37,
"gamma": 0.11,
"pulse_shape":"gaussian",
"dt": 1e-15,
"nt": 16384,
"frep": 80e6,
"behaviors": ["spm", "ss", "raman"],
"raman_rf": "stolen",
"adapt_step_size": true,
"error_ok": 1e-8,
"vmin_log": -40
}

View File

@@ -1,198 +0,0 @@
{
"air": {
"sellmeier": {
"B": [57921050000.0, 1679170000.0],
"C": [238018500000000.0, 57362000000000.0],
"kind": 2,
"P0": 101325,
"T0": 288.15
}
},
"nitrogen": {
"a": 0.137,
"b": 1.709e-05,
"sellmeier": {
"B": [32431570000.0],
"C": [144000000000000.0],
"kind": 2,
"P0": 101325,
"T0": 273.15,
"const": 6.8552e-05
},
"kerr": {
"source": "Wahlstrand, J. K., Cheng, Y. H., & Milchberg, H. M. (2012). High field optical nonlinearity and the Kramers-Kronig relations. Physical review letters, 109(11), 113904.",
"P0": 30.4e3,
"T0": 273.15,
"n2": 2.2e-23
}
},
"helium": {
"a": 0.00346,
"b": 2.38e-05,
"sellmeier": {
"source": "A. Ermolov, K. F. Mak, M. H. Frosz, J. C. Travers, P. St. J. Russell, Supercontinuum generation in the vacuum ultraviolet through dispersive-wave and soliton-plasma interaction in a noble-gas-filled hollow-core photonic crystal fiber, Phys. Rev. A 92, 033821 (2015)",
"B": [2.16463842e-5, 2.10561127e-7, 4.7509272e-5],
"C": [-6.80769781e-16, 5.13251289e-15, 3.18621354e-15],
"kind": 1,
"P0": 101325,
"T0": 273.15
},
"kerr": {
"source": "Wahlstrand, J. K., Cheng, Y. H., & Milchberg, H. M. (2012). High field optical nonlinearity and the Kramers-Kronig relations. Physical review letters, 109(11), 113904.",
"P0": 30.4e3,
"T0": 273.15,
"n2": 3.1e-25
}
},
"helium_alt": {
"a": 0.00346,
"b": 2.38e-05,
"sellmeier": {
"source": " C. Cuthbertson and M. Cuthbertson. The refraction and dispersion of neon and helium. Proc. R. Soc. London A 135, 40-47 (1936)",
"B": [14755297000.0],
"C": [426297400000000.0],
"kind": 2,
"P0": 101325,
"T0": 273.15
},
"kerr": {
"P0": 30.4e3,
"T0": 273.15,
"n2": 3.1e-25
}
},
"hydrogen": {
"a": 0.02453,
"b": 2.651e-05,
"sellmeier": {
"source": "E. R. Peck and S. Hung. Refractivity and dispersion of hydrogen in the visible and near infrared, J. Opt. Soc. Am. 67, 1550-1554 (1977)",
"B": [0.0148956, 0.0049037],
"C": [180.7e-12, 92e-12],
"kind": 2,
"P0": 101325,
"T0": 273.15
},
"kerr": {
"source": "Shelton, D. P., & Rice, J. E. (1994). Measurements and calculations of the hyperpolarizabilities of atoms and small molecules in the gas phase. Chemical Reviews, 94(1), 3-29",
"P0": 30.4e3,
"T0": 273.15,
"n2": 6.36e-24
}
},
"neon": {
"a": 0.02135,
"b": 1.709e-05,
"sellmeier": {
"B": [1281450000.0, 22048600000.0],
"C": [184661000000000.0, 376840000000000.0],
"kind": 2,
"P0": 101325,
"T0": 273.15
},
"kerr": {
"source": "Wahlstrand, J. K., Cheng, Y. H., & Milchberg, H. M. (2012). High field optical nonlinearity and the Kramers-Kronig relations. Physical review letters, 109(11), 113904.",
"P0": 30.4e3,
"T0": 273.15,
"n2": 8.7e-25
}
},
"argon": {
"a": 0.1355,
"b": 3.201e-05,
"sellmeier": {
"source": "A. Bideau-Mehu, Y. Guern, R. Abjean, A. Johannin-Gilles. Measurement of refractive indices of neon, argon, krypton and xenon in the 253.7-140.4 nm wavelength range. Dispersion relations and estimated oscillator strengths of the resonance lines. J. Quant. Spectrosc. Rad. Transfer 25, 395-402 (1981)",
"B": [2501410000.0, 500283000.0, 52234300000.0],
"C": [91012000000000.0, 87892000000000.0, 214020000000000.0],
"kind": 2,
"P0": 101325,
"T0": 273.15
},
"kerr": {
"source": "Wahlstrand, J. K., Cheng, Y. H., & Milchberg, H. M. (2012). High field optical nonlinearity and the Kramers-Kronig relations. Physical review letters, 109(11), 113904.",
"P0": 30.4e3,
"T0": 273.15,
"n2": 9.7e-24
}
},
"argon_alt": {
"a": 0.1355,
"b": 3.201e-05,
"sellmeier": {
"source": "A. Börzsönyi, Z. Heiner, M. P. Kalashnikov, A. P. Kovács, and K. Osvay, Dispersion measurement of inert gases and gas mixtures at 800 nm, Appl. Opt. 47, 4856-4863 (2008)",
"B": [20332.29e-8, 34458.31e-8],
"C": [206.12e-18, 8.066e-15],
"kind": 1,
"P0": 101325,
"T0": 273.15
},
"kerr": {
"source": "Wahlstrand, J. K., Cheng, Y. H., & Milchberg, H. M. (2012). High field optical nonlinearity and the Kramers-Kronig relations. Physical review letters, 109(11), 113904.",
"P0": 30.4e3,
"T0": 273.15,
"n2": 9.7e-24
}
},
"argon_alt2": {
"a": 0.1355,
"b": 3.201e-05,
"sellmeier": {
"source": "E. R. Peck and D. J. Fisher. Dispersion of argon, J. Opt. Soc. Am. 54, 1362-1364 (1964)",
"B": [3.0182943e-2],
"C": [144e12],
"const": 6.7867e-5,
"kind": 2,
"P0": 101325,
"T0": 273.15
},
"kerr": {
"source": "Wahlstrand, J. K., Cheng, Y. H., & Milchberg, H. M. (2012). High field optical nonlinearity and the Kramers-Kronig relations. Physical review letters, 109(11), 113904.",
"P0": 30.4e3,
"T0": 273.15,
"n2": 9.7e-24
}
},
"krypton": {
"a": 0.2349,
"b": 3.978e-05,
"sellmeier": {
"B": [2536370000.0, 2736490000.0, 62080200000.0],
"C": [65474200000000.0, 73698000000000.0, 181080000000000.0],
"kind": 2,
"P0": 101325,
"T0": 273.15
},
"kerr": {
"source": "Wahlstrand, J. K., Cheng, Y. H., & Milchberg, H. M. (2012). High field optical nonlinearity and the Kramers-Kronig relations. Physical review letters, 109(11), 113904.",
"P0": 30.4e3,
"T0": 273.15,
"n2": 2.2e-23
}
},
"xenon": {
"a": 0.425,
"b": 5.105e-05,
"sellmeier": {
"B": [3228690000.0, 3553930000.0, 60676400000.0],
"C": [46301000000000.0, 59578000000000.0, 112740000000000.0],
"kind": 2,
"P0": 101325,
"T0": 273.15
},
"kerr": {
"source": "Wahlstrand, J. K., Cheng, Y. H., & Milchberg, H. M. (2012). High field optical nonlinearity and the Kramers-Kronig relations. Physical review letters, 109(11), 113904.",
"P0": 30.4e3,
"T0": 273.15,
"n2": 5.8e-23
}
}
}

View File

@@ -318,8 +318,6 @@ default_rules: list[Rule] = [
Rule(["input_time", "input_field"], pulse.load_custom_field), Rule(["input_time", "input_field"], pulse.load_custom_field),
Rule("spec_0", lambda fft, field_0: fft(field_0)), Rule("spec_0", lambda fft, field_0: fft(field_0)),
Rule("field_0", lambda ifft, spec_0: ifft(spec_0)), Rule("field_0", lambda ifft, spec_0: ifft(spec_0)),
Rule("spec_0", utils.load_previous_spectrum, ["recovery_data_dir"], priorities=4),
Rule("spec_0", utils.load_previous_spectrum, priorities=3),
*Rule.deduce( *Rule.deduce(
["pre_field_0", "peak_power", "energy", "width"], ["pre_field_0", "peak_power", "energy", "width"],
pulse.adjust_custom_field, pulse.adjust_custom_field,
@@ -355,7 +353,7 @@ default_rules: list[Rule] = [
Rule( Rule(
"n_eff", "n_eff",
fiber.n_eff_pcf, fiber.n_eff_pcf,
["wl_for_disp", "pitch", "pitch_ratio"], ["wl_for_disp", "pcf_pitch", "pcf_pitch_ratio"],
conditions=dict(model="pcf"), conditions=dict(model="pcf"),
), ),
Rule("n0", lambda w0_ind, n_eff: n_eff[w0_ind]), Rule("n0", lambda w0_ind, n_eff: n_eff[w0_ind]),
@@ -370,18 +368,17 @@ default_rules: list[Rule] = [
lambda beta2_arr, wl_for_disp: wl_for_disp[math.argclosest(beta2_arr, 0)], lambda beta2_arr, wl_for_disp: wl_for_disp[math.argclosest(beta2_arr, 0)],
), ),
# Fiber nonlinearity # Fiber nonlinearity
Rule("A_eff", fiber.A_eff_from_V), Rule("effective_area", fiber.effective_area_from_V),
Rule("A_eff", fiber.A_eff_from_diam), Rule("effective_area", fiber.effective_area_from_diam),
Rule("A_eff", fiber.A_eff_hasan, conditions=dict(model="hasan")), Rule("effective_area", fiber.effective_area_hasan, conditions=dict(model="hasan")),
Rule("A_eff", fiber.A_eff_from_gamma, priorities=-1), Rule("effective_area", fiber.effective_area_from_gamma, priorities=-1),
Rule("A_eff", fiber.A_eff_marcatili, priorities=-2), Rule("effective_area", fiber.elfective_area_marcatili, priorities=-2),
Rule("A_eff_arr", fiber.A_eff_from_V, ["core_radius", "V_eff_arr"]), Rule("effecive_area_arr", fiber.effective_area_from_V, ["core_radius", "V_eff_arr"]),
Rule("A_eff_arr", fiber.load_custom_A_eff), Rule("effecive_area_arr", fiber.load_custom_effective_area),
# Rule("A_eff_arr", fiber.constant_A_eff_arr, priorities=-1),
Rule( Rule(
"V_eff", "V_eff",
fiber.V_parameter_koshiba, fiber.V_parameter_koshiba,
["wavelength", "pitch", "pitch_ratio"], ["wavelength", "pcf_pitch", "pcf_pitch_ratio"],
conditions=dict(model="pcf"), conditions=dict(model="pcf"),
), ),
Rule( Rule(
@@ -399,7 +396,7 @@ default_rules: list[Rule] = [
Rule("n2", lambda: 2.2e-20, priorities=-1), Rule("n2", lambda: 2.2e-20, priorities=-1),
Rule("gamma", lambda gamma_arr: gamma_arr[0], priorities=-1), Rule("gamma", lambda gamma_arr: gamma_arr[0], priorities=-1),
Rule("gamma", fiber.gamma_parameter), Rule("gamma", fiber.gamma_parameter),
Rule("gamma_arr", fiber.gamma_parameter, ["n2", "w0", "A_eff_arr"]), Rule("gamma_arr", fiber.gamma_parameter, ["n2", "w0", "effecive_area_arr"]),
# Raman # Raman
Rule(["hr_w", "raman_fraction"], fiber.delayed_raman_w), Rule(["hr_w", "raman_fraction"], fiber.delayed_raman_w),
Rule("raman_fraction", fiber.raman_fraction), Rule("raman_fraction", fiber.raman_fraction),

View File

@@ -315,11 +315,13 @@ def full_field_spm(raman_fraction: float, w: np.ndarray, chi3: float) -> FieldOp
################################################## ##################################################
def variable_gamma(n2_op: VariableQuantity, w0: float, A_eff: float, t_num: int) -> SpecOperator: def variable_gamma(
n2_op: VariableQuantity, w0: float, effective_area: float, t_num: int
) -> SpecOperator:
arr = np.ones(t_num) arr = np.ones(t_num)
def operate(z: float) -> np.ndarray: def operate(z: float) -> np.ndarray:
return arr * fiber.gamma_parameter(n2_op(z), w0, A_eff) return arr * fiber.gamma_parameter(n2_op(z), w0, effective_area)
return operate return operate

View File

@@ -7,8 +7,7 @@ from dataclasses import dataclass, field, fields
from functools import lru_cache, wraps from functools import lru_cache, wraps
from math import isnan from math import isnan
from pathlib import Path from pathlib import Path
from typing import (Any, Callable, ClassVar, Iterable, Iterator, Set, Type, from typing import Any, Callable, ClassVar, Iterable, Iterator, Set, Type, TypeVar
TypeVar)
import numpy as np import numpy as np
@@ -229,7 +228,7 @@ class Parameter:
when displaying the value when displaying the value
example : (1e-6, "MW") will mean the value 1.12e6 is displayed as '1.12MW' example : (1e-6, "MW") will mean the value 1.12e6 is displayed as '1.12MW'
""" """
self.__validator = validator self._validator = validator
self.converter = converter self.converter = converter
self.default = default self.default = default
self.display_info = display_info self.display_info = display_info
@@ -247,28 +246,25 @@ class Parameter:
def __get__(self, instance: Parameters, owner): def __get__(self, instance: Parameters, owner):
if instance is None: if instance is None:
return self return self
if self.name not in instance._param_dico:
try:
instance._evaluator.compute(self.name)
except EvaluatorError:
pass
return instance._param_dico.get(self.name) return instance._param_dico.get(self.name)
# return instance.__dict__[self.name]
def __delete__(self, instance): def __delete__(self, instance):
raise AttributeError("Cannot delete parameter") if self.name in instance._param_dico:
del instance._param_dico[self.name]
def __set__(self, instance: Parameters, value): def __set__(self, instance: Parameters, value):
if isinstance(value, Parameter): if instance._frozen:
if self.default is not None: raise AttributeError("Parameters instance is frozen and can no longer be modified")
if isinstance(value, Parameter) and self.default is not None:
instance._param_dico[self.name] = copy(self.default) instance._param_dico[self.name] = copy(self.default)
else: return
is_value, value = self.validate(value) is_value, value = self.validate(value)
if is_value: if is_value:
instance._param_dico[self.name] = value instance._param_dico[self.name] = value
else: else:
if self.name in instance._param_dico: self.__delete__(instance)
del instance._param_dico[self.name]
def display(self, num: float) -> str: def display(self, num: float) -> str:
if self.display_info is None: if self.display_info is None:
@@ -291,12 +287,9 @@ class Parameter:
if is_value: if is_value:
if self.converter is not None: if self.converter is not None:
v = self.converter(v) v = self.converter(v)
self.__validator(self.name, v) self._validator(self.name, v)
return is_value, v return is_value, v
def validator(self, name, value):
self.validate(value)
@dataclass(repr=False) @dataclass(repr=False)
class Parameters: class Parameters:
@@ -308,11 +301,10 @@ class Parameters:
_param_dico: dict[str, Any] = field(init=False, default_factory=dict, repr=False) _param_dico: dict[str, Any] = field(init=False, default_factory=dict, repr=False)
_evaluator: Evaluator = field(init=False, repr=False) _evaluator: Evaluator = field(init=False, repr=False)
_p_names: ClassVar[Set[str]] = set() _p_names: ClassVar[Set[str]] = set()
_frozen: bool = field(init=False, default=False, repr=False)
# root # root
name: str = Parameter(string, default="no name") name: str = Parameter(string, default="no name")
prev_data_dir: str = Parameter(string)
recovery_data_dir: str = Parameter(string)
output_path: Path = Parameter(type_checker(Path), default=Path("sc_data"), converter=Path) output_path: Path = Parameter(type_checker(Path), default=Path("sc_data"), converter=Path)
# fiber # fiber
@@ -323,11 +315,11 @@ class Parameters:
loss: str = Parameter(literal("capillary")) loss: str = Parameter(literal("capillary"))
loss_file: str = Parameter(string) loss_file: str = Parameter(string)
effective_mode_diameter: float = Parameter(positive(float, int)) effective_mode_diameter: float = Parameter(positive(float, int))
A_eff: float = Parameter(non_negative(float, int)) effective_area: float = Parameter(non_negative(float, int))
A_eff_file: str = Parameter(string) effective_area_file: str = Parameter(string)
numerical_aperture: float = Parameter(in_range_excl(0, 1)) numerical_aperture: float = Parameter(in_range_excl(0, 1))
pitch: float = Parameter(in_range_excl(0, 1e-3), display_info=(1e6, "μm")) pcf_pitch: float = Parameter(in_range_excl(0, 1e-3), display_info=(1e6, "μm"))
pitch_ratio: float = Parameter(in_range_excl(0, 1)) pcf_pitch_ratio: float = Parameter(in_range_excl(0, 1))
core_radius: float = Parameter(in_range_excl(0, 1e-3), display_info=(1e6, "μm")) core_radius: float = Parameter(in_range_excl(0, 1e-3), display_info=(1e6, "μm"))
he_mode: tuple[int, int] = Parameter(int_pair, default=(1, 1)) he_mode: tuple[int, int] = Parameter(int_pair, default=(1, 1))
fit_parameters: tuple[int, int] = Parameter(float_pair, default=(0.08, 200e-9)) fit_parameters: tuple[int, int] = Parameter(float_pair, default=(0.08, 200e-9))
@@ -421,7 +413,7 @@ class Parameters:
alpha_arr: np.ndarray = Parameter(type_checker(np.ndarray)) alpha_arr: np.ndarray = Parameter(type_checker(np.ndarray))
alpha: float = Parameter(non_negative(float, int)) alpha: float = Parameter(non_negative(float, int))
gamma_arr: np.ndarray = Parameter(type_checker(np.ndarray)) gamma_arr: np.ndarray = Parameter(type_checker(np.ndarray))
A_eff_arr: np.ndarray = Parameter(type_checker(np.ndarray)) effective_area_arr: np.ndarray = Parameter(type_checker(np.ndarray))
spectrum_factor: float = Parameter(type_checker(float)) spectrum_factor: float = Parameter(type_checker(float))
c_to_a_factor: np.ndarray = Parameter(type_checker(float, int, np.ndarray)) c_to_a_factor: np.ndarray = Parameter(type_checker(float, int, np.ndarray))
w: np.ndarray = Parameter(type_checker(np.ndarray)) w: np.ndarray = Parameter(type_checker(np.ndarray))
@@ -524,7 +516,7 @@ class Parameters:
"wl_for_disp", "wl_for_disp",
"alpha", "alpha",
"gamma_arr", "gamma_arr",
"A_eff_arr", "effective_area_arr",
"nonlinear_op", "nonlinear_op",
"linear_op", "linear_op",
} }

View File

@@ -205,7 +205,7 @@ def n_eff_marcatili_adjusted(wl_for_disp, n_gas_2, core_radius, he_mode=(1, 1),
return np.sqrt(n_gas_2 - (wl_for_disp * u / (pipi * corrected_radius)) ** 2) return np.sqrt(n_gas_2 - (wl_for_disp * u / (pipi * corrected_radius)) ** 2)
def A_eff_marcatili(core_radius: float) -> float: def effective_area_marcatili(core_radius: float) -> float:
"""Effective mode-field area for fundamental mode hollow capillaries """Effective mode-field area for fundamental mode hollow capillaries
Parameters Parameters
@@ -353,7 +353,7 @@ def n_eff_hasan(
return np.sqrt(n_eff_2) return np.sqrt(n_eff_2)
def A_eff_hasan(core_radius, capillary_num, capillary_spacing): def effective_area_hasan(core_radius, capillary_num, capillary_spacing):
"""computed the effective mode area """computed the effective mode area
Parameters Parameters
@@ -367,7 +367,7 @@ def A_eff_hasan(core_radius, capillary_num, capillary_spacing):
Returns Returns
------- -------
A_eff : float effective_area: float
""" """
M_f = 1.5 / (1 - 0.5 * np.exp(-0.245 * capillary_num)) M_f = 1.5 / (1 - 0.5 * np.exp(-0.245 * capillary_num))
return M_f * core_radius**2 * np.exp((capillary_spacing / 22e-6) ** 2.5) return M_f * core_radius**2 * np.exp((capillary_spacing / 22e-6) ** 2.5)
@@ -405,7 +405,7 @@ def V_eff_step_index(
return pi2cn / l return pi2cn / l
def V_parameter_koshiba(l: np.ndarray, pitch: float, pitch_ratio: float) -> float: def V_parameter_koshiba(l: np.ndarray, pcf_pitch: float, pcf_pitch_ratio: float) -> float:
"""returns the V parameter according to Koshiba2004 """returns the V parameter according to Koshiba2004
@@ -413,9 +413,9 @@ def V_parameter_koshiba(l: np.ndarray, pitch: float, pitch_ratio: float) -> floa
---------- ----------
l : np.ndarray, shape (n,) l : np.ndarray, shape (n,)
wavelength wavelength
pitch : float pcf_pitch : float
distance between air holes in m distance between air holes in m
pitch_ratio : float pcf_pitch_ratio : float
ratio diameter of holes / distance ratio diameter of holes / distance
w0 : float w0 : float
pump angular frequency pump angular frequency
@@ -425,11 +425,11 @@ def V_parameter_koshiba(l: np.ndarray, pitch: float, pitch_ratio: float) -> floa
float float
effective mode field area effective mode field area
""" """
ratio_l = l / pitch ratio_l = l / pcf_pitch
n_co = 1.45 n_co = 1.45
a_eff = pitch / np.sqrt(3) a_eff = pcf_pitch / np.sqrt(3)
pi2a = pipi * a_eff pi2a = pipi * a_eff
A, B = saitoh_paramters(pitch_ratio) A, B = saitoh_paramters(pcf_pitch_ratio)
V = A[0] + A[1] / (1 + A[2] * np.exp(A[3] * ratio_l)) V = A[0] + A[1] / (1 + A[2] * np.exp(A[3] * ratio_l))
@@ -439,7 +439,7 @@ def V_parameter_koshiba(l: np.ndarray, pitch: float, pitch_ratio: float) -> floa
return V_eff return V_eff
def A_eff_from_V(core_radius: float, V_eff: T) -> T: def effective_area_from_V(core_radius: float, V_eff: T) -> T:
"""According to Marcuse1978 """According to Marcuse1978
Parameters Parameters
@@ -452,7 +452,8 @@ def A_eff_from_V(core_radius: float, V_eff: T) -> T:
Returns Returns
------- -------
T T
A_eff effective_area
""" """
out = np.ones_like(V_eff) out = np.ones_like(V_eff)
out[V_eff > 0] = core_radius * ( out[V_eff > 0] = core_radius * (
@@ -533,20 +534,21 @@ def HCPCF_dispersion(
return beta2(w, n_eff) return beta2(w, n_eff)
def gamma_parameter(n2: float, w0: float, A_eff: T) -> T: def gamma_parameter(n2: float, w0: float, effective_area: T) -> T:
if isinstance(A_eff, np.ndarray): if isinstance(effective_area, np.ndarray):
A_eff_term = np.sqrt(A_eff * A_eff[0]) effective_area_term = np.sqrt(effective_area * effective_area[0])
else: else:
A_eff_term = A_eff effective_area_term = effective_area
return n2 * w0 / (A_eff_term * c)
return n2 * w0 / (effective_area_term * c)
def constant_A_eff_arr(l: np.ndarray, A_eff: float) -> np.ndarray: def constant_effective_area_arr(l: np.ndarray, effective_area: float) -> np.ndarray:
return np.ones_like(l) * A_eff return np.ones_like(l) * effective_area
@np_cache @np_cache
def n_eff_pcf(wl_for_disp: np.ndarray, pitch: float, pitch_ratio: float) -> np.ndarray: def n_eff_pcf(wl_for_disp: np.ndarray, pcf_pitch: float, pcf_pitch_ratio: float) -> np.ndarray:
""" """
semi-analytical computation of the dispersion profile of a triangular Index-guiding PCF semi-analytical computation of the dispersion profile of a triangular Index-guiding PCF
@@ -554,10 +556,10 @@ def n_eff_pcf(wl_for_disp: np.ndarray, pitch: float, pitch_ratio: float) -> np.n
---------- ----------
wl_for_disp : np.ndarray, shape (n,) wl_for_disp : np.ndarray, shape (n,)
wavelengths over which to calculate the dispersion wavelengths over which to calculate the dispersion
pitch : float pcf_pitch : float
distance between air holes in m distance between air holes in m
pitch_ratio : float pcf_pitch_ratio : float
ratio diameter of hole / pitch ratio diameter of hole / pcf_pitch
Returns Returns
------- -------
@@ -570,15 +572,15 @@ def n_eff_pcf(wl_for_disp: np.ndarray, pitch: float, pitch_ratio: float) -> np.n
""" """
# Check validity # Check validity
if pitch_ratio < 0.2 or pitch_ratio > 0.8: if pcf_pitch_ratio < 0.2 or pcf_pitch_ratio > 0.8:
print("WARNING : Fitted formula valid only for pitch ratio between 0.2 and 0.8") print("WARNING : Fitted formula valid only for pcf_pitch ratio between 0.2 and 0.8")
a_eff = pitch / np.sqrt(3) effective_area = pcf_pitch / np.sqrt(3)
pi2a = pipi * a_eff pi2a = pipi * effective_area
ratio_l = wl_for_disp / pitch ratio_l = wl_for_disp / pcf_pitch
A, B = saitoh_paramters(pitch_ratio) A, B = saitoh_paramters(pcf_pitch_ratio)
V = A[0] + A[1] / (1 + A[2] * np.exp(A[3] * ratio_l)) V = A[0] + A[1] / (1 + A[2] * np.exp(A[3] * ratio_l))
W = B[0] + B[1] / (1 + B[2] * np.exp(B[3] * ratio_l)) W = B[0] + B[1] / (1 + B[2] * np.exp(B[3] * ratio_l))
@@ -591,15 +593,15 @@ def n_eff_pcf(wl_for_disp: np.ndarray, pitch: float, pitch_ratio: float) -> np.n
return n_eff + np.sqrt(chi_mat + 1) return n_eff + np.sqrt(chi_mat + 1)
def A_eff_from_diam(effective_mode_diameter: float) -> float: def effective_area_from_diam(effective_mode_diameter: float) -> float:
return pi * (effective_mode_diameter / 2) ** 2 return pi * (effective_mode_diameter / 2) ** 2
def A_eff_from_gamma(gamma: float, n2: float, w0: float): def effective_area_from_gamma(gamma: float, n2: float, w0: float):
return n2 * w0 / (c * gamma) return n2 * w0 / (c * gamma)
def saitoh_paramters(pitch_ratio: float) -> tuple[float, float]: def saitoh_paramters(pcf_pitch_ratio: float) -> tuple[float, float]:
# Table 1 and 2 in Saitoh2005 # Table 1 and 2 in Saitoh2005
ai0 = np.array([0.54808, 0.71041, 0.16904, -1.52736]) ai0 = np.array([0.54808, 0.71041, 0.16904, -1.52736])
ai1 = np.array([5.00401, 9.73491, 1.85765, 1.06745]) ai1 = np.array([5.00401, 9.73491, 1.85765, 1.06745])
@@ -616,17 +618,27 @@ def saitoh_paramters(pitch_ratio: float) -> tuple[float, float]:
di2 = np.array([9, 6.58, 10, 0.41]) di2 = np.array([9, 6.58, 10, 0.41])
di3 = np.array([10, 24.8, 15, 6]) di3 = np.array([10, 24.8, 15, 6])
A = ai0 + ai1 * pitch_ratio**bi1 + ai2 * pitch_ratio**bi2 + ai3 * pitch_ratio**bi3 A = (
B = ci0 + ci1 * pitch_ratio**di1 + ci2 * pitch_ratio**di2 + ci3 * pitch_ratio**di3 ai0
+ ai1 * pcf_pitch_ratio**bi1
+ ai2 * pcf_pitch_ratio**bi2
+ ai3 * pcf_pitch_ratio**bi3
)
B = (
ci0
+ ci1 * pcf_pitch_ratio**di1
+ ci2 * pcf_pitch_ratio**di2
+ ci3 * pcf_pitch_ratio**di3
)
return A, B return A, B
def load_custom_A_eff(A_eff_file: str, l: np.ndarray) -> np.ndarray: def load_custom_effective_area(effective_area_file: str, l: np.ndarray) -> np.ndarray:
"""loads custom effective area file """loads custom effective area file
Parameters Parameters
---------- ----------
A_eff_file : str effective_area_file : str
relative or absolute path to the file relative or absolute path to the file
l : np.ndarray, shape (n,) l : np.ndarray, shape (n,)
wavelength array of the simulation wavelength array of the simulation
@@ -636,10 +648,10 @@ def load_custom_A_eff(A_eff_file: str, l: np.ndarray) -> np.ndarray:
np.ndarray, shape (n,) np.ndarray, shape (n,)
wl-dependent effective mode field area wl-dependent effective mode field area
""" """
data = np.load(A_eff_file) data = np.load(effective_area_file)
A_eff = data["A_eff"] effective_area = data.get("A_eff", data.get("effective_area"))
wl = data["wavelength"] wl = data["wavelength"]
return interp1d(wl, A_eff, fill_value=1, bounds_error=False)(l) return interp1d(wl, effective_area, fill_value=1, bounds_error=False)(l)
def load_custom_dispersion(dispersion_file: str) -> tuple[np.ndarray, np.ndarray]: def load_custom_dispersion(dispersion_file: str) -> tuple[np.ndarray, np.ndarray]:

View File

@@ -95,7 +95,13 @@ class PulseProperties:
def initial_full_field( def initial_full_field(
t: np.ndarray, shape: str, A_eff: float, t0: float, peak_power: float, w0: float, n0: float t: np.ndarray,
shape: str,
effective_area: float,
t0: float,
peak_power: float,
w0: float,
n0: float,
) -> np.ndarray: ) -> np.ndarray:
"""initial field in full field simulations """initial field in full field simulations
@@ -120,7 +126,9 @@ def initial_full_field(
initial field initial field
""" """
return ( return (
initial_field_envelope(t, shape, t0, peak_power) * np.cos(w0 * t) * units.W_to_Vm(n0, A_eff) initial_field_envelope(t, shape, t0, peak_power)
* np.cos(w0 * t)
* units.W_to_Vm(n0, effective_area)
) )
@@ -192,7 +200,7 @@ def modify_field_ratio(
return ratio return ratio
def convert_field_units(envelope: np.ndarray, n: np.ndarray, A_eff: float) -> np.ndarray: def convert_field_units(envelope: np.ndarray, n: np.ndarray, effective_area: float) -> np.ndarray:
"""[summary] """[summary]
Parameters Parameters
@@ -201,7 +209,7 @@ def convert_field_units(envelope: np.ndarray, n: np.ndarray, A_eff: float) -> np
complex envelope in units such that |envelope|^2 is in W complex envelope in units such that |envelope|^2 is in W
n : np.ndarray, shape (n,) n : np.ndarray, shape (n,)
refractive index refractive index
A_eff : float effective_area : float
effective mode field area in m^2 effective mode field area in m^2
Returns Returns
@@ -209,15 +217,15 @@ def convert_field_units(envelope: np.ndarray, n: np.ndarray, A_eff: float) -> np
np.ndarray, shape (n,) np.ndarray, shape (n,)
real field in V/m real field in V/m
""" """
return 2 * envelope.real / np.sqrt(2 * units.epsilon0 * units.c * n * A_eff) return 2 * envelope.real / np.sqrt(2 * units.epsilon0 * units.c * n * effective_area)
def c_to_a_factor(A_eff_arr: np.ndarray) -> np.ndarray: def c_to_a_factor(effective_area_arr: np.ndarray) -> np.ndarray:
return (A_eff_arr / A_eff_arr[0]) ** (1 / 4) return (effective_area_arr / effective_area_arr[0]) ** (1 / 4)
def a_to_c_factor(A_eff_arr: np.ndarray) -> np.ndarray: def a_to_c_factor(effective_area_arr: np.ndarray) -> np.ndarray:
return (A_eff_arr / A_eff_arr[0]) ** (-1 / 4) return (effective_area_arr / effective_area_arr[0]) ** (-1 / 4)
def spectrum_factor_envelope(dt: float) -> float: def spectrum_factor_envelope(dt: float) -> float:
@@ -510,12 +518,12 @@ def finalize_pulse(
return np.sqrt(input_transmission) * pre_field_0 * ratio return np.sqrt(input_transmission) * pre_field_0 * ratio
def A_to_C(A: np.ndarray, A_eff_arr: np.ndarray) -> np.ndarray: def A_to_C(A: np.ndarray, effective_area_arr: np.ndarray) -> np.ndarray:
return (A_eff_arr / A_eff_arr[0]) ** (-1 / 4) * A return (effective_area_arr / effective_area_arr[0]) ** (-1 / 4) * A
def C_to_A(C: np.ndarray, A_eff_arr: np.ndarray) -> np.ndarray: def C_to_A(C: np.ndarray, effective_area_arr: np.ndarray) -> np.ndarray:
return (A_eff_arr / A_eff_arr[0]) ** (1 / 4) * C return (effective_area_arr / effective_area_arr[0]) ** (1 / 4) * C
def mean_phase(spectra): def mean_phase(spectra):

View File

@@ -10,7 +10,6 @@ from typing import Callable, TypeVar, Union
import numpy as np import numpy as np
from numpy import pi from numpy import pi
c = 299792458.0 c = 299792458.0
hbar = 1.05457148e-34 hbar = 1.05457148e-34
NA = 6.02214076e23 NA = 6.02214076e23
@@ -77,7 +76,7 @@ class To:
raise KeyError(f"no registered unit named {key!r}") from None raise KeyError(f"no registered unit named {key!r}") from None
def W_to_Vm(n0: float, A_eff: float) -> float: def W_to_Vm(n0: float, effective_area: float) -> float:
"""returns the factor to convert from [|E|²] = W to [|E|] = V/m """returns the factor to convert from [|E|²] = W to [|E|] = V/m
Parameters Parameters
@@ -90,7 +89,7 @@ def W_to_Vm(n0: float, A_eff: float) -> float:
float float
p such that E_sqrt(W) * p = W_Vm p such that E_sqrt(W) * p = W_Vm
""" """
return 1.0 / np.sqrt(A_eff * 0.5 * epsilon0 * c * n0) return 1.0 / np.sqrt(effective_area * 0.5 * epsilon0 * c * n0)
class unit: class unit: