Lots of progress, switching to tomli
This commit is contained in:
@@ -5,3 +5,7 @@
|
|||||||
- optional : add a default value
|
- optional : add a default value
|
||||||
- optional : add to valid_variable
|
- optional : add to valid_variable
|
||||||
- optional : add to mandatory_parameters
|
- 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
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
numpy
|
numpy
|
||||||
matplotlib
|
matplotlib
|
||||||
scipy
|
scipy
|
||||||
toml
|
tomli
|
||||||
|
tomli-w
|
||||||
tqdm
|
tqdm
|
||||||
@@ -23,7 +23,7 @@ install_requires =
|
|||||||
numba
|
numba
|
||||||
matplotlib
|
matplotlib
|
||||||
scipy
|
scipy
|
||||||
toml
|
tomli
|
||||||
tqdm
|
tqdm
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -42,3 +42,7 @@ class EvaluatorError(Exception):
|
|||||||
|
|
||||||
class NoDefaultError(EvaluatorError):
|
class NoDefaultError(EvaluatorError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class OperatorError(EvaluatorError):
|
||||||
|
pass
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ class Rule:
|
|||||||
targets = list(target) if isinstance(target, (list, tuple)) else [target]
|
targets = list(target) if isinstance(target, (list, tuple)) else [target]
|
||||||
self.func = func
|
self.func = func
|
||||||
if priorities is None:
|
if priorities is None:
|
||||||
priorities = [1] * len(targets)
|
priorities = [0] * len(targets)
|
||||||
elif isinstance(priorities, (int, float, np.integer, np.floating)):
|
elif isinstance(priorities, (int, float, np.integer, np.floating)):
|
||||||
priorities = [priorities]
|
priorities = [priorities]
|
||||||
self.targets = dict(zip(targets, priorities))
|
self.targets = dict(zip(targets, priorities))
|
||||||
@@ -293,7 +293,7 @@ class Evaluator:
|
|||||||
default_rules: list[Rule] = [
|
default_rules: list[Rule] = [
|
||||||
# Grid
|
# Grid
|
||||||
*Rule.deduce(
|
*Rule.deduce(
|
||||||
["z_targets", "t", "time_window", "t_num", "dt", "w_c", "w0", "w", "l"],
|
["z_targets", "t", "time_window", "t_num", "dt", "w_c", "w0", "w", "w_order", "l"],
|
||||||
math.build_sim_grid,
|
math.build_sim_grid,
|
||||||
["time_window", "t_num", "dt"],
|
["time_window", "t_num", "dt"],
|
||||||
2,
|
2,
|
||||||
@@ -403,11 +403,16 @@ default_rules: list[Rule] = [
|
|||||||
Rule("raman_op", operators.Raman),
|
Rule("raman_op", operators.Raman),
|
||||||
Rule("raman_op", operators.NoRaman, priorities=-1),
|
Rule("raman_op", operators.NoRaman, priorities=-1),
|
||||||
Rule("nonlinear_operator", operators.EnvelopeNonLinearOperator),
|
Rule("nonlinear_operator", operators.EnvelopeNonLinearOperator),
|
||||||
Rule("loss_op", operators.CustomConstantLoss, priorities=3),
|
Rule("loss_op", operators.CustomLoss, priorities=3),
|
||||||
Rule("loss_op", operators.CapillaryLoss, priorities=2, conditions=dict(loss="capillary")),
|
Rule("loss_op", operators.CapillaryLoss, priorities=2, conditions=dict(loss="capillary")),
|
||||||
Rule("loss_op", operators.ConstantLoss, priorities=1),
|
Rule("loss_op", operators.ConstantLoss, priorities=1),
|
||||||
Rule("loss_op", operators.NoLoss, priorities=-1),
|
Rule("loss_op", operators.NoLoss, priorities=-1),
|
||||||
|
Rule("n_op", operators.ConstantRefractiveIndex),
|
||||||
|
Rule("n_op", operators.MarcatiliRefractiveIndex),
|
||||||
|
Rule("n_op", operators.MarcatiliAdjustedRefractiveIndex),
|
||||||
|
Rule("n_op", operators.HasanRefractiveIndex),
|
||||||
Rule("dispersion_op", operators.ConstantPolyDispersion),
|
Rule("dispersion_op", operators.ConstantPolyDispersion),
|
||||||
|
Rule("dispersion_op", operators.DirectDispersion),
|
||||||
Rule("linear_operator", operators.LinearOperator),
|
Rule("linear_operator", operators.LinearOperator),
|
||||||
Rule("conserved_quantity", operators.ConservedQuantity),
|
Rule("conserved_quantity", operators.conserved_quantity),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ from pathlib import Path
|
|||||||
from typing import Any, Set
|
from typing import Any, Set
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import toml
|
import tomli
|
||||||
|
import tomli_w
|
||||||
|
|
||||||
from .const import SPEC1_FN, SPEC1_FN_N, SPECN_FN1
|
from .const import SPEC1_FN, SPEC1_FN_N, SPECN_FN1
|
||||||
from .parameter import Configuration, Parameters
|
from .parameter import Configuration, Parameters
|
||||||
@@ -15,8 +16,8 @@ from .variationer import VariationDescriptor
|
|||||||
|
|
||||||
|
|
||||||
def load_config(path: os.PathLike) -> dict[str, Any]:
|
def load_config(path: os.PathLike) -> dict[str, Any]:
|
||||||
with open(path) as file:
|
with open(path, "rb") as file:
|
||||||
d = toml.load(file)
|
d = tomli.load(file)
|
||||||
d.setdefault("variable", {})
|
d.setdefault("variable", {})
|
||||||
return d
|
return d
|
||||||
|
|
||||||
@@ -40,8 +41,8 @@ def convert_sim_folder(path: os.PathLike):
|
|||||||
os.makedirs(new_root, exist_ok=True)
|
os.makedirs(new_root, exist_ok=True)
|
||||||
_, configs = load_config_sequence(path)
|
_, configs = load_config_sequence(path)
|
||||||
master_config = dict(name=path.name, Fiber=configs)
|
master_config = dict(name=path.name, Fiber=configs)
|
||||||
with open(new_root / "initial_config.toml", "w") as f:
|
with open(new_root / "initial_config.toml", "wb") as f:
|
||||||
toml.dump(master_config, f, encoder=toml.TomlNumpyEncoder())
|
tomli_w.dump(Parameters.strip_params_dict(master_config), f)
|
||||||
configuration = Configuration(path, final_output_path=new_root)
|
configuration = Configuration(path, final_output_path=new_root)
|
||||||
pbar = PBars(configuration.total_num_steps, "Converting")
|
pbar = PBars(configuration.total_num_steps, "Converting")
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from typing import Union
|
|||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from scipy.special import jn_zeros
|
from scipy.special import jn_zeros
|
||||||
|
|
||||||
from .cache import np_cache
|
from .cache import np_cache
|
||||||
|
|
||||||
pi = np.pi
|
pi = np.pi
|
||||||
@@ -244,7 +245,6 @@ def build_sim_grid(
|
|||||||
length: float,
|
length: float,
|
||||||
z_num: int,
|
z_num: int,
|
||||||
wavelength: float,
|
wavelength: float,
|
||||||
interpolation_degree: int,
|
|
||||||
time_window: float = None,
|
time_window: float = None,
|
||||||
t_num: int = None,
|
t_num: int = None,
|
||||||
dt: float = None,
|
dt: float = None,
|
||||||
@@ -286,6 +286,8 @@ def build_sim_grid(
|
|||||||
pump angular frequency
|
pump angular frequency
|
||||||
w : np.ndarray, shape (t_num, )
|
w : np.ndarray, shape (t_num, )
|
||||||
actual angualr frequency grid in rad/s
|
actual angualr frequency grid in rad/s
|
||||||
|
w_order : np.ndarray, shape (t_num, )
|
||||||
|
result of w.argsort()
|
||||||
l : np.ndarray, shape (t_num)
|
l : np.ndarray, shape (t_num)
|
||||||
wavelengths in m
|
wavelengths in m
|
||||||
"""
|
"""
|
||||||
@@ -295,31 +297,34 @@ def build_sim_grid(
|
|||||||
dt = t[1] - t[0]
|
dt = t[1] - t[0]
|
||||||
t_num = len(t)
|
t_num = len(t)
|
||||||
z_targets = np.linspace(0, length, z_num)
|
z_targets = np.linspace(0, length, z_num)
|
||||||
w_c, w0, w = update_frequency_domain(t, wavelength, interpolation_degree)
|
|
||||||
l = 2 * pi * c / w
|
|
||||||
return z_targets, t, time_window, t_num, dt, w_c, w0, w, l
|
|
||||||
|
|
||||||
|
|
||||||
def update_frequency_domain(
|
|
||||||
t: np.ndarray, wavelength: float, deg: int
|
|
||||||
) -> tuple[np.ndarray, float, np.ndarray, np.ndarray]:
|
|
||||||
"""updates the frequency grid
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
t : np.ndarray
|
|
||||||
time array
|
|
||||||
wavelength : float
|
|
||||||
wavelength
|
|
||||||
deg : int
|
|
||||||
interpolation degree of the dispersion
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
Tuple[np.ndarray, float, np.ndarray, np.ndarray]
|
|
||||||
w_c, w0, w
|
|
||||||
"""
|
|
||||||
w_c = wspace(t)
|
w_c = wspace(t)
|
||||||
w0 = 2 * pi * c / wavelength
|
w0 = 2 * pi * c / wavelength
|
||||||
w = w_c + w0
|
w = w_c + w0
|
||||||
return w_c, w0, w
|
w_order = np.argsort(w)
|
||||||
|
l = 2 * pi * c / w
|
||||||
|
return z_targets, t, time_window, t_num, dt, w_c, w0, w, w_order, l
|
||||||
|
|
||||||
|
|
||||||
|
def linear_extrapolation(y: np.ndarray) -> np.ndarray:
|
||||||
|
"""extrapolates IN PLACE linearily on both side of the support
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
y : np.ndarray
|
||||||
|
array
|
||||||
|
left_ind : int
|
||||||
|
first value we want to keep (extrapolate to the left of that)
|
||||||
|
right_ind : int
|
||||||
|
last value we want to keep (extrapolate to the right of that)
|
||||||
|
"""
|
||||||
|
out = y.copy()
|
||||||
|
order = np.argsort(y)
|
||||||
|
left_ind, *_, right_ind = np.nonzero(out[order])[0]
|
||||||
|
_linear_extrapolation_in_place(out[order], left_ind, right_ind)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def _linear_extrapolation_in_place(y: np.ndarray, left_ind: int, right_ind: int):
|
||||||
|
y[:left_ind] = -(1 + np.arange(left_ind))[::-1] * (y[left_ind + 1] - y[left_ind]) + y[left_ind]
|
||||||
|
y[right_ind:] = np.arange(len(y) - right_ind) * (y[right_ind] - y[right_ind - 1]) + y[right_ind]
|
||||||
|
return y
|
||||||
|
|||||||
@@ -4,15 +4,19 @@ Nothing except the solver should depend on this file
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from abc import ABC, abstractmethod
|
|
||||||
import dataclasses
|
import dataclasses
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from scipy.interpolate import interp1d
|
from scipy.interpolate import interp1d
|
||||||
|
|
||||||
from . import math
|
from . import math
|
||||||
|
from .errors import OperatorError
|
||||||
from .logger import get_logger
|
from .logger import get_logger
|
||||||
|
from .physics import fiber, materials, pulse, units
|
||||||
from .physics import fiber, pulse
|
from .utils import load_material_dico
|
||||||
|
|
||||||
|
|
||||||
class SpectrumDescriptor:
|
class SpectrumDescriptor:
|
||||||
@@ -57,10 +61,12 @@ class CurrentState:
|
|||||||
class Operator(ABC):
|
class Operator(ABC):
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
value_pair_list = list(self.__dict__.items())
|
value_pair_list = list(self.__dict__.items())
|
||||||
if len(value_pair_list) > 1:
|
if len(value_pair_list) == 0:
|
||||||
value_pair_str_list = [k + "=" + self.__value_repr(k, v) for k, v in value_pair_list]
|
value_pair_str_list = ""
|
||||||
else:
|
elif len(value_pair_list) == 1:
|
||||||
value_pair_str_list = [self.__value_repr(value_pair_list[0][0], value_pair_list[0][1])]
|
value_pair_str_list = [self.__value_repr(value_pair_list[0][0], value_pair_list[0][1])]
|
||||||
|
else:
|
||||||
|
value_pair_str_list = [k + "=" + self.__value_repr(k, v) for k, v in value_pair_list]
|
||||||
|
|
||||||
return self.__class__.__name__ + "(" + ", ".join(value_pair_str_list) + ")"
|
return self.__class__.__name__ + "(" + ", ".join(value_pair_str_list) + ")"
|
||||||
|
|
||||||
@@ -79,6 +85,238 @@ class NoOp:
|
|||||||
self.arr_const = np.zeros(t_num)
|
self.arr_const = np.zeros(t_num)
|
||||||
|
|
||||||
|
|
||||||
|
##################################################
|
||||||
|
###################### GAS #######################
|
||||||
|
##################################################
|
||||||
|
|
||||||
|
|
||||||
|
class AbstractGas(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
def pressure(self, state: CurrentState) -> float:
|
||||||
|
"""returns the pressure at the current
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
state : CurrentState
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
float
|
||||||
|
pressure un bar
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def number_density(self, state: CurrentState) -> float:
|
||||||
|
"""returns the number density in 1/m^3 of at the current state
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
state : CurrentState
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
float
|
||||||
|
number density in 1/m^3
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def square_index(self, state: CurrentState) -> np.ndarray:
|
||||||
|
"""returns the square of the material refractive index at the current state
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
state : CurrentState
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
np.ndarray
|
||||||
|
n^2
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class ConstantGas(AbstractGas):
|
||||||
|
pressure_const: float
|
||||||
|
number_density_const: float
|
||||||
|
n_gas_2_const: np.ndarray
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
gas_name: str,
|
||||||
|
pressure: float,
|
||||||
|
temperature: float,
|
||||||
|
ideal_gas: bool,
|
||||||
|
wl_for_disp: np.ndarray,
|
||||||
|
):
|
||||||
|
gas_dico = load_material_dico(gas_name)
|
||||||
|
self.pressure_const = pressure
|
||||||
|
if ideal_gas:
|
||||||
|
self.number_density_const = materials.number_density_van_der_waals(
|
||||||
|
pressure=pressure, temperature=temperature, material_dico=gas_dico
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.number_density_const = self.pressure_const / (units.kB * temperature)
|
||||||
|
self.n_gas_2_const = materials.n_gas_2(
|
||||||
|
wl_for_disp, gas_name, self.pressure_const, temperature, ideal_gas
|
||||||
|
)
|
||||||
|
|
||||||
|
def pressure(self, state: CurrentState = None) -> float:
|
||||||
|
return self.pressure_const
|
||||||
|
|
||||||
|
def number_density(self, state: CurrentState = None) -> float:
|
||||||
|
return self.number_density_const
|
||||||
|
|
||||||
|
def square_index(self, state: CurrentState = None) -> float:
|
||||||
|
return self.n_gas_2_const
|
||||||
|
|
||||||
|
|
||||||
|
class PressureGradientGas(AbstractGas):
|
||||||
|
name: str
|
||||||
|
p_in: float
|
||||||
|
p_out: float
|
||||||
|
temperature: float
|
||||||
|
gas_dico: dict[str, Any]
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
gas_name: str,
|
||||||
|
pressure_in: float,
|
||||||
|
pressure_out: float,
|
||||||
|
temperature: float,
|
||||||
|
ideal_gas: bool,
|
||||||
|
wl_for_disp: np.ndarray,
|
||||||
|
):
|
||||||
|
self.name = gas_name
|
||||||
|
self.p_in = pressure_in
|
||||||
|
self.p_out = pressure_out
|
||||||
|
self.gas_dico = load_material_dico(gas_name)
|
||||||
|
self.temperature = temperature
|
||||||
|
self.ideal_gas = ideal_gas
|
||||||
|
self.wl_for_disp = wl_for_disp
|
||||||
|
|
||||||
|
def pressure(self, state: CurrentState) -> float:
|
||||||
|
return materials.pressure_from_gradient(state.z_ratio, self.p_in, self.p_out)
|
||||||
|
|
||||||
|
def number_density(self, state: CurrentState) -> float:
|
||||||
|
if self.ideal:
|
||||||
|
return self.pressure(state) / (units.kB * self.temperature)
|
||||||
|
else:
|
||||||
|
return materials.number_density_van_der_waals(
|
||||||
|
pressure=self.pressure(state),
|
||||||
|
temperature=self.temperature,
|
||||||
|
material_dico=self.gas_dico,
|
||||||
|
)
|
||||||
|
|
||||||
|
def square_index(self, state: CurrentState) -> np.ndarray:
|
||||||
|
return materials.fast_n_gas_2(
|
||||||
|
self.wl_for_disp, self.pressure(state), self.temperature, self.ideal_gas, self.gas_dico
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
##################################################
|
||||||
|
################### DISPERSION ###################
|
||||||
|
##################################################
|
||||||
|
|
||||||
|
|
||||||
|
class AbstractRefractiveIndex(Operator):
|
||||||
|
@abstractmethod
|
||||||
|
def __call__(self, state: CurrentState) -> np.ndarray:
|
||||||
|
"""returns the total/effective refractive index at this state
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
state : CurrentState
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
np.ndarray
|
||||||
|
refractive index
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class ConstantRefractiveIndex(AbstractRefractiveIndex):
|
||||||
|
n_eff_arr: np.ndarray
|
||||||
|
|
||||||
|
def __init__(self, n_eff: np.ndarray):
|
||||||
|
self.n_eff_arr = n_eff
|
||||||
|
|
||||||
|
def __call__(self, state: CurrentState = None) -> np.ndarray:
|
||||||
|
return self.n_eff_arr
|
||||||
|
|
||||||
|
|
||||||
|
class PCFRefractiveIndex(AbstractRefractiveIndex):
|
||||||
|
def __int__(self, wl_for_disp: np.ndarray, pitch: float, pitch_ratio: float):
|
||||||
|
self.n_eff_const = fiber.n_eff_pcf(wl_for_disp, pitch, pitch_ratio)
|
||||||
|
|
||||||
|
|
||||||
|
class MarcatiliRefractiveIndex(AbstractRefractiveIndex):
|
||||||
|
gas_op: AbstractGas
|
||||||
|
core_radius: float
|
||||||
|
wl_for_disp: np.ndarray
|
||||||
|
|
||||||
|
def __init__(self, gas_op: ConstantGas, core_radius: float, wl_for_disp: np.ndarray):
|
||||||
|
self.gas_op = gas_op
|
||||||
|
self.core_radius = core_radius
|
||||||
|
self.wl_for_disp = wl_for_disp
|
||||||
|
|
||||||
|
def __call__(self, state: CurrentState) -> np.ndarray:
|
||||||
|
return fiber.n_eff_marcatili(
|
||||||
|
self.wl_for_disp, self.gas_op.square_index(state), self.core_radius
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class MarcatiliAdjustedRefractiveIndex(MarcatiliRefractiveIndex):
|
||||||
|
def __call__(self, state: CurrentState) -> np.ndarray:
|
||||||
|
return fiber.n_eff_marcatili_adjusted(
|
||||||
|
self.wl_for_disp, self.gas_op.square_index(state), self.core_radius
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(repr=False, eq=False)
|
||||||
|
class HasanRefractiveIndex(AbstractRefractiveIndex):
|
||||||
|
gas_op: ConstantGas
|
||||||
|
core_radius: float
|
||||||
|
capillary_num: int
|
||||||
|
capillary_nested: int
|
||||||
|
capillary_thickness: float
|
||||||
|
capillary_radius: float
|
||||||
|
capillary_resonance_strengths: list[float]
|
||||||
|
wl_for_disp: np.ndarray
|
||||||
|
|
||||||
|
# def __init__(
|
||||||
|
# self,
|
||||||
|
# gas_op: ConstantGas,
|
||||||
|
# core_radius: float,
|
||||||
|
# capillary_num: int,
|
||||||
|
# capillary_nested: int,
|
||||||
|
# capillary_thickness: float,
|
||||||
|
# capillary_radius: float,
|
||||||
|
# capillary_resonance_strengths: list[float],
|
||||||
|
# wl_for_disp: np.ndarray,
|
||||||
|
# ):
|
||||||
|
# self.gas_op = gas_op
|
||||||
|
# self.core_radius = core_radius
|
||||||
|
# self.capillary_num = capillary_num
|
||||||
|
# self.capillary_nested = capillary_nested
|
||||||
|
# self.capillary_thickness = capillary_thickness
|
||||||
|
# self.capillary_radius = capillary_radius
|
||||||
|
# self.capillary_resonance_strengths = capillary_resonance_strengths
|
||||||
|
# self.wl_for_disp = wl_for_disp
|
||||||
|
|
||||||
|
def __call__(self, state: CurrentState) -> np.ndarray:
|
||||||
|
return fiber.n_eff_hasan(
|
||||||
|
self.wl_for_disp,
|
||||||
|
self.gas_op.square_index(state),
|
||||||
|
self.core_radius,
|
||||||
|
self.capillary_num,
|
||||||
|
self.capillary_nested,
|
||||||
|
self.capillary_thickness,
|
||||||
|
fiber.capillary_spacing_hasan(
|
||||||
|
self.capillary_num, self.capillary_radius, self.core_radius
|
||||||
|
),
|
||||||
|
self.capillary_resonance_strengths,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
##################################################
|
##################################################
|
||||||
################### DISPERSION ###################
|
################### DISPERSION ###################
|
||||||
##################################################
|
##################################################
|
||||||
@@ -92,7 +330,6 @@ class AbstractDispersion(Operator):
|
|||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
state : CurrentState
|
state : CurrentState
|
||||||
current state of the simulation
|
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
@@ -118,6 +355,10 @@ class ConstantPolyDispersion(AbstractDispersion):
|
|||||||
w_c: np.ndarray,
|
w_c: np.ndarray,
|
||||||
interpolation_degree: int,
|
interpolation_degree: int,
|
||||||
):
|
):
|
||||||
|
if interpolation_degree < 1:
|
||||||
|
raise OperatorError(
|
||||||
|
f"interpolation degree of degree {interpolation_degree} incompatible"
|
||||||
|
)
|
||||||
self.coefs = fiber.dispersion_coefficients(w_for_disp, beta2_arr, w0, interpolation_degree)
|
self.coefs = fiber.dispersion_coefficients(w_for_disp, beta2_arr, w0, interpolation_degree)
|
||||||
self.w_c = w_c
|
self.w_c = w_c
|
||||||
self.w_power_fact = np.array(
|
self.w_power_fact = np.array(
|
||||||
@@ -133,24 +374,66 @@ class ConstantDirectDispersion(AbstractDispersion):
|
|||||||
Direct dispersion for when the refractive index is known
|
Direct dispersion for when the refractive index is known
|
||||||
"""
|
"""
|
||||||
|
|
||||||
disp_arr_const: np.ndarray
|
disp_arr: np.ndarray
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
w_for_disp: np.ndarray,
|
w_for_disp: np.ndarray,
|
||||||
w0: np.ndarray,
|
w0: np.ndarray,
|
||||||
t_num: int,
|
t_num: int,
|
||||||
n_eff: np.ndarray,
|
n_op: ConstantRefractiveIndex,
|
||||||
dispersion_ind: np.ndarray,
|
dispersion_ind: np.ndarray,
|
||||||
|
w_order: np.ndarray,
|
||||||
):
|
):
|
||||||
self.disp_arr_const = np.zeros(t_num)
|
self.disp_arr = np.zeros(t_num, dtype=complex)
|
||||||
w0_ind = math.argclosest(w_for_disp, w0)
|
w0_ind = math.argclosest(w_for_disp, w0)
|
||||||
self.disp_arr_const[dispersion_ind] = fiber.fast_direct_dispersion(
|
self.disp_arr[dispersion_ind] = fiber.fast_direct_dispersion(
|
||||||
w_for_disp, w0, n_eff, w0_ind
|
w_for_disp, w0, n_op(), w0_ind
|
||||||
)[2:-2]
|
)[2:-2]
|
||||||
|
left_ind, *_, right_ind = np.nonzero(self.disp_arr[w_order])[0]
|
||||||
|
self.disp_arr[w_order] = math._linear_extrapolation_in_place(
|
||||||
|
self.disp_arr[w_order], left_ind, right_ind
|
||||||
|
)
|
||||||
|
|
||||||
def __call__(self, state: CurrentState = None):
|
def __call__(self, state: CurrentState = None) -> np.ndarray:
|
||||||
return self.disp_arr_const
|
return self.disp_arr
|
||||||
|
|
||||||
|
|
||||||
|
class DirectDispersion(AbstractDispersion):
|
||||||
|
def __new__(
|
||||||
|
cls,
|
||||||
|
w_for_disp: np.ndarray,
|
||||||
|
w0: np.ndarray,
|
||||||
|
t_num: int,
|
||||||
|
n_op: ConstantRefractiveIndex,
|
||||||
|
dispersion_ind: np.ndarray,
|
||||||
|
w_order: np.ndarray,
|
||||||
|
):
|
||||||
|
if isinstance(n_op, ConstantRefractiveIndex):
|
||||||
|
return ConstantDirectDispersion(w_for_disp, w0, t_num, n_op, dispersion_ind, w_order)
|
||||||
|
return object.__new__(cls)
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
w_for_disp: np.ndarray,
|
||||||
|
w0: np.ndarray,
|
||||||
|
t_num: int,
|
||||||
|
n_op: ConstantRefractiveIndex,
|
||||||
|
dispersion_ind: np.ndarray,
|
||||||
|
w_order: np.ndarray,
|
||||||
|
):
|
||||||
|
self.w_for_disp = w_for_disp
|
||||||
|
self.disp_ind = dispersion_ind
|
||||||
|
self.n_op = n_op
|
||||||
|
self.disp_arr = np.zeros(t_num)
|
||||||
|
self.w0 = w0
|
||||||
|
self.w0_ind = math.argclosest(w_for_disp, w0)
|
||||||
|
|
||||||
|
def __call__(self, state: CurrentState) -> np.ndarray:
|
||||||
|
self.disp_arr[self.disp_ind] = fiber.fast_direct_dispersion(
|
||||||
|
self.w_for_disp, self.w0, self.n_op(state), self.w0_ind
|
||||||
|
)[2:-2]
|
||||||
|
return self.disp_arr
|
||||||
|
|
||||||
|
|
||||||
##################################################
|
##################################################
|
||||||
@@ -166,7 +449,6 @@ class AbstractLoss(Operator):
|
|||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
state : CurrentState
|
state : CurrentState
|
||||||
current state of the simulation
|
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
@@ -203,18 +485,18 @@ class CapillaryLoss(ConstantLoss):
|
|||||||
self.arr = np.zeros(t_num)
|
self.arr = np.zeros(t_num)
|
||||||
self.arr[dispersion_ind] = alpha[2:-2]
|
self.arr[dispersion_ind] = alpha[2:-2]
|
||||||
|
|
||||||
def __call__(self, state: CurrentState) -> np.ndarray:
|
def __call__(self, state: CurrentState = None) -> np.ndarray:
|
||||||
return self.arr
|
return self.arr
|
||||||
|
|
||||||
|
|
||||||
class CustomConstantLoss(ConstantLoss):
|
class CustomLoss(ConstantLoss):
|
||||||
def __init__(self, l: np.ndarray, loss_file: str):
|
def __init__(self, l: np.ndarray, loss_file: str):
|
||||||
loss_data = np.load(loss_file)
|
loss_data = np.load(loss_file)
|
||||||
wl = loss_data["wavelength"]
|
wl = loss_data["wavelength"]
|
||||||
loss = loss_data["loss"]
|
loss = loss_data["loss"]
|
||||||
self.arr = interp1d(wl, loss, fill_value=0, bounds_error=False)(l)
|
self.arr = interp1d(wl, loss, fill_value=0, bounds_error=False)(l)
|
||||||
|
|
||||||
def __call__(self, state: CurrentState) -> np.ndarray:
|
def __call__(self, state: CurrentState = None) -> np.ndarray:
|
||||||
return self.arr
|
return self.arr
|
||||||
|
|
||||||
|
|
||||||
@@ -234,7 +516,6 @@ class LinearOperator(Operator):
|
|||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
state : CurrentState
|
state : CurrentState
|
||||||
current state of the simulation
|
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
@@ -259,7 +540,6 @@ class AbstractRaman(Operator):
|
|||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
state : CurrentState
|
state : CurrentState
|
||||||
current state of the simulation
|
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
@@ -297,7 +577,6 @@ class AbstractSPM(Operator):
|
|||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
state : CurrentState
|
state : CurrentState
|
||||||
current state of the simulation
|
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
@@ -332,7 +611,6 @@ class AbstractSelfSteepening(Operator):
|
|||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
state : CurrentState
|
state : CurrentState
|
||||||
current state of the simulation
|
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
@@ -367,7 +645,6 @@ class AbstractGamma(Operator):
|
|||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
state : CurrentState
|
state : CurrentState
|
||||||
current state of the simulation
|
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
@@ -414,7 +691,6 @@ class NonLinearOperator(Operator):
|
|||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
state : CurrentState
|
state : CurrentState
|
||||||
current state of the simulation
|
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
@@ -450,39 +726,19 @@ class EnvelopeNonLinearOperator(NonLinearOperator):
|
|||||||
##################################################
|
##################################################
|
||||||
|
|
||||||
|
|
||||||
class ConservedQuantity(Operator):
|
class AbstractConservedQuantity(Operator):
|
||||||
@classmethod
|
|
||||||
def create(
|
|
||||||
cls, raman_op: AbstractGamma, gamma_op: AbstractGamma, loss_op: AbstractLoss, w: np.ndarray
|
|
||||||
) -> ConservedQuantity:
|
|
||||||
logger = get_logger(__name__)
|
|
||||||
raman = not isinstance(raman_op, NoRaman)
|
|
||||||
loss = not isinstance(raman_op, NoLoss)
|
|
||||||
if raman and loss:
|
|
||||||
logger.debug("Conserved quantity : photon number with loss")
|
|
||||||
return PhotonNumberLoss(w, gamma_op, loss_op)
|
|
||||||
elif raman:
|
|
||||||
logger.debug("Conserved quantity : photon number without loss")
|
|
||||||
return PhotonNumberNoLoss(w, gamma_op)
|
|
||||||
elif loss:
|
|
||||||
logger.debug("Conserved quantity : energy with loss")
|
|
||||||
return EnergyLoss(w, loss_op)
|
|
||||||
else:
|
|
||||||
logger.debug("Conserved quantity : energy without loss")
|
|
||||||
return EnergyNoLoss(w)
|
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __call__(self, state: CurrentState) -> float:
|
def __call__(self, state: CurrentState) -> float:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class NoConservedQuantity(ConservedQuantity):
|
class NoConservedQuantity(AbstractConservedQuantity):
|
||||||
def __call__(self, state: CurrentState) -> float:
|
def __call__(self, state: CurrentState) -> float:
|
||||||
return 0.0
|
return 0.0
|
||||||
|
|
||||||
|
|
||||||
class PhotonNumberLoss(ConservedQuantity):
|
class PhotonNumberLoss(AbstractConservedQuantity):
|
||||||
def __init__(self, w: np.ndarray, gamma_op: AbstractGamma, loss_op=AbstractLoss):
|
def __init__(self, w: np.ndarray, gamma_op: AbstractGamma, loss_op: AbstractLoss):
|
||||||
self.w = w
|
self.w = w
|
||||||
self.dw = w[1] - w[0]
|
self.dw = w[1] - w[0]
|
||||||
self.gamma_op = gamma_op
|
self.gamma_op = gamma_op
|
||||||
@@ -494,7 +750,7 @@ class PhotonNumberLoss(ConservedQuantity):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class PhotonNumberNoLoss(ConservedQuantity):
|
class PhotonNumberNoLoss(AbstractConservedQuantity):
|
||||||
def __init__(self, w: np.ndarray, gamma_op: AbstractGamma):
|
def __init__(self, w: np.ndarray, gamma_op: AbstractGamma):
|
||||||
self.w = w
|
self.w = w
|
||||||
self.dw = w[1] - w[0]
|
self.dw = w[1] - w[0]
|
||||||
@@ -504,7 +760,7 @@ class PhotonNumberNoLoss(ConservedQuantity):
|
|||||||
return pulse.photon_number(state.spec2, self.w, self.dw, self.gamma_op(state))
|
return pulse.photon_number(state.spec2, self.w, self.dw, self.gamma_op(state))
|
||||||
|
|
||||||
|
|
||||||
class EnergyLoss(ConservedQuantity):
|
class EnergyLoss(AbstractConservedQuantity):
|
||||||
def __init__(self, w: np.ndarray, loss_op: AbstractLoss):
|
def __init__(self, w: np.ndarray, loss_op: AbstractLoss):
|
||||||
self.dw = w[1] - w[0]
|
self.dw = w[1] - w[0]
|
||||||
self.loss_op = loss_op
|
self.loss_op = loss_op
|
||||||
@@ -515,9 +771,35 @@ class EnergyLoss(ConservedQuantity):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class EnergyNoLoss(ConservedQuantity):
|
class EnergyNoLoss(AbstractConservedQuantity):
|
||||||
def __init__(self, w: np.ndarray):
|
def __init__(self, w: np.ndarray):
|
||||||
self.dw = w[1] - w[0]
|
self.dw = w[1] - w[0]
|
||||||
|
|
||||||
def __call__(self, state: CurrentState) -> float:
|
def __call__(self, state: CurrentState) -> float:
|
||||||
return pulse.pulse_energy(math.abs2(state.C_to_A_factor * state.spectrum), self.dw)
|
return pulse.pulse_energy(math.abs2(state.C_to_A_factor * state.spectrum), self.dw)
|
||||||
|
|
||||||
|
|
||||||
|
def conserved_quantity(
|
||||||
|
adapt_step_size: bool,
|
||||||
|
raman_op: AbstractGamma,
|
||||||
|
gamma_op: AbstractGamma,
|
||||||
|
loss_op: AbstractLoss,
|
||||||
|
w: np.ndarray,
|
||||||
|
) -> AbstractConservedQuantity:
|
||||||
|
if not adapt_step_size:
|
||||||
|
return NoConservedQuantity()
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
raman = not isinstance(raman_op, NoRaman)
|
||||||
|
loss = not isinstance(raman_op, NoLoss)
|
||||||
|
if raman and loss:
|
||||||
|
logger.debug("Conserved quantity : photon number with loss")
|
||||||
|
return PhotonNumberLoss(w, gamma_op, loss_op)
|
||||||
|
elif raman:
|
||||||
|
logger.debug("Conserved quantity : photon number without loss")
|
||||||
|
return PhotonNumberNoLoss(w, gamma_op)
|
||||||
|
elif loss:
|
||||||
|
logger.debug("Conserved quantity : energy with loss")
|
||||||
|
return EnergyLoss(w, loss_op)
|
||||||
|
else:
|
||||||
|
logger.debug("Conserved quantity : energy without loss")
|
||||||
|
return EnergyNoLoss(w)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
|
||||||
import datetime as datetime_module
|
import datetime as datetime_module
|
||||||
import enum
|
import enum
|
||||||
import os
|
import os
|
||||||
@@ -16,7 +17,7 @@ from . import env, legacy, utils
|
|||||||
from .const import MANDATORY_PARAMETERS, PARAM_FN, VALID_VARIABLE, __version__
|
from .const import MANDATORY_PARAMETERS, PARAM_FN, VALID_VARIABLE, __version__
|
||||||
from .evaluator import Evaluator, pdict
|
from .evaluator import Evaluator, pdict
|
||||||
from .logger import get_logger
|
from .logger import get_logger
|
||||||
from .operators import LinearOperator, NonLinearOperator
|
from .operators import AbstractConservedQuantity, LinearOperator, NonLinearOperator
|
||||||
from .utils import fiber_folder, update_path_name
|
from .utils import fiber_folder, update_path_name
|
||||||
from .variationer import VariationDescriptor, Variationer
|
from .variationer import VariationDescriptor, Variationer
|
||||||
|
|
||||||
@@ -261,7 +262,6 @@ class Parameters:
|
|||||||
name: str = Parameter(string, default="no name")
|
name: str = Parameter(string, default="no name")
|
||||||
prev_data_dir: str = Parameter(string)
|
prev_data_dir: str = Parameter(string)
|
||||||
recovery_data_dir: str = Parameter(string)
|
recovery_data_dir: str = Parameter(string)
|
||||||
previous_config_file: 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
|
||||||
@@ -334,7 +334,7 @@ class Parameters:
|
|||||||
tolerated_error: float = Parameter(in_range_excl(1e-15, 1e-3), default=1e-11)
|
tolerated_error: float = Parameter(in_range_excl(1e-15, 1e-3), default=1e-11)
|
||||||
step_size: float = Parameter(non_negative(float, int), default=0)
|
step_size: float = Parameter(non_negative(float, int), default=0)
|
||||||
interpolation_range: tuple[float, float] = Parameter(float_pair)
|
interpolation_range: tuple[float, float] = Parameter(float_pair)
|
||||||
interpolation_degree: int = Parameter(positive(int), default=8)
|
interpolation_degree: int = Parameter(non_negative(int))
|
||||||
prev_sim_dir: str = Parameter(string)
|
prev_sim_dir: str = Parameter(string)
|
||||||
recovery_last_stored: int = Parameter(non_negative(int), default=0)
|
recovery_last_stored: int = Parameter(non_negative(int), default=0)
|
||||||
parallel: bool = Parameter(boolean, default=True)
|
parallel: bool = Parameter(boolean, default=True)
|
||||||
@@ -343,6 +343,9 @@ class Parameters:
|
|||||||
# computed
|
# computed
|
||||||
linear_operator: LinearOperator = Parameter(type_checker(LinearOperator))
|
linear_operator: LinearOperator = Parameter(type_checker(LinearOperator))
|
||||||
nonlinear_operator: NonLinearOperator = Parameter(type_checker(NonLinearOperator))
|
nonlinear_operator: NonLinearOperator = Parameter(type_checker(NonLinearOperator))
|
||||||
|
conserved_quantity: AbstractConservedQuantity = Parameter(
|
||||||
|
type_checker(AbstractConservedQuantity)
|
||||||
|
)
|
||||||
field_0: np.ndarray = Parameter(type_checker(np.ndarray))
|
field_0: np.ndarray = Parameter(type_checker(np.ndarray))
|
||||||
spec_0: np.ndarray = Parameter(type_checker(np.ndarray))
|
spec_0: np.ndarray = Parameter(type_checker(np.ndarray))
|
||||||
beta2: float = Parameter(type_checker(int, float))
|
beta2: float = Parameter(type_checker(int, float))
|
||||||
@@ -372,7 +375,13 @@ class Parameters:
|
|||||||
self._evaluator.set(self._param_dico)
|
self._evaluator.set(self._param_dico)
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return "Parameter(" + ", ".join(f"{k}={v}" for k, v in self.dump_dict().items()) + ")"
|
return "Parameter(" + ", ".join(self.__repr_list__()) + ")"
|
||||||
|
|
||||||
|
def __pformat__(self) -> str:
|
||||||
|
return "\n".join(["Parameter(", *list(self.__repr_list__()), ")"])
|
||||||
|
|
||||||
|
def __repr_list__(self) -> Iterator[str]:
|
||||||
|
yield from (f"{k}={v}" for k, v in self.dump_dict().items())
|
||||||
|
|
||||||
def dump_dict(self) -> dict[str, Any]:
|
def dump_dict(self) -> dict[str, Any]:
|
||||||
param = Parameters.strip_params_dict(self._param_dico)
|
param = Parameters.strip_params_dict(self._param_dico)
|
||||||
@@ -427,7 +436,7 @@ class Parameters:
|
|||||||
"nonlinear_op",
|
"nonlinear_op",
|
||||||
"linear_op",
|
"linear_op",
|
||||||
}
|
}
|
||||||
types = (np.ndarray, float, int, str, list, tuple, dict)
|
types = (np.ndarray, float, int, str, list, tuple, dict, Path)
|
||||||
out = {}
|
out = {}
|
||||||
for key, value in dico.items():
|
for key, value in dico.items():
|
||||||
if key in forbiden_keys:
|
if key in forbiden_keys:
|
||||||
@@ -436,8 +445,12 @@ class Parameters:
|
|||||||
continue
|
continue
|
||||||
if isinstance(value, dict):
|
if isinstance(value, dict):
|
||||||
out[key] = Parameters.strip_params_dict(value)
|
out[key] = Parameters.strip_params_dict(value)
|
||||||
|
elif isinstance(value, Path):
|
||||||
|
out[key] = str(value)
|
||||||
elif isinstance(value, np.ndarray) and value.dtype == complex:
|
elif isinstance(value, np.ndarray) and value.dtype == complex:
|
||||||
continue
|
continue
|
||||||
|
elif isinstance(value, np.ndarray):
|
||||||
|
out[key] = value.tolist()
|
||||||
else:
|
else:
|
||||||
out[key] = value
|
out[key] = value
|
||||||
|
|
||||||
|
|||||||
@@ -1087,7 +1087,7 @@ def capillary_loss(wl: np.ndarray, he_mode: tuple[int, int], core_radius: float)
|
|||||||
np.ndarray
|
np.ndarray
|
||||||
loss in 1/m
|
loss in 1/m
|
||||||
"""
|
"""
|
||||||
chi_silica = mat.sellmeier(wl, utils.load_material_dico("silica"))
|
chi_silica = abs(mat.sellmeier(wl, utils.load_material_dico("silica")))
|
||||||
nu_n = 0.5 * (chi_silica + 2) / np.sqrt(chi_silica)
|
nu_n = 0.5 * (chi_silica + 2) / np.sqrt(chi_silica)
|
||||||
return nu_n * (u_nm(*he_mode) * wl / pipi) ** 2 * core_radius ** -3
|
return nu_n * (u_nm(*he_mode) * wl / pipi) ** 2 * core_radius ** -3
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from typing import Callable
|
from typing import Any, Callable
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import scipy.special
|
import scipy.special
|
||||||
@@ -18,6 +18,17 @@ def n_gas_2(
|
|||||||
"""Returns the sqare of the index of refraction of the specified gas"""
|
"""Returns the sqare of the index of refraction of the specified gas"""
|
||||||
material_dico = utils.load_material_dico(gas_name)
|
material_dico = utils.load_material_dico(gas_name)
|
||||||
|
|
||||||
|
n_gas_2 = fast_n_gas_2(wl_for_disp, pressure, temperature, ideal_gas, material_dico)
|
||||||
|
return n_gas_2
|
||||||
|
|
||||||
|
|
||||||
|
def fast_n_gas_2(
|
||||||
|
wl_for_disp: np.ndarray,
|
||||||
|
pressure: float,
|
||||||
|
temperature: float,
|
||||||
|
ideal_gas: bool,
|
||||||
|
material_dico: dict[str, Any],
|
||||||
|
):
|
||||||
if ideal_gas:
|
if ideal_gas:
|
||||||
n_gas_2 = sellmeier(wl_for_disp, material_dico, pressure, temperature) + 1
|
n_gas_2 = sellmeier(wl_for_disp, material_dico, pressure, temperature) + 1
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -2,16 +2,21 @@ import multiprocessing
|
|||||||
import multiprocessing.connection
|
import multiprocessing.connection
|
||||||
import os
|
import os
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from pathlib import Path
|
|
||||||
from typing import Any, Generator, Type, Union, Optional
|
|
||||||
from logging import Logger
|
from logging import Logger
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any, Generator, Optional, Type, Union
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from .. import utils
|
from .. import utils
|
||||||
|
from ..errors import EvaluatorError
|
||||||
from ..logger import get_logger
|
from ..logger import get_logger
|
||||||
|
from ..operators import (
|
||||||
|
AbstractConservedQuantity,
|
||||||
|
CurrentState,
|
||||||
|
)
|
||||||
from ..parameter import Configuration, Parameters
|
from ..parameter import Configuration, Parameters
|
||||||
from ..pbar import PBars, ProgressBarActor, progress_worker
|
from ..pbar import PBars, ProgressBarActor, progress_worker
|
||||||
from ..operators import CurrentState, ConservedQuantity, NoConservedQuantity
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import ray
|
import ray
|
||||||
@@ -35,7 +40,7 @@ class RK4IP:
|
|||||||
cons_qty: list[float]
|
cons_qty: list[float]
|
||||||
|
|
||||||
state: CurrentState
|
state: CurrentState
|
||||||
conserved_quantity_func: ConservedQuantity
|
conserved_quantity: AbstractConservedQuantity
|
||||||
stored_spectra: list[np.ndarray]
|
stored_spectra: list[np.ndarray]
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@@ -82,22 +87,8 @@ class RK4IP:
|
|||||||
params.tolerated_error if self.params.adapt_step_size else self.params.step_size
|
params.tolerated_error if self.params.adapt_step_size else self.params.step_size
|
||||||
)
|
)
|
||||||
|
|
||||||
self.set_cons_qty()
|
|
||||||
self._setup_sim_parameters()
|
self._setup_sim_parameters()
|
||||||
|
|
||||||
def set_cons_qty(self):
|
|
||||||
# Set up which quantity is conserved for adaptive step size
|
|
||||||
if self.params.adapt_step_size:
|
|
||||||
self.conserved_quantity_func = ConservedQuantity.create(
|
|
||||||
self.params.nonlinear_operator.raman_op,
|
|
||||||
self.params.nonlinear_operator.gamma_op,
|
|
||||||
self.params.linear_operator.loss_op,
|
|
||||||
self.params.w,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
self.logger.debug(f"Using constant step size of {1e6*self.error_ok:.3f}μm")
|
|
||||||
self.conserved_quantity_func = NoConservedQuantity()
|
|
||||||
|
|
||||||
def _setup_sim_parameters(self):
|
def _setup_sim_parameters(self):
|
||||||
# making sure to keep only the z that we want
|
# making sure to keep only the z that we want
|
||||||
self.z_stored = list(self.z_targets.copy()[0 : self.params.recovery_last_stored + 1])
|
self.z_stored = list(self.z_targets.copy()[0 : self.params.recovery_last_stored + 1])
|
||||||
@@ -106,7 +97,10 @@ class RK4IP:
|
|||||||
self.store_num = len(self.z_targets)
|
self.store_num = len(self.z_targets)
|
||||||
|
|
||||||
# Setup initial values for every physical quantity that we want to track
|
# Setup initial values for every physical quantity that we want to track
|
||||||
C_to_A_factor = (self.params.A_eff_arr / self.params.A_eff_arr[0]) ** (1 / 4)
|
try:
|
||||||
|
C_to_A_factor = (self.params.A_eff_arr / self.params.A_eff_arr[0]) ** (1 / 4)
|
||||||
|
except EvaluatorError:
|
||||||
|
C_to_A_factor = 1.0
|
||||||
z = self.z_targets.pop(0)
|
z = self.z_targets.pop(0)
|
||||||
# Initial step size
|
# Initial step size
|
||||||
if self.params.adapt_step_size:
|
if self.params.adapt_step_size:
|
||||||
@@ -124,7 +118,7 @@ class RK4IP:
|
|||||||
self.state.spectrum.copy()
|
self.state.spectrum.copy()
|
||||||
]
|
]
|
||||||
self.cons_qty = [
|
self.cons_qty = [
|
||||||
self.conserved_quantity_func(self.state),
|
self.params.conserved_quantity(self.state),
|
||||||
0,
|
0,
|
||||||
]
|
]
|
||||||
self.size_fac = 2 ** (1 / 5)
|
self.size_fac = 2 ** (1 / 5)
|
||||||
@@ -267,7 +261,7 @@ class RK4IP:
|
|||||||
new_state = self.state.replace(expD * (A_I + k1 / 6 + k2 / 3 + k3 / 3) + k4 / 6)
|
new_state = self.state.replace(expD * (A_I + k1 / 6 + k2 / 3 + k3 / 3) + k4 / 6)
|
||||||
|
|
||||||
if self.params.adapt_step_size:
|
if self.params.adapt_step_size:
|
||||||
self.cons_qty[step] = self.conserved_quantity_func(new_state)
|
self.cons_qty[step] = self.params.conserved_quantity(new_state)
|
||||||
curr_p_change = np.abs(self.cons_qty[step - 1] - self.cons_qty[step])
|
curr_p_change = np.abs(self.cons_qty[step - 1] - self.cons_qty[step])
|
||||||
cons_qty_change_ok = self.error_ok * self.cons_qty[step - 1]
|
cons_qty_change_ok = self.error_ok * self.cons_qty[step - 1]
|
||||||
|
|
||||||
@@ -531,7 +525,7 @@ class MultiProcSimulations(Simulations, priority=1):
|
|||||||
super().run()
|
super().run()
|
||||||
|
|
||||||
def new_sim(self, params: Parameters):
|
def new_sim(self, params: Parameters):
|
||||||
self.queue.put((params,), block=True, timeout=None)
|
self.queue.put(params.dump_dict(), block=True, timeout=None)
|
||||||
|
|
||||||
def finish(self):
|
def finish(self):
|
||||||
"""0 means finished"""
|
"""0 means finished"""
|
||||||
@@ -556,7 +550,7 @@ class MultiProcSimulations(Simulations, priority=1):
|
|||||||
if raw_data == 0:
|
if raw_data == 0:
|
||||||
queue.task_done()
|
queue.task_done()
|
||||||
return
|
return
|
||||||
(params,) = raw_data
|
params = Parameters(**raw_data)
|
||||||
MutliProcRK4IP(
|
MutliProcRK4IP(
|
||||||
params,
|
params,
|
||||||
p_queue,
|
p_queue,
|
||||||
|
|||||||
@@ -174,7 +174,6 @@ def create_zoom_axis(
|
|||||||
# copy the plot content
|
# copy the plot content
|
||||||
if plot:
|
if plot:
|
||||||
lines = axis.get_lines()
|
lines = axis.get_lines()
|
||||||
ymin, ymax = 0, 0
|
|
||||||
for line in lines:
|
for line in lines:
|
||||||
xdata = line.get_xdata()
|
xdata = line.get_xdata()
|
||||||
xdata, ind, _ = sort_axis(xdata, (*xlim, units.s))
|
xdata, ind, _ = sort_axis(xdata, (*xlim, units.s))
|
||||||
@@ -1071,9 +1070,36 @@ def partial_plot(root: os.PathLike):
|
|||||||
spec_list = sorted(
|
spec_list = sorted(
|
||||||
path.glob(SPEC1_FN.format("*")), key=lambda el: int(re.search("[0-9]+", el.name)[0])
|
path.glob(SPEC1_FN.format("*")), key=lambda el: int(re.search("[0-9]+", el.name)[0])
|
||||||
)
|
)
|
||||||
|
params = Parameters.load(path / "params.toml")
|
||||||
|
params.z_targets = params.z_targets[: len(spec_list)]
|
||||||
raw_values = np.array([load_spectrum(s) for s in spec_list])
|
raw_values = np.array([load_spectrum(s) for s in spec_list])
|
||||||
specs = units.to_log2D(math.abs2(np.fft.fftshift(raw_values, axes=-1)))
|
|
||||||
fields = math.abs2(np.fft.ifft(raw_values))
|
wl, z, values = transform_2D_propagation(
|
||||||
left.imshow(specs, origin="lower", aspect="auto", vmin=-60, interpolation="nearest")
|
raw_values,
|
||||||
right.imshow(fields, origin="lower", aspect="auto", interpolation="nearest")
|
PlotRange(
|
||||||
|
0.5 * params.interpolation_range[0] * 1e9,
|
||||||
|
1.1 * params.interpolation_range[1] * 1e9,
|
||||||
|
"nm",
|
||||||
|
),
|
||||||
|
params,
|
||||||
|
log="2D",
|
||||||
|
)
|
||||||
|
left.imshow(
|
||||||
|
values,
|
||||||
|
origin="lower",
|
||||||
|
aspect="auto",
|
||||||
|
vmin=-60,
|
||||||
|
interpolation="nearest",
|
||||||
|
extent=get_extent(wl, z),
|
||||||
|
)
|
||||||
|
|
||||||
|
t, z, values = transform_2D_propagation(
|
||||||
|
np.fft.ifft(raw_values),
|
||||||
|
PlotRange(-10, 10, "ps"),
|
||||||
|
params,
|
||||||
|
log=False,
|
||||||
|
)
|
||||||
|
right.imshow(
|
||||||
|
values, origin="lower", aspect="auto", interpolation="nearest", extent=get_extent(t, z)
|
||||||
|
)
|
||||||
return left, right
|
return left, right
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ from ..parameter import Configuration, Parameters
|
|||||||
from ..physics import fiber, units
|
from ..physics import fiber, units
|
||||||
from ..plotting import plot_setup
|
from ..plotting import plot_setup
|
||||||
from ..spectra import SimulationSeries
|
from ..spectra import SimulationSeries
|
||||||
from ..utils import _open_config, auto_crop, save_toml, simulations_list, translate_parameters
|
from ..utils import _open_config, auto_crop, save_toml, simulations_list
|
||||||
|
from ..legacy import translate_parameters
|
||||||
|
|
||||||
|
|
||||||
def fingerprint(params: Parameters):
|
def fingerprint(params: Parameters):
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ from typing import Any, Callable, MutableMapping, Sequence, TypeVar, Set
|
|||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pkg_resources as pkg
|
import pkg_resources as pkg
|
||||||
import toml
|
import tomli
|
||||||
|
import tomli_w
|
||||||
|
|
||||||
from .const import PARAM_FN, PARAM_SEPARATOR, SPEC1_FN, Z_FN, ROOT_PARAMETERS
|
from .const import PARAM_FN, PARAM_SEPARATOR, SPEC1_FN, Z_FN, ROOT_PARAMETERS
|
||||||
from .logger import get_logger
|
from .logger import get_logger
|
||||||
@@ -47,8 +48,8 @@ class Paths:
|
|||||||
def get(cls, key):
|
def get(cls, key):
|
||||||
if key not in cls.paths:
|
if key not in cls.paths:
|
||||||
if os.path.exists("paths.toml"):
|
if os.path.exists("paths.toml"):
|
||||||
with open("paths.toml") as file:
|
with open("paths.toml", "rb") as file:
|
||||||
paths_dico = toml.load(file)
|
paths_dico = tomli.load(file)
|
||||||
for k, v in paths_dico.items():
|
for k, v in paths_dico.items():
|
||||||
cls.paths[k] = v
|
cls.paths[k] = v
|
||||||
if key not in cls.paths:
|
if key not in cls.paths:
|
||||||
@@ -182,18 +183,18 @@ def load_toml(descr: os.PathLike) -> dict[str, Any]:
|
|||||||
descr = str(descr)
|
descr = str(descr)
|
||||||
if ":" in descr:
|
if ":" in descr:
|
||||||
path, entry = descr.split(":", 1)
|
path, entry = descr.split(":", 1)
|
||||||
with open(path) as file:
|
with open(path, "rb") as file:
|
||||||
return toml.load(file)[entry]
|
return tomli.load(file)[entry]
|
||||||
else:
|
else:
|
||||||
with open(descr) as file:
|
with open(descr, "rb") as file:
|
||||||
return toml.load(file)
|
return tomli.load(file)
|
||||||
|
|
||||||
|
|
||||||
def save_toml(path: os.PathLike, dico):
|
def save_toml(path: os.PathLike, dico):
|
||||||
"""saves a dictionary into a toml file"""
|
"""saves a dictionary into a toml file"""
|
||||||
path = conform_toml_path(path)
|
path = conform_toml_path(path)
|
||||||
with open(path, mode="w") as file:
|
with open(path, mode="wb") as file:
|
||||||
toml.dump(dico, file)
|
tomli_w.dump(dico, file)
|
||||||
return dico
|
return dico
|
||||||
|
|
||||||
|
|
||||||
@@ -247,7 +248,7 @@ def load_material_dico(name: str) -> dict[str, Any]:
|
|||||||
----------
|
----------
|
||||||
material_dico : dict
|
material_dico : dict
|
||||||
"""
|
"""
|
||||||
return toml.loads(Paths.gets("materials"))[name]
|
return tomli.loads(Paths.gets("materials"))[name]
|
||||||
|
|
||||||
|
|
||||||
def save_data(data: np.ndarray, data_dir: Path, file_name: str):
|
def save_data(data: np.ndarray, data_dir: Path, file_name: str):
|
||||||
@@ -478,8 +479,8 @@ def save_parameters(
|
|||||||
os.makedirs(file_path.parent, exist_ok=True)
|
os.makedirs(file_path.parent, exist_ok=True)
|
||||||
|
|
||||||
# save toml of the simulation
|
# save toml of the simulation
|
||||||
with open(file_path, "w") as file:
|
with open(file_path, "wb") as file:
|
||||||
toml.dump(params, file, encoder=toml.TomlNumpyEncoder())
|
tomli_w.dump(params, file)
|
||||||
|
|
||||||
return file_path
|
return file_path
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user