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"
length = 0.01
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"
[Fiber.variable] # this variable parameter will be applied to PM2000D_2
@@ -133,9 +133,9 @@ and specify the parameters it needs
pcf :
pitch: float
pcf_pitch: float
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
marcatili, marcatili_adjusted, hasan :
@@ -189,11 +189,11 @@ effective_mode_diameter : float, optional
n2 : float, optional
non linear refractive index in m^2/W
A_eff : float, optional
effective_area : float, optional
effective mode field area
A_eff_file : str, optional
file containing an A_eff array (in m^2) as function of a wavelength array (in m)
effective_area_file : str, optional
file containing an effective_area array (in m^2) as function of a wavelength array (in m)
length: float, optional
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
dispersion_file = "PM2000D_2 extrapolated 4 0.npz"
interpolation_degree = 12
A_eff_file = "PM2000D_A_eff_marcuse.npz"
effective_area_file = "PM2000D_A_eff_marcuse.npz"
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("spec_0", lambda fft, field_0: fft(field_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(
["pre_field_0", "peak_power", "energy", "width"],
pulse.adjust_custom_field,
@@ -355,7 +353,7 @@ default_rules: list[Rule] = [
Rule(
"n_eff",
fiber.n_eff_pcf,
["wl_for_disp", "pitch", "pitch_ratio"],
["wl_for_disp", "pcf_pitch", "pcf_pitch_ratio"],
conditions=dict(model="pcf"),
),
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)],
),
# Fiber nonlinearity
Rule("A_eff", fiber.A_eff_from_V),
Rule("A_eff", fiber.A_eff_from_diam),
Rule("A_eff", fiber.A_eff_hasan, conditions=dict(model="hasan")),
Rule("A_eff", fiber.A_eff_from_gamma, priorities=-1),
Rule("A_eff", fiber.A_eff_marcatili, priorities=-2),
Rule("A_eff_arr", fiber.A_eff_from_V, ["core_radius", "V_eff_arr"]),
Rule("A_eff_arr", fiber.load_custom_A_eff),
# Rule("A_eff_arr", fiber.constant_A_eff_arr, priorities=-1),
Rule("effective_area", fiber.effective_area_from_V),
Rule("effective_area", fiber.effective_area_from_diam),
Rule("effective_area", fiber.effective_area_hasan, conditions=dict(model="hasan")),
Rule("effective_area", fiber.effective_area_from_gamma, priorities=-1),
Rule("effective_area", fiber.elfective_area_marcatili, priorities=-2),
Rule("effecive_area_arr", fiber.effective_area_from_V, ["core_radius", "V_eff_arr"]),
Rule("effecive_area_arr", fiber.load_custom_effective_area),
Rule(
"V_eff",
fiber.V_parameter_koshiba,
["wavelength", "pitch", "pitch_ratio"],
["wavelength", "pcf_pitch", "pcf_pitch_ratio"],
conditions=dict(model="pcf"),
),
Rule(
@@ -399,7 +396,7 @@ default_rules: list[Rule] = [
Rule("n2", lambda: 2.2e-20, priorities=-1),
Rule("gamma", lambda gamma_arr: gamma_arr[0], priorities=-1),
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
Rule(["hr_w", "raman_fraction"], fiber.delayed_raman_w),
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)
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

View File

@@ -7,8 +7,7 @@ from dataclasses import dataclass, field, fields
from functools import lru_cache, wraps
from math import isnan
from pathlib import Path
from typing import (Any, Callable, ClassVar, Iterable, Iterator, Set, Type,
TypeVar)
from typing import Any, Callable, ClassVar, Iterable, Iterator, Set, Type, TypeVar
import numpy as np
@@ -229,7 +228,7 @@ class Parameter:
when displaying the value
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.default = default
self.display_info = display_info
@@ -247,28 +246,25 @@ class Parameter:
def __get__(self, instance: Parameters, owner):
if instance is None:
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.__dict__[self.name]
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):
if isinstance(value, Parameter):
if self.default is not None:
instance._param_dico[self.name] = copy(self.default)
if instance._frozen:
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)
return
is_value, value = self.validate(value)
if is_value:
instance._param_dico[self.name] = value
else:
is_value, value = self.validate(value)
if is_value:
instance._param_dico[self.name] = value
else:
if self.name in instance._param_dico:
del instance._param_dico[self.name]
self.__delete__(instance)
def display(self, num: float) -> str:
if self.display_info is None:
@@ -291,12 +287,9 @@ class Parameter:
if is_value:
if self.converter is not None:
v = self.converter(v)
self.__validator(self.name, v)
self._validator(self.name, v)
return is_value, v
def validator(self, name, value):
self.validate(value)
@dataclass(repr=False)
class Parameters:
@@ -308,11 +301,10 @@ class Parameters:
_param_dico: dict[str, Any] = field(init=False, default_factory=dict, repr=False)
_evaluator: Evaluator = field(init=False, repr=False)
_p_names: ClassVar[Set[str]] = set()
_frozen: bool = field(init=False, default=False, repr=False)
# root
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)
# fiber
@@ -323,11 +315,11 @@ class Parameters:
loss: str = Parameter(literal("capillary"))
loss_file: str = Parameter(string)
effective_mode_diameter: float = Parameter(positive(float, int))
A_eff: float = Parameter(non_negative(float, int))
A_eff_file: str = Parameter(string)
effective_area: float = Parameter(non_negative(float, int))
effective_area_file: str = Parameter(string)
numerical_aperture: float = Parameter(in_range_excl(0, 1))
pitch: float = Parameter(in_range_excl(0, 1e-3), display_info=(1e6, "μm"))
pitch_ratio: float = Parameter(in_range_excl(0, 1))
pcf_pitch: float = Parameter(in_range_excl(0, 1e-3), display_info=(1e6, "μm"))
pcf_pitch_ratio: float = Parameter(in_range_excl(0, 1))
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))
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: float = Parameter(non_negative(float, int))
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))
c_to_a_factor: np.ndarray = Parameter(type_checker(float, int, np.ndarray))
w: np.ndarray = Parameter(type_checker(np.ndarray))
@@ -524,7 +516,7 @@ class Parameters:
"wl_for_disp",
"alpha",
"gamma_arr",
"A_eff_arr",
"effective_area_arr",
"nonlinear_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)
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
Parameters
@@ -353,7 +353,7 @@ def n_eff_hasan(
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
Parameters
@@ -367,7 +367,7 @@ def A_eff_hasan(core_radius, capillary_num, capillary_spacing):
Returns
-------
A_eff : float
effective_area: float
"""
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)
@@ -405,7 +405,7 @@ def V_eff_step_index(
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
@@ -413,9 +413,9 @@ def V_parameter_koshiba(l: np.ndarray, pitch: float, pitch_ratio: float) -> floa
----------
l : np.ndarray, shape (n,)
wavelength
pitch : float
pcf_pitch : float
distance between air holes in m
pitch_ratio : float
pcf_pitch_ratio : float
ratio diameter of holes / distance
w0 : float
pump angular frequency
@@ -425,11 +425,11 @@ def V_parameter_koshiba(l: np.ndarray, pitch: float, pitch_ratio: float) -> floa
float
effective mode field area
"""
ratio_l = l / pitch
ratio_l = l / pcf_pitch
n_co = 1.45
a_eff = pitch / np.sqrt(3)
a_eff = pcf_pitch / np.sqrt(3)
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))
@@ -439,7 +439,7 @@ def V_parameter_koshiba(l: np.ndarray, pitch: float, pitch_ratio: float) -> floa
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
Parameters
@@ -452,7 +452,8 @@ def A_eff_from_V(core_radius: float, V_eff: T) -> T:
Returns
-------
T
A_eff
effective_area
"""
out = np.ones_like(V_eff)
out[V_eff > 0] = core_radius * (
@@ -533,20 +534,21 @@ def HCPCF_dispersion(
return beta2(w, n_eff)
def gamma_parameter(n2: float, w0: float, A_eff: T) -> T:
if isinstance(A_eff, np.ndarray):
A_eff_term = np.sqrt(A_eff * A_eff[0])
def gamma_parameter(n2: float, w0: float, effective_area: T) -> T:
if isinstance(effective_area, np.ndarray):
effective_area_term = np.sqrt(effective_area * effective_area[0])
else:
A_eff_term = A_eff
return n2 * w0 / (A_eff_term * c)
effective_area_term = effective_area
return n2 * w0 / (effective_area_term * c)
def constant_A_eff_arr(l: np.ndarray, A_eff: float) -> np.ndarray:
return np.ones_like(l) * A_eff
def constant_effective_area_arr(l: np.ndarray, effective_area: float) -> np.ndarray:
return np.ones_like(l) * effective_area
@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
@@ -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,)
wavelengths over which to calculate the dispersion
pitch : float
pcf_pitch : float
distance between air holes in m
pitch_ratio : float
ratio diameter of hole / pitch
pcf_pitch_ratio : float
ratio diameter of hole / pcf_pitch
Returns
-------
@@ -570,15 +572,15 @@ def n_eff_pcf(wl_for_disp: np.ndarray, pitch: float, pitch_ratio: float) -> np.n
"""
# Check validity
if pitch_ratio < 0.2 or pitch_ratio > 0.8:
print("WARNING : Fitted formula valid only for pitch ratio between 0.2 and 0.8")
if pcf_pitch_ratio < 0.2 or pcf_pitch_ratio > 0.8:
print("WARNING : Fitted formula valid only for pcf_pitch ratio between 0.2 and 0.8")
a_eff = pitch / np.sqrt(3)
pi2a = pipi * a_eff
effective_area = pcf_pitch / np.sqrt(3)
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))
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)
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
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)
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
ai0 = np.array([0.54808, 0.71041, 0.16904, -1.52736])
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])
di3 = np.array([10, 24.8, 15, 6])
A = ai0 + ai1 * pitch_ratio**bi1 + ai2 * pitch_ratio**bi2 + ai3 * pitch_ratio**bi3
B = ci0 + ci1 * pitch_ratio**di1 + ci2 * pitch_ratio**di2 + ci3 * pitch_ratio**di3
A = (
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
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
Parameters
----------
A_eff_file : str
effective_area_file : str
relative or absolute path to the file
l : np.ndarray, shape (n,)
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,)
wl-dependent effective mode field area
"""
data = np.load(A_eff_file)
A_eff = data["A_eff"]
data = np.load(effective_area_file)
effective_area = data.get("A_eff", data.get("effective_area"))
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]:

View File

@@ -95,7 +95,13 @@ class PulseProperties:
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:
"""initial field in full field simulations
@@ -120,7 +126,9 @@ def initial_full_field(
initial field
"""
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
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]
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
n : np.ndarray, shape (n,)
refractive index
A_eff : float
effective_area : float
effective mode field area in m^2
Returns
@@ -209,15 +217,15 @@ def convert_field_units(envelope: np.ndarray, n: np.ndarray, A_eff: float) -> np
np.ndarray, shape (n,)
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:
return (A_eff_arr / A_eff_arr[0]) ** (1 / 4)
def c_to_a_factor(effective_area_arr: np.ndarray) -> np.ndarray:
return (effective_area_arr / effective_area_arr[0]) ** (1 / 4)
def a_to_c_factor(A_eff_arr: np.ndarray) -> np.ndarray:
return (A_eff_arr / A_eff_arr[0]) ** (-1 / 4)
def a_to_c_factor(effective_area_arr: np.ndarray) -> np.ndarray:
return (effective_area_arr / effective_area_arr[0]) ** (-1 / 4)
def spectrum_factor_envelope(dt: float) -> float:
@@ -510,12 +518,12 @@ def finalize_pulse(
return np.sqrt(input_transmission) * pre_field_0 * ratio
def A_to_C(A: np.ndarray, A_eff_arr: np.ndarray) -> np.ndarray:
return (A_eff_arr / A_eff_arr[0]) ** (-1 / 4) * A
def A_to_C(A: np.ndarray, effective_area_arr: np.ndarray) -> np.ndarray:
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:
return (A_eff_arr / A_eff_arr[0]) ** (1 / 4) * C
def C_to_A(C: np.ndarray, effective_area_arr: np.ndarray) -> np.ndarray:
return (effective_area_arr / effective_area_arr[0]) ** (1 / 4) * C
def mean_phase(spectra):

View File

@@ -10,7 +10,6 @@ from typing import Callable, TypeVar, Union
import numpy as np
from numpy import pi
c = 299792458.0
hbar = 1.05457148e-34
NA = 6.02214076e23
@@ -77,7 +76,7 @@ class To:
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
Parameters
@@ -90,7 +89,7 @@ def W_to_Vm(n0: float, A_eff: float) -> float:
float
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: