initial commit
This commit is contained in:
18
.gitignore
vendored
Normal file
18
.gitignore
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
.DS_store
|
||||||
|
.idea
|
||||||
|
**/*.npy
|
||||||
|
|
||||||
|
plots*
|
||||||
|
Archive
|
||||||
|
*.mp4
|
||||||
|
*.png
|
||||||
|
*.pdf
|
||||||
|
__pycache__
|
||||||
|
*.egg-info
|
||||||
|
*sim_data*
|
||||||
|
tmp*
|
||||||
|
paths.json
|
||||||
|
scgenerator_log*
|
||||||
|
.scgenerator_tmp
|
||||||
|
|
||||||
|
.vscode
|
||||||
19
LICENSE
Normal file
19
LICENSE
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
Copyright (c) 2020 Benoît Sierro
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
1
MANIFEST.in
Normal file
1
MANIFEST.in
Normal file
@@ -0,0 +1 @@
|
|||||||
|
include src/scgenerator/data/*
|
||||||
204
README.md
Normal file
204
README.md
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
It is recommended to import scgenerator in the following manner :
|
||||||
|
`import scgenerator as sc`
|
||||||
|
|
||||||
|
# How to run a set of simulations
|
||||||
|
create a config file
|
||||||
|
|
||||||
|
run `sc.parallel_simulations(config_file)` or `sc.simulate(config_file)`
|
||||||
|
|
||||||
|
# How to analyse a simulation
|
||||||
|
|
||||||
|
load data with the load_sim_data method
|
||||||
|
spectra = load_sim_data("varyTechNoise100kW_sim_data", nickname="cool_sim")
|
||||||
|
to plot
|
||||||
|
plot_results_2D(spectra[0], (600, 1450, nm)) # will take care of looking up the nickname
|
||||||
|
to retrieve a paramteter:
|
||||||
|
z = state.params["cool_sim"]["z"]
|
||||||
|
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
|
||||||
|
You can load parameters by simpling passing the path to a toml file to the appropriate simulation function. Each possible key of this dictionary is described below. Every value must be given in standard SI units (m, s, W, J, ...)
|
||||||
|
The configuration file can have a ```name``` parameter at the root and must otherwise contain the following sections with the specified parameters
|
||||||
|
|
||||||
|
note : internally, another structure with a flattened dictionary is used
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Fiber parameters
|
||||||
|
If you already know the Taylor coefficients corresponding to the expansion of the beta2 profile, you can specify them and skip to "Other fiber parameters":
|
||||||
|
|
||||||
|
beta: list-like
|
||||||
|
list of Taylor coefficients for the beta_2 function
|
||||||
|
|
||||||
|
|
||||||
|
else, you can choose a mathematical fiber model
|
||||||
|
|
||||||
|
model: str {"pcf", "marcatili", "marcatili_adjusted", "hasan"}
|
||||||
|
|
||||||
|
**PCF** : solid core silica photonic crystal fiber, as modeled in Saitoh, Kunimasa, and Masanori Koshiba. "Empirical relations for simple design of photonic crystal fibers." Optics express 13.1 (2005): 267-274.
|
||||||
|
|
||||||
|
**marcatili** : Marcatili model of a capillary fiber : Marcatili, Enrique AJ, and R. A. Schmeltzer. "Hollow metallic and dielectric waveguides for long distance optical transmission and lasers." Bell System Technical Journal 43.4 (1964): 1783-1809.
|
||||||
|
|
||||||
|
**marcatili_adjusted** : Marcatili model of a capillary fiber with adjusted effective radius in the longer wavelength : Köttig, F., et al. "Novel mid-infrared dispersive wave generation in gas-filled PCF by transient ionization-driven changes in dispersion." arXiv preprint arXiv:1701.04843 (2017).
|
||||||
|
|
||||||
|
**hasan** : Hasan model of hollow core anti-resonance fibers : Hasan, Md Imran, Nail Akhmediev, and Wonkeun Chang. "Empirical formulae for dispersion and effective mode area in hollow-core antiresonant fibers." Journal of Lightwave Technology 36.18 (2018): 4060-4065.
|
||||||
|
|
||||||
|
and specify the parameters it needs
|
||||||
|
|
||||||
|
pcf :
|
||||||
|
|
||||||
|
pitch: float
|
||||||
|
distance between air holes in m
|
||||||
|
pitch_ratio: float 0.2 < pitch_ratio < 0.8
|
||||||
|
ratio hole diameter/pich
|
||||||
|
|
||||||
|
marcatili, marcatili_adjusted, hasan :
|
||||||
|
|
||||||
|
core_radius: float
|
||||||
|
radius of the hollow core in m
|
||||||
|
|
||||||
|
|
||||||
|
marcatili, marcatili_adjusted :
|
||||||
|
|
||||||
|
he_mode: list, shape (2, ), optional
|
||||||
|
mode of propagation. default is (1, 1), which is the fundamental mode
|
||||||
|
|
||||||
|
marcatili_adjusted :
|
||||||
|
|
||||||
|
fit_parameters: list, shape (2, ), optional
|
||||||
|
parameters for the effective radius correction. Defaults are (s, h) = (0.08, 200e-9) as in the referenced paper.
|
||||||
|
|
||||||
|
hasan :
|
||||||
|
|
||||||
|
capillary_num : int
|
||||||
|
number of capillaries
|
||||||
|
|
||||||
|
capillary_outer_d : float, optional if g is specified
|
||||||
|
outer diameter of the capillaries
|
||||||
|
|
||||||
|
capillary_thickness : float
|
||||||
|
thickness of the capillary walls
|
||||||
|
|
||||||
|
capillary_spacing : float, optional if d is specified
|
||||||
|
spacing between the capillary
|
||||||
|
|
||||||
|
capillray_resonance_strengths : list, optional
|
||||||
|
list of resonance strengths. Default is []
|
||||||
|
|
||||||
|
capillary_nested : int, optional
|
||||||
|
how many nested capillaries. Default is 0
|
||||||
|
|
||||||
|
## Other fiber parameters :
|
||||||
|
|
||||||
|
|
||||||
|
gamma: float, optional unless beta is directly provided
|
||||||
|
nonlinear parameter in m^2 / W. Will overwrite any computed gamma parameter.
|
||||||
|
|
||||||
|
length: float, optional
|
||||||
|
length of the fiber in m. default : 1
|
||||||
|
|
||||||
|
|
||||||
|
## Gas parameters
|
||||||
|
this section is completely optional and ignored if the fiber model is "pcf"
|
||||||
|
|
||||||
|
gas_name: str
|
||||||
|
name of the gas. default : "vacuum"
|
||||||
|
|
||||||
|
pressure: float
|
||||||
|
pressure of the gas in the fiber. default : 1e5
|
||||||
|
|
||||||
|
temperature: float
|
||||||
|
temperature of the gas in the fiber. default : 300
|
||||||
|
|
||||||
|
plasma_density: float
|
||||||
|
constant plasma density (in m^-3). default : 0
|
||||||
|
|
||||||
|
## Pulse parameters:
|
||||||
|
### Mandatory
|
||||||
|
|
||||||
|
wavelength: float
|
||||||
|
pump wavelength in m
|
||||||
|
|
||||||
|
To specify the initial pulse shape, either use one of 2 in (power, energy) together with one of 2 in (width, t0), or use soliton_num together with one of 4 in (power, energy, width, t0)
|
||||||
|
|
||||||
|
power: float
|
||||||
|
peak power in W
|
||||||
|
|
||||||
|
energy: float
|
||||||
|
total pulse energy in J
|
||||||
|
|
||||||
|
width: float
|
||||||
|
full width half maximum of the pulse in s. Will be converted to appropriate t0 depending on pulse shape
|
||||||
|
|
||||||
|
t0: float
|
||||||
|
pulse width parameter
|
||||||
|
|
||||||
|
solition_num: float
|
||||||
|
soliton number
|
||||||
|
|
||||||
|
### optional
|
||||||
|
|
||||||
|
quantum_noise: bool
|
||||||
|
whether or not one-photon-per-mode quantum noise is activated. default : False
|
||||||
|
|
||||||
|
intensity_noise: float
|
||||||
|
relative intensity noise
|
||||||
|
|
||||||
|
shape: str {"gaussian", "sech"}
|
||||||
|
shape of the pulse. default : gaussian
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Simulation parameters
|
||||||
|
### 2 of 3
|
||||||
|
|
||||||
|
dt: float
|
||||||
|
resolution of the temporal grid in s
|
||||||
|
|
||||||
|
t_num: int
|
||||||
|
number of temporal grid points
|
||||||
|
|
||||||
|
time_window: float
|
||||||
|
total length of the temporal grid in s
|
||||||
|
|
||||||
|
### optional
|
||||||
|
behaviors: list of str {"spm", "raman", "ss"}
|
||||||
|
spm is self-phase modulation
|
||||||
|
raman is raman effect
|
||||||
|
ss is self-steepening
|
||||||
|
default : ["spm", "ss"]
|
||||||
|
|
||||||
|
raman_type: str {"measured", "stolen", "agrawal"}
|
||||||
|
type of Raman effect. Default is "agrawal".
|
||||||
|
|
||||||
|
ideal_gas: bool
|
||||||
|
if True, use the ideal gas law. Otherwise, use van der Waals equation. default : False
|
||||||
|
|
||||||
|
z_num : int
|
||||||
|
number of spatial grid points along the fiber. default : 128
|
||||||
|
|
||||||
|
frep: float
|
||||||
|
repetition rate in Hz. Only useful to convert units. default : 80e6
|
||||||
|
|
||||||
|
tolerated_error: float
|
||||||
|
relative tolerated step-to-step error. default : 1e-11
|
||||||
|
|
||||||
|
step_size: float
|
||||||
|
if given, sets a constant step size rather than adapting it.
|
||||||
|
|
||||||
|
parallel: int
|
||||||
|
how many parallel simulations to run. default : 1
|
||||||
|
|
||||||
|
repeat: int
|
||||||
|
how many simulations to run per parameter set. default : 1
|
||||||
|
|
||||||
|
lower_wavelength_interp_limit: float
|
||||||
|
dispersion coefficients are computed over a certain wavelength range. This parameter
|
||||||
|
sets the lowest end of this range. If the set value is lower than the lower end of the
|
||||||
|
wavelength window, it is raised up to that point. default : 0
|
||||||
|
|
||||||
|
upper_wavelength_interp_limit: float
|
||||||
|
dispersion coefficients are computed over a certain wavelength range. This parameter
|
||||||
|
sets the lowest end of this range. If the set value is higher than the higher end of the
|
||||||
|
wavelength window, it is lowered down to that point. default : 1900e-9
|
||||||
BIN
config.npz
Normal file
BIN
config.npz
Normal file
Binary file not shown.
7
developement_help.md
Normal file
7
developement_help.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
## add parameter
|
||||||
|
- add it to ```const.valid_param_types```
|
||||||
|
- add it to README.md
|
||||||
|
- add the necessary logic in the appropriate ```initialize.ensure_consistency``` subfunction
|
||||||
|
- optional : add a default value
|
||||||
|
- optional : add to valid varying
|
||||||
|
- optional : add/update dependency map
|
||||||
586
scgenerator.log
Normal file
586
scgenerator.log
Normal file
@@ -0,0 +1,586 @@
|
|||||||
|
scgenerator.initialize: computed initial N = 8.66
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 0)]
|
||||||
|
wavelength_8.35e-07_num_0: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.35e-07_num_0: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.35e-07_num_0: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 16:01:39[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 16:01:44[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 25s (30% in total). [31mETA : 2021-01-28 16:02:16[0m (2638 steps). z = 0.0060, h = 9.7856e-07
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 21s (41% in total). [31mETA : 2021-01-28 16:02:15[0m (3444 steps). z = 0.0083, h = 1.7968e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 16s (50% in total). [31mETA : 2021-01-28 16:02:10[0m (3706 steps). z = 0.0102, h = 2.8346e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 11s (60% in total). [31mETA : 2021-01-28 16:02:07[0m (3915 steps). z = 0.0121, h = 8.8081e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 7s (71% in total). [31mETA : 2021-01-28 16:02:03[0m (4135 steps). z = 0.0143, h = 5.7601e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 4s (80% in total). [31mETA : 2021-01-28 16:02:01[0m (4307 steps). z = 0.0162, h = 6.6994e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 16:02:00[0m (4466 steps). z = 0.0181, h = 5.4078e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 16:01:59[0m (4634 steps). z = 0.0200, h = 7.4967e-06
|
||||||
|
wavelength_8.35e-07_num_0: propagation finished in 4634 steps (19.990754 seconds)
|
||||||
|
scgenerator.initialize: computed initial N = 8.66
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.3e-07), ('num', 0)]
|
||||||
|
wavelength_8.3e-07_num_0: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.3e-07_num_0: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.3e-07_num_0: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 16:02:00[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 16:02:05[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.3e-07_num_0: step 997 rejected with h = 2.7537e-06, doing over
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 23s (30% in total). [31mETA : 2021-01-28 16:02:33[0m (2162 steps). z = 0.0060, h = 3.8127e-08
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 19s (41% in total). [31mETA : 2021-01-28 16:02:31[0m (2991 steps). z = 0.0083, h = 5.8562e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 14s (50% in total). [31mETA : 2021-01-28 16:02:28[0m (3242 steps). z = 0.0102, h = 6.5756e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 10s (60% in total). [31mETA : 2021-01-28 16:02:25[0m (3443 steps). z = 0.0121, h = 2.9227e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 6s (71% in total). [31mETA : 2021-01-28 16:02:22[0m (3664 steps). z = 0.0143, h = 1.1425e-05
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 4s (80% in total). [31mETA : 2021-01-28 16:02:21[0m (3833 steps). z = 0.0162, h = 1.0515e-05
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 16:02:19[0m (4003 steps). z = 0.0181, h = 7.4644e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 16:02:18[0m (4181 steps). z = 0.0200, h = 1.21e-05
|
||||||
|
wavelength_8.3e-07_num_0: propagation finished in 4181 steps (18.946698 seconds)
|
||||||
|
scgenerator.physics.simulate: Merging data...
|
||||||
|
scgenerator.physics.simulate: Finished simulations from config full anomalous !
|
||||||
|
scgenerator.physics.simulate: 1 node in the Ray cluster : ['Obento.fritz.box']
|
||||||
|
scgenerator.initialize: computed initial N = 8.66
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 0)], job : df5a1a828c9685d3ffffffff0100000001000000
|
||||||
|
scgenerator.initialize: computed initial N = 8.66
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.3e-07), ('num', 0)], job : cb230a572350ff44ffffffff0100000001000000
|
||||||
|
wavelength_8.35e-07_num_0: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.35e-07_num_0: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.35e-07_num_0: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.3e-07_num_0: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.3e-07_num_0: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.3e-07_num_0: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 16:08:57[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 16:08:58[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 16:09:02[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 16:09:03[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.3e-07_num_0: step 997 rejected with h = 2.7537e-06, doing over
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 23s (30% in total). [31mETA : 2021-01-28 16:09:31[0m (2162 steps). z = 0.0060, h = 3.8127e-08
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 28s (30% in total). [31mETA : 2021-01-28 16:09:37[0m (2638 steps). z = 0.0060, h = 9.7856e-07
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 20s (41% in total). [31mETA : 2021-01-28 16:09:31[0m (2991 steps). z = 0.0083, h = 5.8562e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 16s (50% in total). [31mETA : 2021-01-28 16:09:28[0m (3242 steps). z = 0.0102, h = 6.5756e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 24s (41% in total). [31mETA : 2021-01-28 16:09:37[0m (3444 steps). z = 0.0083, h = 1.7968e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 11s (60% in total). [31mETA : 2021-01-28 16:09:25[0m (3443 steps). z = 0.0121, h = 2.9227e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 17s (50% in total). [31mETA : 2021-01-28 16:09:32[0m (3706 steps). z = 0.0102, h = 2.8346e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 7s (71% in total). [31mETA : 2021-01-28 16:09:22[0m (3664 steps). z = 0.0143, h = 1.1425e-05
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 12s (60% in total). [31mETA : 2021-01-28 16:09:28[0m (3915 steps). z = 0.0121, h = 8.8081e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 4s (80% in total). [31mETA : 2021-01-28 16:09:20[0m (3833 steps). z = 0.0162, h = 1.0515e-05
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 8s (71% in total). [31mETA : 2021-01-28 16:09:25[0m (4135 steps). z = 0.0143, h = 5.7601e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 16:09:19[0m (4003 steps). z = 0.0181, h = 7.4644e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 5s (80% in total). [31mETA : 2021-01-28 16:09:23[0m (4307 steps). z = 0.0162, h = 6.6994e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 16:09:18[0m (4181 steps). z = 0.0200, h = 1.21e-05
|
||||||
|
wavelength_8.3e-07_num_0: propagation finished in 4181 steps (20.752765 seconds)
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 16:09:21[0m (4466 steps). z = 0.0181, h = 5.4078e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 16:09:19[0m (4634 steps). z = 0.0200, h = 7.4967e-06
|
||||||
|
wavelength_8.35e-07_num_0: propagation finished in 4634 steps (22.817256 seconds)
|
||||||
|
scgenerator.physics.simulate: Merging data...
|
||||||
|
scgenerator.physics.simulate: Finished simulations from config full anomalous !
|
||||||
|
scgenerator.physics.simulate: 1 node in the Ray cluster : ['Obento.fritz.box']
|
||||||
|
scgenerator.initialize: computed initial N = 8.66
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 0)], job : df5a1a828c9685d3ffffffff0100000001000000
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 1)], job : cb230a572350ff44ffffffff0100000001000000
|
||||||
|
wavelength_8.35e-07_num_0: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.35e-07_num_0: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.35e-07_num_0: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.35e-07_num_1: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.35e-07_num_1: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.35e-07_num_1: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 16:21:10[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 16:21:11[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 16:21:15[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 16:21:16[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 30s (30% in total). [31mETA : 2021-01-28 16:21:54[0m (2638 steps). z = 0.0060, h = 9.7856e-07
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 30s (30% in total). [31mETA : 2021-01-28 16:21:54[0m (2638 steps). z = 0.0060, h = 9.7856e-07
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 24s (41% in total). [31mETA : 2021-01-28 16:21:52[0m (3444 steps). z = 0.0083, h = 1.7968e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 24s (41% in total). [31mETA : 2021-01-28 16:21:52[0m (3444 steps). z = 0.0083, h = 1.7968e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 17s (50% in total). [31mETA : 2021-01-28 16:21:46[0m (3706 steps). z = 0.0102, h = 2.8346e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 17s (50% in total). [31mETA : 2021-01-28 16:21:47[0m (3706 steps). z = 0.0102, h = 2.8346e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 12s (60% in total). [31mETA : 2021-01-28 16:21:42[0m (3915 steps). z = 0.0121, h = 8.8081e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 12s (60% in total). [31mETA : 2021-01-28 16:21:43[0m (3915 steps). z = 0.0121, h = 8.8081e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 8s (71% in total). [31mETA : 2021-01-28 16:21:39[0m (4135 steps). z = 0.0143, h = 5.7601e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 8s (71% in total). [31mETA : 2021-01-28 16:21:39[0m (4135 steps). z = 0.0143, h = 5.7601e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 5s (80% in total). [31mETA : 2021-01-28 16:21:37[0m (4307 steps). z = 0.0162, h = 6.6994e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 5s (80% in total). [31mETA : 2021-01-28 16:21:37[0m (4307 steps). z = 0.0162, h = 6.6994e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 16:21:35[0m (4466 steps). z = 0.0181, h = 5.4078e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 16:21:35[0m (4466 steps). z = 0.0181, h = 5.4078e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 16:21:33[0m (4634 steps). z = 0.0200, h = 7.4967e-06
|
||||||
|
wavelength_8.35e-07_num_0: propagation finished in 4634 steps (23.470734 seconds)
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 2)], job : 7bbd90284b71e599ffffffff0100000001000000
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 16:21:34[0m (4634 steps). z = 0.0200, h = 7.4967e-06
|
||||||
|
wavelength_8.35e-07_num_1: propagation finished in 4634 steps (23.325504 seconds)
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 3)], job : bd37d2621480fc7dffffffff0100000001000000
|
||||||
|
scgenerator.initialize: computed initial N = 8.66
|
||||||
|
wavelength_8.35e-07_num_2: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.35e-07_num_2: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.35e-07_num_2: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.35e-07_num_3: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.35e-07_num_3: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.35e-07_num_3: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 16:21:35[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 16:21:35[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 16:21:40[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 16:21:40[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 28s (30% in total). [31mETA : 2021-01-28 16:22:15[0m (2638 steps). z = 0.0060, h = 9.7856e-07
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 28s (30% in total). [31mETA : 2021-01-28 16:22:15[0m (2638 steps). z = 0.0060, h = 9.7856e-07
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 23s (41% in total). [31mETA : 2021-01-28 16:22:13[0m (3444 steps). z = 0.0083, h = 1.7968e-06
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 23s (41% in total). [31mETA : 2021-01-28 16:22:14[0m (3444 steps). z = 0.0083, h = 1.7968e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 16s (50% in total). [31mETA : 2021-01-28 16:22:08[0m (3706 steps). z = 0.0102, h = 2.8346e-06
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 16s (50% in total). [31mETA : 2021-01-28 16:22:09[0m (3706 steps). z = 0.0102, h = 2.8346e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 12s (60% in total). [31mETA : 2021-01-28 16:22:05[0m (3915 steps). z = 0.0121, h = 8.8081e-06
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 12s (60% in total). [31mETA : 2021-01-28 16:22:05[0m (3915 steps). z = 0.0121, h = 8.8081e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 8s (71% in total). [31mETA : 2021-01-28 16:22:01[0m (4135 steps). z = 0.0143, h = 5.7601e-06
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 8s (71% in total). [31mETA : 2021-01-28 16:22:02[0m (4135 steps). z = 0.0143, h = 5.7601e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 5s (80% in total). [31mETA : 2021-01-28 16:21:59[0m (4307 steps). z = 0.0162, h = 6.6994e-06
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 5s (80% in total). [31mETA : 2021-01-28 16:22:00[0m (4307 steps). z = 0.0162, h = 6.6994e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 16:21:58[0m (4466 steps). z = 0.0181, h = 5.4078e-06
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 16:21:58[0m (4466 steps). z = 0.0181, h = 5.4078e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 16:21:56[0m (4634 steps). z = 0.0200, h = 7.4967e-06
|
||||||
|
wavelength_8.35e-07_num_2: propagation finished in 4634 steps (22.065082 seconds)
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.3e-07), ('num', 0)], job : 88866c7daffdd00effffffff0100000001000000
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 16:21:57[0m (4634 steps). z = 0.0200, h = 7.4967e-06
|
||||||
|
wavelength_8.35e-07_num_3: propagation finished in 4634 steps (22.22073 seconds)
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.3e-07), ('num', 1)], job : d251967856448cebffffffff0100000001000000
|
||||||
|
wavelength_8.3e-07_num_0: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.3e-07_num_0: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.3e-07_num_0: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.3e-07_num_1: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.3e-07_num_1: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.3e-07_num_1: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 16:21:58[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 16:21:59[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 16:22:03[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 16:22:04[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.3e-07_num_0: step 997 rejected with h = 2.7537e-06, doing over
|
||||||
|
wavelength_8.3e-07_num_1: step 997 rejected with h = 2.7537e-06, doing over
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 23s (30% in total). [31mETA : 2021-01-28 16:22:31[0m (2162 steps). z = 0.0060, h = 3.8127e-08
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 23s (30% in total). [31mETA : 2021-01-28 16:22:31[0m (2162 steps). z = 0.0060, h = 3.8127e-08
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 20s (41% in total). [31mETA : 2021-01-28 16:22:32[0m (2991 steps). z = 0.0083, h = 5.8562e-06
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 20s (41% in total). [31mETA : 2021-01-28 16:22:32[0m (2991 steps). z = 0.0083, h = 5.8562e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 15s (50% in total). [31mETA : 2021-01-28 16:22:28[0m (3242 steps). z = 0.0102, h = 6.5756e-06
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 15s (50% in total). [31mETA : 2021-01-28 16:22:28[0m (3242 steps). z = 0.0102, h = 6.5756e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 11s (60% in total). [31mETA : 2021-01-28 16:22:25[0m (3443 steps). z = 0.0121, h = 2.9227e-06
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 11s (60% in total). [31mETA : 2021-01-28 16:22:25[0m (3443 steps). z = 0.0121, h = 2.9227e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 7s (71% in total). [31mETA : 2021-01-28 16:22:22[0m (3664 steps). z = 0.0143, h = 1.1425e-05
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 7s (71% in total). [31mETA : 2021-01-28 16:22:23[0m (3664 steps). z = 0.0143, h = 1.1425e-05
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 4s (80% in total). [31mETA : 2021-01-28 16:22:20[0m (3833 steps). z = 0.0162, h = 1.0515e-05
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 4s (80% in total). [31mETA : 2021-01-28 16:22:21[0m (3833 steps). z = 0.0162, h = 1.0515e-05
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 16:22:19[0m (4003 steps). z = 0.0181, h = 7.4644e-06
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 16:22:20[0m (4003 steps). z = 0.0181, h = 7.4644e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 16:22:18[0m (4181 steps). z = 0.0200, h = 1.21e-05
|
||||||
|
wavelength_8.3e-07_num_0: propagation finished in 4181 steps (20.406912 seconds)
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.3e-07), ('num', 2)], job : 3bf0c856ace5a4d8ffffffff0100000001000000
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 16:22:18[0m (4181 steps). z = 0.0200, h = 1.21e-05
|
||||||
|
wavelength_8.3e-07_num_1: propagation finished in 4181 steps (20.386092 seconds)
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.3e-07), ('num', 3)], job : 72e11b46e93d91e4ffffffff0100000001000000
|
||||||
|
wavelength_8.3e-07_num_2: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.3e-07_num_2: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.3e-07_num_2: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.3e-07_num_3: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.3e-07_num_3: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.3e-07_num_3: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 16:22:20[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 16:22:20[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 16:22:25[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 16:22:25[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.3e-07_num_2: step 997 rejected with h = 2.7537e-06, doing over
|
||||||
|
wavelength_8.3e-07_num_3: step 997 rejected with h = 2.7537e-06, doing over
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 23s (30% in total). [31mETA : 2021-01-28 16:22:52[0m (2162 steps). z = 0.0060, h = 3.8127e-08
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 23s (30% in total). [31mETA : 2021-01-28 16:22:53[0m (2162 steps). z = 0.0060, h = 3.8127e-08
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 20s (41% in total). [31mETA : 2021-01-28 16:22:53[0m (2991 steps). z = 0.0083, h = 5.8562e-06
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 20s (41% in total). [31mETA : 2021-01-28 16:22:54[0m (2991 steps). z = 0.0083, h = 5.8562e-06
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 15s (50% in total). [31mETA : 2021-01-28 16:22:49[0m (3242 steps). z = 0.0102, h = 6.5756e-06
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 15s (50% in total). [31mETA : 2021-01-28 16:22:50[0m (3242 steps). z = 0.0102, h = 6.5756e-06
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 11s (60% in total). [31mETA : 2021-01-28 16:22:46[0m (3443 steps). z = 0.0121, h = 2.9227e-06
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 11s (60% in total). [31mETA : 2021-01-28 16:22:47[0m (3443 steps). z = 0.0121, h = 2.9227e-06
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 7s (71% in total). [31mETA : 2021-01-28 16:22:43[0m (3664 steps). z = 0.0143, h = 1.1425e-05
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 7s (71% in total). [31mETA : 2021-01-28 16:22:44[0m (3664 steps). z = 0.0143, h = 1.1425e-05
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 4s (80% in total). [31mETA : 2021-01-28 16:22:42[0m (3833 steps). z = 0.0162, h = 1.0515e-05
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 4s (80% in total). [31mETA : 2021-01-28 16:22:42[0m (3833 steps). z = 0.0162, h = 1.0515e-05
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 16:22:40[0m (4003 steps). z = 0.0181, h = 7.4644e-06
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 16:22:41[0m (4003 steps). z = 0.0181, h = 7.4644e-06
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 16:22:39[0m (4181 steps). z = 0.0200, h = 1.21e-05
|
||||||
|
wavelength_8.3e-07_num_2: propagation finished in 4181 steps (20.253876 seconds)
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 16:22:40[0m (4181 steps). z = 0.0200, h = 1.21e-05
|
||||||
|
wavelength_8.3e-07_num_3: propagation finished in 4181 steps (20.165082 seconds)
|
||||||
|
scgenerator.physics.simulate: Merging data...
|
||||||
|
scgenerator.physics.simulate: Finished simulations from config full anomalous !
|
||||||
|
scgenerator.physics.simulate: 1 node in the Ray cluster : ['Obento.fritz.box']
|
||||||
|
scgenerator.initialize: computed initial N = 8.66
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 0)], job : df5a1a828c9685d3ffffffff0100000001000000
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 1)], job : cb230a572350ff44ffffffff0100000001000000
|
||||||
|
wavelength_8.35e-07_num_0: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.35e-07_num_0: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.35e-07_num_0: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.35e-07_num_1: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.35e-07_num_1: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.35e-07_num_1: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
scgenerator.physics.simulate: 1 node in the Ray cluster : ['Obento.fritz.box']
|
||||||
|
scgenerator.initialize: computed initial N = 8.66
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 0)], job : df5a1a828c9685d3ffffffff0100000001000000
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 1)], job : cb230a572350ff44ffffffff0100000001000000
|
||||||
|
wavelength_8.35e-07_num_0: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.35e-07_num_0: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.35e-07_num_0: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 16:45:21[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.35e-07_num_1: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.35e-07_num_1: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.35e-07_num_1: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 16:45:22[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 16:45:26[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 16:45:27[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 28s (30% in total). [31mETA : 2021-01-28 16:46:00[0m (2638 steps). z = 0.0060, h = 9.7856e-07
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 28s (30% in total). [31mETA : 2021-01-28 16:46:01[0m (2638 steps). z = 0.0060, h = 9.7856e-07
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 21s (41% in total). [31mETA : 2021-01-28 16:45:57[0m (3444 steps). z = 0.0083, h = 1.7968e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 21s (41% in total). [31mETA : 2021-01-28 16:45:58[0m (3444 steps). z = 0.0083, h = 1.7968e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 16s (50% in total). [31mETA : 2021-01-28 16:45:53[0m (3706 steps). z = 0.0102, h = 2.8346e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 16s (50% in total). [31mETA : 2021-01-28 16:45:53[0m (3706 steps). z = 0.0102, h = 2.8346e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 11s (60% in total). [31mETA : 2021-01-28 16:45:49[0m (3915 steps). z = 0.0121, h = 8.8081e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 11s (60% in total). [31mETA : 2021-01-28 16:45:50[0m (3915 steps). z = 0.0121, h = 8.8081e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 7s (71% in total). [31mETA : 2021-01-28 16:45:46[0m (4135 steps). z = 0.0143, h = 5.7601e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 7s (71% in total). [31mETA : 2021-01-28 16:45:47[0m (4135 steps). z = 0.0143, h = 5.7601e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 4s (80% in total). [31mETA : 2021-01-28 16:45:44[0m (4307 steps). z = 0.0162, h = 6.6994e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 4s (80% in total). [31mETA : 2021-01-28 16:45:45[0m (4307 steps). z = 0.0162, h = 6.6994e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 16:45:43[0m (4466 steps). z = 0.0181, h = 5.4078e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 16:45:44[0m (4466 steps). z = 0.0181, h = 5.4078e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 16:45:42[0m (4634 steps). z = 0.0200, h = 7.4967e-06
|
||||||
|
wavelength_8.35e-07_num_0: propagation finished in 4634 steps (21.323236 seconds)
|
||||||
|
scgenerator.physics.simulate: [34mremaining : 0h 2min 41s (12% in total). [31mETA : 2021-01-28 16:48:23[0m
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 2)], job : 7bbd90284b71e599ffffffff0100000001000000
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 16:45:42[0m (4634 steps). z = 0.0200, h = 7.4967e-06
|
||||||
|
wavelength_8.35e-07_num_1: propagation finished in 4634 steps (21.296093 seconds)
|
||||||
|
scgenerator.physics.simulate: [34mremaining : 0h 1min 9s (25% in total). [31mETA : 2021-01-28 16:46:51[0m
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 3)], job : bd37d2621480fc7dffffffff0100000001000000
|
||||||
|
scgenerator.initialize: computed initial N = 8.66
|
||||||
|
wavelength_8.35e-07_num_2: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.35e-07_num_2: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.35e-07_num_2: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.35e-07_num_3: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.35e-07_num_3: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.35e-07_num_3: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 16:45:43[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 16:45:44[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 16:45:48[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 16:45:49[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 28s (30% in total). [31mETA : 2021-01-28 16:46:23[0m (2638 steps). z = 0.0060, h = 9.7856e-07
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 28s (30% in total). [31mETA : 2021-01-28 16:46:24[0m (2638 steps). z = 0.0060, h = 9.7856e-07
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 23s (41% in total). [31mETA : 2021-01-28 16:46:22[0m (3444 steps). z = 0.0083, h = 1.7968e-06
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 23s (41% in total). [31mETA : 2021-01-28 16:46:23[0m (3444 steps). z = 0.0083, h = 1.7968e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 16s (50% in total). [31mETA : 2021-01-28 16:46:17[0m (3706 steps). z = 0.0102, h = 2.8346e-06
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 16s (50% in total). [31mETA : 2021-01-28 16:46:17[0m (3706 steps). z = 0.0102, h = 2.8346e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 12s (60% in total). [31mETA : 2021-01-28 16:46:13[0m (3915 steps). z = 0.0121, h = 8.8081e-06
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 12s (60% in total). [31mETA : 2021-01-28 16:46:14[0m (3915 steps). z = 0.0121, h = 8.8081e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 8s (71% in total). [31mETA : 2021-01-28 16:46:10[0m (4135 steps). z = 0.0143, h = 5.7601e-06
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 8s (71% in total). [31mETA : 2021-01-28 16:46:11[0m (4135 steps). z = 0.0143, h = 5.7601e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 5s (80% in total). [31mETA : 2021-01-28 16:46:08[0m (4307 steps). z = 0.0162, h = 6.6994e-06
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 5s (80% in total). [31mETA : 2021-01-28 16:46:08[0m (4307 steps). z = 0.0162, h = 6.6994e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 16:46:06[0m (4466 steps). z = 0.0181, h = 5.4078e-06
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 16:46:07[0m (4466 steps). z = 0.0181, h = 5.4078e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 16:46:05[0m (4634 steps). z = 0.0200, h = 7.4967e-06
|
||||||
|
wavelength_8.35e-07_num_2: propagation finished in 4634 steps (22.109413 seconds)
|
||||||
|
scgenerator.physics.simulate: [34mremaining : 0h 1min 17s (37% in total). [31mETA : 2021-01-28 16:47:21[0m
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.3e-07), ('num', 0)], job : 88866c7daffdd00effffffff0100000001000000
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 16:46:05[0m (4634 steps). z = 0.0200, h = 7.4967e-06
|
||||||
|
wavelength_8.35e-07_num_3: propagation finished in 4634 steps (22.079782 seconds)
|
||||||
|
scgenerator.physics.simulate: [34mremaining : 0h 0min 47s (50% in total). [31mETA : 2021-01-28 16:46:52[0m
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.3e-07), ('num', 1)], job : d251967856448cebffffffff0100000001000000
|
||||||
|
wavelength_8.3e-07_num_0: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.3e-07_num_0: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.3e-07_num_0: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.3e-07_num_1: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.3e-07_num_1: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.3e-07_num_1: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 16:46:06[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 16:46:07[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 16:46:11[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 16:46:12[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.3e-07_num_0: step 997 rejected with h = 2.7537e-06, doing over
|
||||||
|
wavelength_8.3e-07_num_1: step 997 rejected with h = 2.7537e-06, doing over
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 21s (30% in total). [31mETA : 2021-01-28 16:46:36[0m (2162 steps). z = 0.0060, h = 3.8127e-08
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 21s (30% in total). [31mETA : 2021-01-28 16:46:37[0m (2162 steps). z = 0.0060, h = 3.8127e-08
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 19s (41% in total). [31mETA : 2021-01-28 16:46:38[0m (2991 steps). z = 0.0083, h = 5.8562e-06
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 19s (41% in total). [31mETA : 2021-01-28 16:46:38[0m (2991 steps). z = 0.0083, h = 5.8562e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 14s (50% in total). [31mETA : 2021-01-28 16:46:34[0m (3242 steps). z = 0.0102, h = 6.5756e-06
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 14s (50% in total). [31mETA : 2021-01-28 16:46:35[0m (3242 steps). z = 0.0102, h = 6.5756e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 10s (60% in total). [31mETA : 2021-01-28 16:46:31[0m (3443 steps). z = 0.0121, h = 2.9227e-06
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 10s (60% in total). [31mETA : 2021-01-28 16:46:32[0m (3443 steps). z = 0.0121, h = 2.9227e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 6s (71% in total). [31mETA : 2021-01-28 16:46:29[0m (3664 steps). z = 0.0143, h = 1.1425e-05
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 6s (71% in total). [31mETA : 2021-01-28 16:46:29[0m (3664 steps). z = 0.0143, h = 1.1425e-05
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 4s (80% in total). [31mETA : 2021-01-28 16:46:27[0m (3833 steps). z = 0.0162, h = 1.0515e-05
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 4s (80% in total). [31mETA : 2021-01-28 16:46:28[0m (3833 steps). z = 0.0162, h = 1.0515e-05
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 16:46:26[0m (4003 steps). z = 0.0181, h = 7.4644e-06
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 16:46:26[0m (4003 steps). z = 0.0181, h = 7.4644e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 16:46:25[0m (4181 steps). z = 0.0200, h = 1.21e-05
|
||||||
|
wavelength_8.3e-07_num_0: propagation finished in 4181 steps (19.058624 seconds)
|
||||||
|
scgenerator.physics.simulate: [34mremaining : 0h 0min 40s (62% in total). [31mETA : 2021-01-28 16:47:04[0m
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.3e-07), ('num', 2)], job : 3bf0c856ace5a4d8ffffffff0100000001000000
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 16:46:25[0m (4181 steps). z = 0.0200, h = 1.21e-05
|
||||||
|
wavelength_8.3e-07_num_1: propagation finished in 4181 steps (19.191059 seconds)
|
||||||
|
scgenerator.physics.simulate: [34mremaining : 0h 0min 22s (75% in total). [31mETA : 2021-01-28 16:46:48[0m
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.3e-07), ('num', 3)], job : 72e11b46e93d91e4ffffffff0100000001000000
|
||||||
|
wavelength_8.3e-07_num_2: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.3e-07_num_2: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.3e-07_num_2: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.3e-07_num_3: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.3e-07_num_3: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.3e-07_num_3: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 16:46:27[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 16:46:27[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 16:46:32[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 8s (20% in total). [31mETA : 2021-01-28 16:46:36[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.3e-07_num_2: step 997 rejected with h = 2.7537e-06, doing over
|
||||||
|
wavelength_8.3e-07_num_3: step 997 rejected with h = 2.7537e-06, doing over
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 25s (30% in total). [31mETA : 2021-01-28 16:47:02[0m (2162 steps). z = 0.0060, h = 3.8127e-08
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 25s (30% in total). [31mETA : 2021-01-28 16:47:03[0m (2162 steps). z = 0.0060, h = 3.8127e-08
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 21s (41% in total). [31mETA : 2021-01-28 16:47:02[0m (2991 steps). z = 0.0083, h = 5.8562e-06
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 20s (41% in total). [31mETA : 2021-01-28 16:47:01[0m (2991 steps). z = 0.0083, h = 5.8562e-06
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 16s (50% in total). [31mETA : 2021-01-28 16:46:58[0m (3242 steps). z = 0.0102, h = 6.5756e-06
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 16s (50% in total). [31mETA : 2021-01-28 16:46:58[0m (3242 steps). z = 0.0102, h = 6.5756e-06
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 11s (60% in total). [31mETA : 2021-01-28 16:46:54[0m (3443 steps). z = 0.0121, h = 2.9227e-06
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 11s (60% in total). [31mETA : 2021-01-28 16:46:55[0m (3443 steps). z = 0.0121, h = 2.9227e-06
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 7s (71% in total). [31mETA : 2021-01-28 16:46:51[0m (3664 steps). z = 0.0143, h = 1.1425e-05
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 7s (71% in total). [31mETA : 2021-01-28 16:46:52[0m (3664 steps). z = 0.0143, h = 1.1425e-05
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 4s (80% in total). [31mETA : 2021-01-28 16:46:49[0m (3833 steps). z = 0.0162, h = 1.0515e-05
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 4s (80% in total). [31mETA : 2021-01-28 16:46:50[0m (3833 steps). z = 0.0162, h = 1.0515e-05
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 16:46:48[0m (4003 steps). z = 0.0181, h = 7.4644e-06
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 16:46:48[0m (4003 steps). z = 0.0181, h = 7.4644e-06
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 16:46:47[0m (4181 steps). z = 0.0200, h = 1.21e-05
|
||||||
|
wavelength_8.3e-07_num_2: propagation finished in 4181 steps (20.62597 seconds)
|
||||||
|
scgenerator.physics.simulate: [34mremaining : 0h 0min 13s (87% in total). [31mETA : 2021-01-28 16:46:59[0m
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 16:46:47[0m (4181 steps). z = 0.0200, h = 1.21e-05
|
||||||
|
wavelength_8.3e-07_num_3: propagation finished in 4181 steps (20.517408 seconds)
|
||||||
|
scgenerator.physics.simulate: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 16:46:47[0m
|
||||||
|
scgenerator.physics.simulate: Merging data...
|
||||||
|
scgenerator.physics.simulate: Finished simulations from config full anomalous !
|
||||||
|
scgenerator.initialize: using computed ɣ = 2.00e-02 W/m^2
|
||||||
|
scgenerator.initialize: computed initial N = 17.4
|
||||||
|
scgenerator.initialize: intensity noise of 0.0005
|
||||||
|
scgenerator.initialize: computed initial N = 8.66
|
||||||
|
scgenerator.initialize: computed initial N = 8.66
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 0)]
|
||||||
|
wavelength_8.35e-07_num_0: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.35e-07_num_0: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.35e-07_num_0: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 19:54:08[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 19:54:13[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 23s (30% in total). [31mETA : 2021-01-28 19:54:41[0m (2638 steps). z = 0.0060, h = 9.7856e-07
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 19s (41% in total). [31mETA : 2021-01-28 19:54:39[0m (3444 steps). z = 0.0083, h = 1.7968e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 14s (50% in total). [31mETA : 2021-01-28 19:54:36[0m (3706 steps). z = 0.0102, h = 2.8346e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 10s (60% in total). [31mETA : 2021-01-28 19:54:33[0m (3915 steps). z = 0.0121, h = 8.8081e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 6s (71% in total). [31mETA : 2021-01-28 19:54:30[0m (4135 steps). z = 0.0143, h = 5.7601e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 4s (80% in total). [31mETA : 2021-01-28 19:54:28[0m (4307 steps). z = 0.0162, h = 6.6994e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 19:54:27[0m (4466 steps). z = 0.0181, h = 5.4078e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 19:54:26[0m (4634 steps). z = 0.0200, h = 7.4967e-06
|
||||||
|
wavelength_8.35e-07_num_0: propagation finished in 4634 steps (18.270374 seconds)
|
||||||
|
scgenerator.physics.simulate: [34mremaining : 0h 2min 6s (12% in total). [31mETA : 2021-01-28 19:56:32[0m
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 1)]
|
||||||
|
scgenerator.initialize: computed initial N = 8.66
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 0)]
|
||||||
|
wavelength_8.35e-07_num_0: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.35e-07_num_0: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.35e-07_num_0: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 19:56:42[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 19:56:47[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 23s (30% in total). [31mETA : 2021-01-28 19:57:15[0m (2638 steps). z = 0.0060, h = 9.7856e-07
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 19s (41% in total). [31mETA : 2021-01-28 19:57:14[0m (3444 steps). z = 0.0083, h = 1.7968e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 14s (50% in total). [31mETA : 2021-01-28 19:57:10[0m (3706 steps). z = 0.0102, h = 2.8346e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 10s (60% in total). [31mETA : 2021-01-28 19:57:07[0m (3915 steps). z = 0.0121, h = 8.8081e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 6s (71% in total). [31mETA : 2021-01-28 19:57:04[0m (4135 steps). z = 0.0143, h = 5.7601e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 4s (80% in total). [31mETA : 2021-01-28 19:57:03[0m (4307 steps). z = 0.0162, h = 6.6994e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 19:57:01[0m (4466 steps). z = 0.0181, h = 5.4078e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 19:57:00[0m (4634 steps). z = 0.0200, h = 7.4967e-06
|
||||||
|
wavelength_8.35e-07_num_0: propagation finished in 4634 steps (18.345039 seconds)
|
||||||
|
scgenerator.physics.simulate: [34mremaining : 0h 2min 6s (12% in total). [31mETA : 2021-01-28 19:59:06[0m
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 1)]
|
||||||
|
scgenerator.initialize: computed initial N = 8.66
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 0)]
|
||||||
|
wavelength_8.35e-07_num_0: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.35e-07_num_0: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.35e-07_num_0: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 19:59:41[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 19:59:46[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 23s (30% in total). [31mETA : 2021-01-28 20:00:15[0m (2638 steps). z = 0.0060, h = 9.7856e-07
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 20s (41% in total). [31mETA : 2021-01-28 20:00:15[0m (3444 steps). z = 0.0083, h = 1.7968e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 15s (50% in total). [31mETA : 2021-01-28 20:00:10[0m (3706 steps). z = 0.0102, h = 2.8346e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 10s (60% in total). [31mETA : 2021-01-28 20:00:07[0m (3915 steps). z = 0.0121, h = 8.8081e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 6s (71% in total). [31mETA : 2021-01-28 20:00:04[0m (4135 steps). z = 0.0143, h = 5.7601e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 4s (80% in total). [31mETA : 2021-01-28 20:00:02[0m (4307 steps). z = 0.0162, h = 6.6994e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 20:00:01[0m (4466 steps). z = 0.0181, h = 5.4078e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 20:00:00[0m (4634 steps). z = 0.0200, h = 7.4967e-06
|
||||||
|
wavelength_8.35e-07_num_0: propagation finished in 4634 steps (18.838541 seconds)
|
||||||
|
scgenerator.physics.simulate: [34mremaining : 0h 2min 6s (12% in total). [31mETA : 2021-01-28 20:02:06[0m
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 1)]
|
||||||
|
scgenerator.initialize: computed initial N = 8.66
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 0)]
|
||||||
|
wavelength_8.35e-07_num_0: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.35e-07_num_0: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.35e-07_num_0: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 20:01:06[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 20:01:11[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 23s (30% in total). [31mETA : 2021-01-28 20:01:40[0m (2638 steps). z = 0.0060, h = 9.7856e-07
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 20s (41% in total). [31mETA : 2021-01-28 20:01:40[0m (3444 steps). z = 0.0083, h = 1.7968e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 15s (50% in total). [31mETA : 2021-01-28 20:01:36[0m (3706 steps). z = 0.0102, h = 2.8346e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 11s (60% in total). [31mETA : 2021-01-28 20:01:33[0m (3915 steps). z = 0.0121, h = 8.8081e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 7s (71% in total). [31mETA : 2021-01-28 20:01:30[0m (4135 steps). z = 0.0143, h = 5.7601e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 4s (80% in total). [31mETA : 2021-01-28 20:01:28[0m (4307 steps). z = 0.0162, h = 6.6994e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 20:01:26[0m (4466 steps). z = 0.0181, h = 5.4078e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 20:01:25[0m (4634 steps). z = 0.0200, h = 7.4967e-06
|
||||||
|
wavelength_8.35e-07_num_0: propagation finished in 4634 steps (19.588611 seconds)
|
||||||
|
scgenerator.physics.simulate: [34mremaining : 0h 2min 13s (12% in total). [31mETA : 2021-01-28 20:03:38[0m
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 1)]
|
||||||
|
wavelength_8.35e-07_num_1: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.35e-07_num_1: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.35e-07_num_1: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 20:01:26[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 20:01:31[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 28s (30% in total). [31mETA : 2021-01-28 20:02:06[0m (2638 steps). z = 0.0060, h = 9.7856e-07
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 21s (41% in total). [31mETA : 2021-01-28 20:02:03[0m (3444 steps). z = 0.0083, h = 1.7968e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 16s (50% in total). [31mETA : 2021-01-28 20:01:59[0m (3706 steps). z = 0.0102, h = 2.8346e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 11s (60% in total). [31mETA : 2021-01-28 20:01:55[0m (3915 steps). z = 0.0121, h = 8.8081e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 7s (71% in total). [31mETA : 2021-01-28 20:01:51[0m (4135 steps). z = 0.0143, h = 5.7601e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 4s (80% in total). [31mETA : 2021-01-28 20:01:49[0m (4307 steps). z = 0.0162, h = 6.6994e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 20:01:48[0m (4466 steps). z = 0.0181, h = 5.4078e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 20:01:46[0m (4634 steps). z = 0.0200, h = 7.4967e-06
|
||||||
|
wavelength_8.35e-07_num_1: propagation finished in 4634 steps (20.783914 seconds)
|
||||||
|
scgenerator.physics.simulate: [34mremaining : 0h 2min 0s (25% in total). [31mETA : 2021-01-28 20:03:46[0m
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 2)]
|
||||||
|
wavelength_8.35e-07_num_2: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.35e-07_num_2: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.35e-07_num_2: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
scgenerator.initialize: computed initial N = 8.66
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 0)]
|
||||||
|
wavelength_8.35e-07_num_0: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.35e-07_num_0: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.35e-07_num_0: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 20:03:06[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 4s (20% in total). [31mETA : 2021-01-28 20:03:11[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
scgenerator.physics.simulate: 1 node in the Ray cluster : ['Obento.fritz.box']
|
||||||
|
scgenerator.initialize: computed initial N = 8.66
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 0)], job : df5a1a828c9685d3ffffffff0100000001000000
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 1)], job : cb230a572350ff44ffffffff0100000001000000
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 2)], job : 7bbd90284b71e599ffffffff0100000001000000
|
||||||
|
wavelength_8.35e-07_num_0: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.35e-07_num_0: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.35e-07_num_0: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.35e-07_num_1: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.35e-07_num_1: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.35e-07_num_2: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.35e-07_num_1: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.35e-07_num_2: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.35e-07_num_2: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 8s (11% in total). [31mETA : 2021-01-28 20:03:57[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 8s (11% in total). [31mETA : 2021-01-28 20:03:57[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 8s (11% in total). [31mETA : 2021-01-28 20:03:57[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 8s (20% in total). [31mETA : 2021-01-28 20:03:58[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 8s (20% in total). [31mETA : 2021-01-28 20:03:58[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 8s (20% in total). [31mETA : 2021-01-28 20:03:58[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 37s (30% in total). [31mETA : 2021-01-28 20:04:41[0m (2638 steps). z = 0.0060, h = 9.7856e-07
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 37s (30% in total). [31mETA : 2021-01-28 20:04:41[0m (2638 steps). z = 0.0060, h = 9.7856e-07
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 37s (30% in total). [31mETA : 2021-01-28 20:04:41[0m (2638 steps). z = 0.0060, h = 9.7856e-07
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 30s (41% in total). [31mETA : 2021-01-28 20:04:39[0m (3444 steps). z = 0.0083, h = 1.7968e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 30s (41% in total). [31mETA : 2021-01-28 20:04:39[0m (3444 steps). z = 0.0083, h = 1.7968e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 30s (41% in total). [31mETA : 2021-01-28 20:04:39[0m (3444 steps). z = 0.0083, h = 1.7968e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 22s (50% in total). [31mETA : 2021-01-28 20:04:33[0m (3706 steps). z = 0.0102, h = 2.8346e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 22s (50% in total). [31mETA : 2021-01-28 20:04:33[0m (3706 steps). z = 0.0102, h = 2.8346e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 22s (50% in total). [31mETA : 2021-01-28 20:04:33[0m (3706 steps). z = 0.0102, h = 2.8346e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 16s (60% in total). [31mETA : 2021-01-28 20:04:28[0m (3915 steps). z = 0.0121, h = 8.8081e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 16s (60% in total). [31mETA : 2021-01-28 20:04:28[0m (3915 steps). z = 0.0121, h = 8.8081e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 16s (60% in total). [31mETA : 2021-01-28 20:04:28[0m (3915 steps). z = 0.0121, h = 8.8081e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 10s (71% in total). [31mETA : 2021-01-28 20:04:24[0m (4135 steps). z = 0.0143, h = 5.7601e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 10s (71% in total). [31mETA : 2021-01-28 20:04:24[0m (4135 steps). z = 0.0143, h = 5.7601e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 10s (71% in total). [31mETA : 2021-01-28 20:04:24[0m (4135 steps). z = 0.0143, h = 5.7601e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 6s (80% in total). [31mETA : 2021-01-28 20:04:21[0m (4307 steps). z = 0.0162, h = 6.6994e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 6s (80% in total). [31mETA : 2021-01-28 20:04:21[0m (4307 steps). z = 0.0162, h = 6.6994e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 6s (80% in total). [31mETA : 2021-01-28 20:04:21[0m (4307 steps). z = 0.0162, h = 6.6994e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 3s (90% in total). [31mETA : 2021-01-28 20:04:18[0m (4466 steps). z = 0.0181, h = 5.4078e-06
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 3s (90% in total). [31mETA : 2021-01-28 20:04:19[0m (4466 steps). z = 0.0181, h = 5.4078e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 3s (90% in total). [31mETA : 2021-01-28 20:04:19[0m (4466 steps). z = 0.0181, h = 5.4078e-06
|
||||||
|
wavelength_8.35e-07_num_2: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 20:04:17[0m (4634 steps). z = 0.0200, h = 7.4967e-06
|
||||||
|
wavelength_8.35e-07_num_2: propagation finished in 4634 steps (28.97378 seconds)
|
||||||
|
scgenerator.physics.simulate: [34mremaining : 0h 3min 30s (12% in total). [31mETA : 2021-01-28 20:07:47[0m
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.35e-07), ('num', 3)], job : bd37d2621480fc7dffffffff0100000001000000
|
||||||
|
scgenerator.initialize: computed initial N = 8.66
|
||||||
|
wavelength_8.35e-07_num_0: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 20:04:17[0m (4634 steps). z = 0.0200, h = 7.4967e-06
|
||||||
|
wavelength_8.35e-07_num_1: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 20:04:17[0m (4634 steps). z = 0.0200, h = 7.4967e-06
|
||||||
|
wavelength_8.35e-07_num_0: propagation finished in 4634 steps (29.131892 seconds)
|
||||||
|
wavelength_8.35e-07_num_1: propagation finished in 4634 steps (29.093002 seconds)
|
||||||
|
scgenerator.physics.simulate: [34mremaining : 0h 1min 33s (25% in total). [31mETA : 2021-01-28 20:05:50[0m
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.3e-07), ('num', 0)], job : 88866c7daffdd00effffffff0100000001000000
|
||||||
|
scgenerator.physics.simulate: [34mremaining : 0h 0min 52s (37% in total). [31mETA : 2021-01-28 20:05:08[0m
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.3e-07), ('num', 1)], job : d251967856448cebffffffff0100000001000000
|
||||||
|
wavelength_8.35e-07_num_3: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.35e-07_num_3: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.35e-07_num_3: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.3e-07_num_0: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.3e-07_num_0: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.3e-07_num_0: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.3e-07_num_1: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.3e-07_num_1: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.3e-07_num_1: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 20:04:18[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 20:04:19[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 0s (11% in total). [31mETA : 2021-01-28 20:04:19[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 8s (20% in total). [31mETA : 2021-01-28 20:04:28[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 8s (20% in total). [31mETA : 2021-01-28 20:04:28[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 8s (20% in total). [31mETA : 2021-01-28 20:04:28[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.3e-07_num_0: step 997 rejected with h = 2.7537e-06, doing over
|
||||||
|
wavelength_8.3e-07_num_1: step 997 rejected with h = 2.7537e-06, doing over
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 30s (30% in total). [31mETA : 2021-01-28 20:05:01[0m (2162 steps). z = 0.0060, h = 3.8127e-08
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 30s (30% in total). [31mETA : 2021-01-28 20:05:01[0m (2162 steps). z = 0.0060, h = 3.8127e-08
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 35s (30% in total). [31mETA : 2021-01-28 20:05:08[0m (2638 steps). z = 0.0060, h = 9.7856e-07
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 24s (41% in total). [31mETA : 2021-01-28 20:05:00[0m (2991 steps). z = 0.0083, h = 5.8562e-06
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 24s (41% in total). [31mETA : 2021-01-28 20:05:00[0m (2991 steps). z = 0.0083, h = 5.8562e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 18s (50% in total). [31mETA : 2021-01-28 20:04:56[0m (3242 steps). z = 0.0102, h = 6.5756e-06
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 18s (50% in total). [31mETA : 2021-01-28 20:04:56[0m (3242 steps). z = 0.0102, h = 6.5756e-06
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 28s (41% in total). [31mETA : 2021-01-28 20:05:07[0m (3444 steps). z = 0.0083, h = 1.7968e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 13s (60% in total). [31mETA : 2021-01-28 20:04:52[0m (3443 steps). z = 0.0121, h = 2.9227e-06
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 13s (60% in total). [31mETA : 2021-01-28 20:04:52[0m (3443 steps). z = 0.0121, h = 2.9227e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 9s (71% in total). [31mETA : 2021-01-28 20:04:49[0m (3664 steps). z = 0.0143, h = 1.1425e-05
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 9s (71% in total). [31mETA : 2021-01-28 20:04:49[0m (3664 steps). z = 0.0143, h = 1.1425e-05
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 21s (50% in total). [31mETA : 2021-01-28 20:05:01[0m (3706 steps). z = 0.0102, h = 2.8346e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 5s (80% in total). [31mETA : 2021-01-28 20:04:46[0m (3833 steps). z = 0.0162, h = 1.0515e-05
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 5s (80% in total). [31mETA : 2021-01-28 20:04:46[0m (3833 steps). z = 0.0162, h = 1.0515e-05
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 16s (60% in total). [31mETA : 2021-01-28 20:04:58[0m (3915 steps). z = 0.0121, h = 8.8081e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 3s (90% in total). [31mETA : 2021-01-28 20:04:46[0m (4003 steps). z = 0.0181, h = 7.4644e-06
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 3s (90% in total). [31mETA : 2021-01-28 20:04:46[0m (4003 steps). z = 0.0181, h = 7.4644e-06
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 10s (71% in total). [31mETA : 2021-01-28 20:04:55[0m (4135 steps). z = 0.0143, h = 5.7601e-06
|
||||||
|
wavelength_8.3e-07_num_0: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 20:04:45[0m (4181 steps). z = 0.0200, h = 1.21e-05
|
||||||
|
wavelength_8.3e-07_num_1: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 20:04:45[0m (4181 steps). z = 0.0200, h = 1.21e-05
|
||||||
|
wavelength_8.3e-07_num_0: propagation finished in 4181 steps (27.237882 seconds)
|
||||||
|
wavelength_8.3e-07_num_1: propagation finished in 4181 steps (27.326729 seconds)
|
||||||
|
scgenerator.physics.simulate: [34mremaining : 0h 0min 59s (50% in total). [31mETA : 2021-01-28 20:05:44[0m
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.3e-07), ('num', 2)], job : 3bf0c856ace5a4d8ffffffff0100000001000000
|
||||||
|
scgenerator.physics.simulate: [34mremaining : 0h 0min 35s (62% in total). [31mETA : 2021-01-28 20:05:21[0m
|
||||||
|
scgenerator.physics.simulate: launching simulation with [('wavelength', 8.3e-07), ('num', 3)], job : 72e11b46e93d91e4ffffffff0100000001000000
|
||||||
|
wavelength_8.3e-07_num_2: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.3e-07_num_2: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.3e-07_num_2: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.3e-07_num_3: Storing 63 new spectra, first one at 0.00031746031746031746m
|
||||||
|
wavelength_8.3e-07_num_3: step 1 rejected with h = 1.5873e-04, doing over
|
||||||
|
wavelength_8.3e-07_num_3: step 1 rejected with h = 7.9365e-05, doing over
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 7s (80% in total). [31mETA : 2021-01-28 20:04:54[0m (4307 steps). z = 0.0162, h = 6.6994e-06
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 8s (11% in total). [31mETA : 2021-01-28 20:04:56[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 8s (11% in total). [31mETA : 2021-01-28 20:04:56[0m (132 steps). z = 0.0022, h = 5.5668e-06
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 3s (90% in total). [31mETA : 2021-01-28 20:04:52[0m (4466 steps). z = 0.0181, h = 5.4078e-06
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 8s (20% in total). [31mETA : 2021-01-28 20:04:57[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.35e-07_num_3: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 20:04:50[0m (4634 steps). z = 0.0200, h = 7.4967e-06
|
||||||
|
wavelength_8.35e-07_num_3: propagation finished in 4634 steps (31.918563 seconds)
|
||||||
|
scgenerator.physics.simulate: [34mremaining : 0h 0min 21s (75% in total). [31mETA : 2021-01-28 20:05:11[0m
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 8s (20% in total). [31mETA : 2021-01-28 20:04:57[0m (353 steps). z = 0.0041, h = 4.8586e-06
|
||||||
|
wavelength_8.3e-07_num_3: step 997 rejected with h = 2.7537e-06, doing over
|
||||||
|
wavelength_8.3e-07_num_2: step 997 rejected with h = 2.7537e-06, doing over
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 25s (30% in total). [31mETA : 2021-01-28 20:05:24[0m (2162 steps). z = 0.0060, h = 3.8127e-08
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 25s (30% in total). [31mETA : 2021-01-28 20:05:24[0m (2162 steps). z = 0.0060, h = 3.8127e-08
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 21s (41% in total). [31mETA : 2021-01-28 20:05:24[0m (2991 steps). z = 0.0083, h = 5.8562e-06
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 21s (41% in total). [31mETA : 2021-01-28 20:05:24[0m (2991 steps). z = 0.0083, h = 5.8562e-06
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 16s (50% in total). [31mETA : 2021-01-28 20:05:20[0m (3242 steps). z = 0.0102, h = 6.5756e-06
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 16s (50% in total). [31mETA : 2021-01-28 20:05:21[0m (3242 steps). z = 0.0102, h = 6.5756e-06
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 12s (60% in total). [31mETA : 2021-01-28 20:05:17[0m (3443 steps). z = 0.0121, h = 2.9227e-06
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 12s (60% in total). [31mETA : 2021-01-28 20:05:17[0m (3443 steps). z = 0.0121, h = 2.9227e-06
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 8s (71% in total). [31mETA : 2021-01-28 20:05:14[0m (3664 steps). z = 0.0143, h = 1.1425e-05
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 8s (71% in total). [31mETA : 2021-01-28 20:05:14[0m (3664 steps). z = 0.0143, h = 1.1425e-05
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 5s (80% in total). [31mETA : 2021-01-28 20:05:12[0m (3833 steps). z = 0.0162, h = 1.0515e-05
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 5s (80% in total). [31mETA : 2021-01-28 20:05:13[0m (3833 steps). z = 0.0162, h = 1.0515e-05
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 20:05:11[0m (4003 steps). z = 0.0181, h = 7.4644e-06
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 2s (90% in total). [31mETA : 2021-01-28 20:05:11[0m (4003 steps). z = 0.0181, h = 7.4644e-06
|
||||||
|
wavelength_8.3e-07_num_2: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 20:05:10[0m (4181 steps). z = 0.0200, h = 1.21e-05
|
||||||
|
wavelength_8.3e-07_num_2: propagation finished in 4181 steps (22.964871 seconds)
|
||||||
|
scgenerator.physics.simulate: [34mremaining : 0h 0min 12s (87% in total). [31mETA : 2021-01-28 20:05:22[0m
|
||||||
|
wavelength_8.3e-07_num_3: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 20:05:10[0m (4181 steps). z = 0.0200, h = 1.21e-05
|
||||||
|
wavelength_8.3e-07_num_3: propagation finished in 4181 steps (22.72864 seconds)
|
||||||
|
scgenerator.physics.simulate: [34mremaining : 0h 0min 0s (100% in total). [31mETA : 2021-01-28 20:05:10[0m
|
||||||
|
scgenerator.physics.simulate: Merging data...
|
||||||
|
scgenerator.physics.simulate: Finished simulations from config full anomalous !
|
||||||
36
setup.cfg
Normal file
36
setup.cfg
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
[metadata]
|
||||||
|
name = scgenerator
|
||||||
|
version = 0.0.1
|
||||||
|
description = Simulated PCFs and supercontinuum generation !
|
||||||
|
author = Benoit Sierro
|
||||||
|
author_email = benoit.sierro@iap.unibe.ch
|
||||||
|
long_description = file: README.md
|
||||||
|
long_description_content_type = text/markdown
|
||||||
|
keywords = supercontinuum, nonlinear optics, GNLSE
|
||||||
|
license = MIT
|
||||||
|
classifiers =
|
||||||
|
License :: OSI Approved :: MIT
|
||||||
|
Programming Language :: Python :: 3
|
||||||
|
|
||||||
|
[options]
|
||||||
|
zip_safe = False
|
||||||
|
include_package_data = True
|
||||||
|
packages = find:
|
||||||
|
package_dir =
|
||||||
|
= src
|
||||||
|
install_requires =
|
||||||
|
numpy
|
||||||
|
matplotlib
|
||||||
|
scipy
|
||||||
|
ray
|
||||||
|
|
||||||
|
|
||||||
|
[options.package_data]
|
||||||
|
scgenerator =
|
||||||
|
data/hr_t.npz
|
||||||
|
data/default_params.json
|
||||||
|
data/gas.json
|
||||||
|
data/silica.json
|
||||||
|
|
||||||
|
[options.packages.find]
|
||||||
|
where = src
|
||||||
7
src/scgenerator/__init__.py
Normal file
7
src/scgenerator/__init__.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
from . import initialize, io, math, plotting, state, utilities
|
||||||
|
from .initialize import compute_init_parameters
|
||||||
|
from .io import Paths, iter_load_sim_data, load_toml, load_sim_data
|
||||||
|
from .math import abs2, argclosest, span
|
||||||
|
from .physics import fiber, materials, pulse, simulate, units
|
||||||
|
from .physics.simulate import RK4IP, parallel_simulations
|
||||||
|
from .plotting import plot_avg, plot_results_1D, plot_results_2D, plot_spectrogram
|
||||||
25
src/scgenerator/cli/__main__.py
Normal file
25
src/scgenerator/cli/__main__.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import argparse
|
||||||
|
|
||||||
|
def create_parser():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="scgenerator command",
|
||||||
|
prog="scgenerator"
|
||||||
|
)
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = create_parser()
|
||||||
|
subparsers = parser.add_subparsers(
|
||||||
|
help="sub-command help"
|
||||||
|
)
|
||||||
|
|
||||||
|
newconfig = subparsers.add_parser(
|
||||||
|
"newconfig",
|
||||||
|
help="create a new configuration file"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
195
src/scgenerator/const.py
Normal file
195
src/scgenerator/const.py
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
def num(n):
|
||||||
|
"""must be a single, real, non-negative number"""
|
||||||
|
return isinstance(n, (float, int)) and n >= 0
|
||||||
|
|
||||||
|
|
||||||
|
def integer(n):
|
||||||
|
"""must be a strictly positive integer"""
|
||||||
|
return isinstance(n, int) and n > 0
|
||||||
|
|
||||||
|
|
||||||
|
def boolean(b):
|
||||||
|
"""must be a boolean"""
|
||||||
|
return type(b) == bool
|
||||||
|
|
||||||
|
|
||||||
|
def behaviors(l):
|
||||||
|
"""must be a valid list of behaviors"""
|
||||||
|
for s in l:
|
||||||
|
if s.lower() not in ["spm", "raman", "ss"]:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def beta(l):
|
||||||
|
"""must be a valid beta array"""
|
||||||
|
for n in l:
|
||||||
|
if not isinstance(n, (float, int)):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def field_0(f):
|
||||||
|
return isinstance(f, (str, tuple, list, np.ndarray))
|
||||||
|
|
||||||
|
|
||||||
|
def he_mode(mode):
|
||||||
|
"""must be a valide HE mode"""
|
||||||
|
if not isinstance(mode, (list, tuple)):
|
||||||
|
return False
|
||||||
|
if not len(mode) == 2:
|
||||||
|
return False
|
||||||
|
for m in mode:
|
||||||
|
if not integer(m):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def fit_parameters(param):
|
||||||
|
"""must be a valide fitting parameter tuple of the mercatili_adjusted model"""
|
||||||
|
if not isinstance(param, (list, tuple)):
|
||||||
|
return False
|
||||||
|
if not len(param) == 2:
|
||||||
|
return False
|
||||||
|
for n in param:
|
||||||
|
if not integer(n):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def string(l):
|
||||||
|
def _string(s):
|
||||||
|
return isinstance(s, str) and s.lower() in l
|
||||||
|
|
||||||
|
_string.__doc__ = f"must be a str matching one of {l}"
|
||||||
|
return _string
|
||||||
|
|
||||||
|
|
||||||
|
def capillary_resonance_strengths(l):
|
||||||
|
"""must be a list of non-zero, real number"""
|
||||||
|
if not isinstance(l, (list, tuple)):
|
||||||
|
return False
|
||||||
|
for m in l:
|
||||||
|
if not num(m):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def capillary_nested(n):
|
||||||
|
"""must be a non negative integer"""
|
||||||
|
return isinstance(n, int) and n >= 0
|
||||||
|
|
||||||
|
|
||||||
|
# def find_parent(param):
|
||||||
|
# """find the parent dictionary name of param"""
|
||||||
|
# for k, v in valid_param_types.items():
|
||||||
|
# if param in v:
|
||||||
|
# return k
|
||||||
|
# raise ValueError(f"'{param}' is an invalid parameter name")
|
||||||
|
|
||||||
|
|
||||||
|
valid_param_types = dict(
|
||||||
|
root=dict(
|
||||||
|
name=lambda s: isinstance(s, str),
|
||||||
|
),
|
||||||
|
fiber=dict(
|
||||||
|
gamma=num,
|
||||||
|
pitch=num,
|
||||||
|
pitch_ratio=num,
|
||||||
|
core_radius=num,
|
||||||
|
he_mode=he_mode,
|
||||||
|
fit_parameters=fit_parameters,
|
||||||
|
beta=beta,
|
||||||
|
model=string(["pcf", "marcatili", "marcatili_adjusted", "hasan"]),
|
||||||
|
length=num,
|
||||||
|
capillary_num=integer,
|
||||||
|
capillary_outer_d=num,
|
||||||
|
capillary_thickness=num,
|
||||||
|
capillary_spacing=num,
|
||||||
|
capillary_resonance_strengths=capillary_resonance_strengths,
|
||||||
|
capillary_nested=capillary_nested,
|
||||||
|
),
|
||||||
|
gas=dict(
|
||||||
|
gas_name=string(["vacuum", "helium", "air"]),
|
||||||
|
pressure=num,
|
||||||
|
temperature=num,
|
||||||
|
plasma_density=num,
|
||||||
|
),
|
||||||
|
pulse=dict(
|
||||||
|
field_0=field_0,
|
||||||
|
power=num,
|
||||||
|
energy=num,
|
||||||
|
soliton_num=num,
|
||||||
|
quantum_noise=boolean,
|
||||||
|
shape=string(["gaussian", "sech"]),
|
||||||
|
wavelength=num,
|
||||||
|
intensity_noise=num,
|
||||||
|
width=num,
|
||||||
|
t0=num,
|
||||||
|
),
|
||||||
|
simulation=dict(
|
||||||
|
behaviors=behaviors,
|
||||||
|
parallel=integer,
|
||||||
|
raman_type=string(["measured", "agrawal", "stolen"]),
|
||||||
|
ideal_gas=boolean,
|
||||||
|
repeat=integer,
|
||||||
|
t_num=integer,
|
||||||
|
z_num=integer,
|
||||||
|
time_window=num,
|
||||||
|
dt=num,
|
||||||
|
tolerated_error=num,
|
||||||
|
step_size=num,
|
||||||
|
lower_wavelength_interp_limit=num,
|
||||||
|
upper_wavelength_interp_limit=num,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
hc_model_specific_parameters = dict(
|
||||||
|
marcatili=["core_radius", "he_mode"],
|
||||||
|
marcatili_adjusted=["core_radius", "he_mode", "fit_parameters"],
|
||||||
|
hasan=[
|
||||||
|
"core_radius",
|
||||||
|
"capillary_num",
|
||||||
|
"capillary_thickness",
|
||||||
|
"capillary_resonance_strengths",
|
||||||
|
"capillary_nested",
|
||||||
|
"capillary_spacing",
|
||||||
|
"capillary_outer_d",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
"""dependecy map only includes actual fiber parameters and exclude gas parameters"""
|
||||||
|
|
||||||
|
valid_varying = dict(
|
||||||
|
fiber=[
|
||||||
|
"beta",
|
||||||
|
"gamma",
|
||||||
|
"pitch",
|
||||||
|
"pitch_ratio",
|
||||||
|
"core_radius",
|
||||||
|
"capillary_num",
|
||||||
|
"capillary_outer_d",
|
||||||
|
"capillary_thickness",
|
||||||
|
"capillary_spacing",
|
||||||
|
"capillary_resonance_strengths",
|
||||||
|
"capillary_nested",
|
||||||
|
"he_mode",
|
||||||
|
"fit_parameters",
|
||||||
|
],
|
||||||
|
gas=["pressure", "temperature", "gas_name", "plasma_density"],
|
||||||
|
pulse=[
|
||||||
|
"power",
|
||||||
|
"quantum_noise",
|
||||||
|
"shape",
|
||||||
|
"wavelength",
|
||||||
|
"intensity_noise",
|
||||||
|
"width",
|
||||||
|
"soliton_num",
|
||||||
|
],
|
||||||
|
simulation=["behaviors", "raman_type", "tolerated_error", "step_size", "ideal_gas"],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
TMP_FOLDER_KEY_BASE = "SCGENERATOR_TMP"
|
||||||
10
src/scgenerator/data/README.md
Normal file
10
src/scgenerator/data/README.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# source of the Sellmeir coefficients
|
||||||
|
Air, Nitrogen, Helium, Neon, Argon, Krypton, Xenon : A. Börzsönyi et al. "Dispersion measurement of inert gases and gas mixtures at 800 nm" (2008)
|
||||||
|
Silica : I. H. Malitson. Interspecimen comparison of the refractive index of fused silica (1965)
|
||||||
|
|
||||||
|
In sellmeierRefractiveIndex : see refractiveindex.info
|
||||||
|
|
||||||
|
Van der Waals constants from https://en.wikipedia.org/wiki/Van_der_Waals_constants_(data_page)
|
||||||
|
|
||||||
|
Chi3 : Wahlstrand 2012
|
||||||
|
|
||||||
29
src/scgenerator/data/RamanTrace.dtf
Normal file
29
src/scgenerator/data/RamanTrace.dtf
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
DTf.
|
||||||
|
file /Users/benoitsierro/Desktop/Capture d’écran 2019-09-12 à 13.38.10.png
|
||||||
|
mainx 0
|
||||||
|
mainy 0
|
||||||
|
window 0 23 1920 1177
|
||||||
|
axis 00 lin X - lin Y
|
||||||
|
state 1
|
||||||
|
continuous 1
|
||||||
|
tools 1
|
||||||
|
a4mode 0
|
||||||
|
distance 0.01
|
||||||
|
mode 4
|
||||||
|
precision 4
|
||||||
|
texts \z , , , \z
|
||||||
|
colors -8388608 -16777024 -13598720 -8372032 -16724992 -3407872 -16777012 -16777216 -16777216 -16777216 -1 -16777216
|
||||||
|
params 7 1 1 2 3 1 4
|
||||||
|
dump show 1028.0 185.0
|
||||||
|
point 109.5 1241.0 124.35055146851568 1235.0450758962884 124.35055146851568 1235.0450758962884 2 0 -16724992
|
||||||
|
point 3101.0 1234.0 3101.000000000001 1234.0 3101.000000000001 1234.0 0 0 -3407872
|
||||||
|
point 955.0 321.5 955.0000000000001 321.5 955.0000000000001 321.5 0 0 -16777012
|
||||||
|
point 109.25 1241.25 109.25000000000003 1241.25 109.25000000000003 1241.25 0 1 -8388608
|
||||||
|
point 3100.75 1242.75 3100.750000000001 1242.75 3100.750000000001 1242.75 0 1 -16777024
|
||||||
|
point 108.75 216.0 108.75000000000003 216.0 108.75000000000003 216.0 0 1 -13598720
|
||||||
|
point 260.0 160.0 260.0 160.0 260.0 160.0 0 1 -8372032
|
||||||
|
point 1174.25 265.25 1185.25 246.5 1176.25 258.25 6 3
|
||||||
|
point 1208.5 192.25 1219.5 220.75 1112.5 192.0 6 3
|
||||||
|
refs 0 0 40 0 0 6 0 0
|
||||||
|
xtrans none
|
||||||
|
ytrans none
|
||||||
2998
src/scgenerator/data/Raman_gain.csv
Normal file
2998
src/scgenerator/data/Raman_gain.csv
Normal file
File diff suppressed because it is too large
Load Diff
21
src/scgenerator/data/default_params.json
Normal file
21
src/scgenerator/data/default_params.json
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"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
|
||||||
|
}
|
||||||
198
src/scgenerator/data/gas.json
Normal file
198
src/scgenerator/data/gas.json
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
{
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
183
src/scgenerator/data/gas.toml
Normal file
183
src/scgenerator/data/gas.toml
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
[nitrogen]
|
||||||
|
a = 0.137
|
||||||
|
b = 1.709e-5
|
||||||
|
|
||||||
|
[helium]
|
||||||
|
a = 0.00346
|
||||||
|
b = 2.38e-5
|
||||||
|
|
||||||
|
[helium_alt]
|
||||||
|
a = 0.00346
|
||||||
|
b = 2.38e-5
|
||||||
|
|
||||||
|
[hydrogen]
|
||||||
|
a = 0.02453
|
||||||
|
b = 2.651e-5
|
||||||
|
|
||||||
|
[neon]
|
||||||
|
a = 0.02135
|
||||||
|
b = 1.709e-5
|
||||||
|
|
||||||
|
[argon]
|
||||||
|
a = 0.1355
|
||||||
|
b = 3.201e-5
|
||||||
|
|
||||||
|
[argon_alt]
|
||||||
|
a = 0.1355
|
||||||
|
b = 3.201e-5
|
||||||
|
|
||||||
|
[argon_alt2]
|
||||||
|
a = 0.1355
|
||||||
|
b = 3.201e-5
|
||||||
|
|
||||||
|
[krypton]
|
||||||
|
a = 0.2349
|
||||||
|
b = 3.978e-5
|
||||||
|
|
||||||
|
[xenon]
|
||||||
|
a = 0.425
|
||||||
|
b = 5.105e-5
|
||||||
|
|
||||||
|
[air.sellmeier]
|
||||||
|
B = [57921050000.0, 1679170000.0]
|
||||||
|
C = [238018500000000.0, 57362000000000.0]
|
||||||
|
P0 = 101325
|
||||||
|
T0 = 288.15
|
||||||
|
kind = 2
|
||||||
|
|
||||||
|
[nitrogen.sellmeier]
|
||||||
|
B = [32431570000.0]
|
||||||
|
C = [144000000000000.0]
|
||||||
|
P0 = 101325
|
||||||
|
T0 = 273.15
|
||||||
|
const = 6.8552e-5
|
||||||
|
kind = 2
|
||||||
|
|
||||||
|
[nitrogen.kerr]
|
||||||
|
P0 = 30400.0
|
||||||
|
T0 = 273.15
|
||||||
|
n2 = 2.2e-23
|
||||||
|
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."
|
||||||
|
|
||||||
|
[helium.sellmeier]
|
||||||
|
B = [2.16463842e-5, 2.10561127e-7, 4.7509272e-5]
|
||||||
|
C = [-6.80769781e-16, 5.13251289e-15, 3.18621354e-15]
|
||||||
|
P0 = 101325
|
||||||
|
T0 = 273.15
|
||||||
|
kind = 1
|
||||||
|
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)"
|
||||||
|
|
||||||
|
[helium.kerr]
|
||||||
|
P0 = 30400.0
|
||||||
|
T0 = 273.15
|
||||||
|
n2 = 3.1e-25
|
||||||
|
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."
|
||||||
|
|
||||||
|
[helium_alt.sellmeier]
|
||||||
|
B = [14755297000.0]
|
||||||
|
C = [426297400000000.0]
|
||||||
|
P0 = 101325
|
||||||
|
T0 = 273.15
|
||||||
|
kind = 2
|
||||||
|
source = " C. Cuthbertson and M. Cuthbertson. The refraction and dispersion of neon and helium. Proc. R. Soc. London A 135, 40-47 (1936)"
|
||||||
|
|
||||||
|
[helium_alt.kerr]
|
||||||
|
P0 = 30400.0
|
||||||
|
T0 = 273.15
|
||||||
|
n2 = 3.1e-25
|
||||||
|
|
||||||
|
[hydrogen.sellmeier]
|
||||||
|
B = [0.0148956, 0.0049037]
|
||||||
|
C = [1.807e-10, 9.2e-11]
|
||||||
|
P0 = 101325
|
||||||
|
T0 = 273.15
|
||||||
|
kind = 2
|
||||||
|
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)"
|
||||||
|
|
||||||
|
[hydrogen.kerr]
|
||||||
|
P0 = 30400.0
|
||||||
|
T0 = 273.15
|
||||||
|
n2 = 6.36e-24
|
||||||
|
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"
|
||||||
|
|
||||||
|
[neon.sellmeier]
|
||||||
|
B = [1281450000.0, 22048600000.0]
|
||||||
|
C = [184661000000000.0, 376840000000000.0]
|
||||||
|
P0 = 101325
|
||||||
|
T0 = 273.15
|
||||||
|
kind = 2
|
||||||
|
|
||||||
|
[neon.kerr]
|
||||||
|
P0 = 30400.0
|
||||||
|
T0 = 273.15
|
||||||
|
n2 = 8.7e-25
|
||||||
|
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."
|
||||||
|
|
||||||
|
[argon.sellmeier]
|
||||||
|
B = [2501410000.0, 500283000.0, 52234300000.0]
|
||||||
|
C = [91012000000000.0, 87892000000000.0, 214020000000000.0]
|
||||||
|
P0 = 101325
|
||||||
|
T0 = 273.15
|
||||||
|
kind = 2
|
||||||
|
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)"
|
||||||
|
|
||||||
|
[argon.kerr]
|
||||||
|
P0 = 30400.0
|
||||||
|
T0 = 273.15
|
||||||
|
n2 = 9.7e-24
|
||||||
|
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."
|
||||||
|
|
||||||
|
[argon_alt.sellmeier]
|
||||||
|
B = [0.0002033229, 0.0003445831]
|
||||||
|
C = [2.0612e-16, 8.066e-15]
|
||||||
|
P0 = 101325
|
||||||
|
T0 = 273.15
|
||||||
|
kind = 1
|
||||||
|
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)"
|
||||||
|
|
||||||
|
[argon_alt.kerr]
|
||||||
|
P0 = 30400.0
|
||||||
|
T0 = 273.15
|
||||||
|
n2 = 9.7e-24
|
||||||
|
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."
|
||||||
|
|
||||||
|
[argon_alt2.sellmeier]
|
||||||
|
B = [0.030182943]
|
||||||
|
C = [144000000000000.0]
|
||||||
|
P0 = 101325
|
||||||
|
T0 = 273.15
|
||||||
|
const = 6.7867e-5
|
||||||
|
kind = 2
|
||||||
|
source = "E. R. Peck and D. J. Fisher. Dispersion of argon, J. Opt. Soc. Am. 54, 1362-1364 (1964)"
|
||||||
|
|
||||||
|
[argon_alt2.kerr]
|
||||||
|
P0 = 30400.0
|
||||||
|
T0 = 273.15
|
||||||
|
n2 = 9.7e-24
|
||||||
|
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."
|
||||||
|
|
||||||
|
[krypton.sellmeier]
|
||||||
|
B = [2536370000.0, 2736490000.0, 62080200000.0]
|
||||||
|
C = [65474200000000.0, 73698000000000.0, 181080000000000.0]
|
||||||
|
P0 = 101325
|
||||||
|
T0 = 273.15
|
||||||
|
kind = 2
|
||||||
|
|
||||||
|
[krypton.kerr]
|
||||||
|
P0 = 30400.0
|
||||||
|
T0 = 273.15
|
||||||
|
n2 = 2.2e-23
|
||||||
|
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."
|
||||||
|
|
||||||
|
[xenon.sellmeier]
|
||||||
|
B = [3228690000.0, 3553930000.0, 60676400000.0]
|
||||||
|
C = [46301000000000.0, 59578000000000.0, 112740000000000.0]
|
||||||
|
P0 = 101325
|
||||||
|
T0 = 273.15
|
||||||
|
kind = 2
|
||||||
|
|
||||||
|
[xenon.kerr]
|
||||||
|
P0 = 30400.0
|
||||||
|
T0 = 273.15
|
||||||
|
n2 = 5.8e-23
|
||||||
|
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."
|
||||||
BIN
src/scgenerator/data/hr_t.npz
Normal file
BIN
src/scgenerator/data/hr_t.npz
Normal file
Binary file not shown.
69
src/scgenerator/data/sellmeierRefractiveIndex.json
Normal file
69
src/scgenerator/data/sellmeierRefractiveIndex.json
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
{
|
||||||
|
"silica" : {
|
||||||
|
"B" : [0.696166300, 0.407942600, 0.897479400],
|
||||||
|
"C" : [4.67914826e-15, 1.35120631e-14, 97.9340025e-12],
|
||||||
|
"kind": 1
|
||||||
|
},
|
||||||
|
"air" : {
|
||||||
|
"B" : [0.05792105e12, 0.00167917e12],
|
||||||
|
"C" : [238.0185e12, 57.362e12],
|
||||||
|
"kind": 2,
|
||||||
|
"P0": 101325,
|
||||||
|
"T0": 288.15
|
||||||
|
},
|
||||||
|
"nitrogen" : {
|
||||||
|
"B" : [3.243157e10],
|
||||||
|
"C" : [144e12],
|
||||||
|
"a" : 0.137,
|
||||||
|
"b" : 0.01709e-3,
|
||||||
|
"const": 6.8552e-5,
|
||||||
|
"kind": 2,
|
||||||
|
"P0": 101325,
|
||||||
|
"T0": 273.15
|
||||||
|
},
|
||||||
|
"helium" : {
|
||||||
|
"B" : [0.014755297e12],
|
||||||
|
"C" : [426.2974e12],
|
||||||
|
"a" : 0.00346,
|
||||||
|
"b" : 0.0238e-3,
|
||||||
|
"kind": 2,
|
||||||
|
"P0": 101325,
|
||||||
|
"T0": 273.15
|
||||||
|
},
|
||||||
|
"neon" : {
|
||||||
|
"B" : [0.00128145e12, 0.0220486e12],
|
||||||
|
"C" : [184.661e12, 376.84e12],
|
||||||
|
"a" : 0.02135,
|
||||||
|
"b" : 0.01709e-3,
|
||||||
|
"kind": 2,
|
||||||
|
"P0": 101325,
|
||||||
|
"T0": 273.15
|
||||||
|
},
|
||||||
|
"argon" : {
|
||||||
|
"B" : [2.50141e9, 5.00283e8, 5.22343e10],
|
||||||
|
"C" : [91.012e12, 87.892e12, 214.02e12],
|
||||||
|
"a" : 0.1355,
|
||||||
|
"b" : 0.03201e-3,
|
||||||
|
"kind": 2,
|
||||||
|
"P0": 101325,
|
||||||
|
"T0": 273.15
|
||||||
|
},
|
||||||
|
"krypton" : {
|
||||||
|
"B" : [0.00253637e12, 0.00273649e12, 0.0620802e12],
|
||||||
|
"C" : [65.4742e12, 73.698e12, 181.08e12],
|
||||||
|
"a" : 0.2349,
|
||||||
|
"b" : 0.03978e-3,
|
||||||
|
"kind": 2,
|
||||||
|
"P0": 101325,
|
||||||
|
"T0": 273.15
|
||||||
|
},
|
||||||
|
"xenon" : {
|
||||||
|
"B" : [0.00322869e12, 0.00355393e12, 0.0606764e12],
|
||||||
|
"C" : [46.301e12, 59.578e12, 112.74e12],
|
||||||
|
"a" : 0.425,
|
||||||
|
"b" : 0.05105e-3,
|
||||||
|
"kind": 2,
|
||||||
|
"P0": 101325,
|
||||||
|
"T0": 273.15
|
||||||
|
}
|
||||||
|
}
|
||||||
34
src/scgenerator/data/sellmeier_Börzsönyi.json
Normal file
34
src/scgenerator/data/sellmeier_Börzsönyi.json
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"silica" : {
|
||||||
|
"B" : [0.696166300, 0.407942600, 0.897479400],
|
||||||
|
"C" : [4.67914826e-15, 1.35120631e-14, 97.9340025e-12]
|
||||||
|
},
|
||||||
|
"air" : {
|
||||||
|
"B" : [14926.44e-8, 41807.57e-8],
|
||||||
|
"C" : [19.36e-18, 7.434e-15]
|
||||||
|
},
|
||||||
|
"nitrogen" : {
|
||||||
|
"B" : [39209.95e-8, 18806.48e-8],
|
||||||
|
"C" : [1146.24e-18, 13.476e-15]
|
||||||
|
},
|
||||||
|
"helium" : {
|
||||||
|
"B" : [4977.77e-8, 1856.94e-8],
|
||||||
|
"C" : [28.54e-18, 7.760e-15]
|
||||||
|
},
|
||||||
|
"neon" : {
|
||||||
|
"B" : [9154.48e-8, 4018.63e-8],
|
||||||
|
"C" : [656.97e-18, 5.728e-15]
|
||||||
|
},
|
||||||
|
"argon" : {
|
||||||
|
"B" : [20332.29e-8, 34458.31e-8],
|
||||||
|
"C" : [206.12e-18, 8.066e-15]
|
||||||
|
},
|
||||||
|
"krypton" : {
|
||||||
|
"B" : [26102.88e-8, 56946.82e-8],
|
||||||
|
"C" : [2.01e-18, 10.043e-15]
|
||||||
|
},
|
||||||
|
"xenon" : {
|
||||||
|
"B" : [103701.61e-8, 31228.61e-8],
|
||||||
|
"C" : [12.75e-15, 0.561e-15]
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/scgenerator/data/silica.json
Normal file
8
src/scgenerator/data/silica.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"sellmeier": {
|
||||||
|
"B": [0.6961663, 0.4079426, 0.8974794],
|
||||||
|
"C": [4.67914826e-15, 1.35120631e-14, 9.79340025e-11],
|
||||||
|
"kind": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
4
src/scgenerator/data/silica.toml
Normal file
4
src/scgenerator/data/silica.toml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[sellmeier]
|
||||||
|
B = [ 0.6961663, 0.4079426, 0.8974794,]
|
||||||
|
C = [ 4.67914826e-15, 1.35120631e-14, 9.79340025e-11,]
|
||||||
|
kind = 1
|
||||||
102
src/scgenerator/defaults.py
Normal file
102
src/scgenerator/defaults.py
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from .errors import MissingParameterError
|
||||||
|
|
||||||
|
default_parameters = dict(
|
||||||
|
name="no name",
|
||||||
|
he_mode=(1, 1),
|
||||||
|
fit_parameters=(0.08, 200e-9),
|
||||||
|
model="pcf",
|
||||||
|
length=1,
|
||||||
|
capillary_resonance_strengths=[],
|
||||||
|
capillary_nested=0,
|
||||||
|
gas_name="vacuum",
|
||||||
|
plasma_density=0,
|
||||||
|
pressure=1e5,
|
||||||
|
temperature=300,
|
||||||
|
quantum_noise=False,
|
||||||
|
intensity_noise=0,
|
||||||
|
shape="gaussian",
|
||||||
|
frep=80e6,
|
||||||
|
behaviors=["spm", "ss"],
|
||||||
|
raman_type="agrawal",
|
||||||
|
parallel=1,
|
||||||
|
repeat=1,
|
||||||
|
tolerated_error=1e-11,
|
||||||
|
lower_wavelength_interp_limit=0,
|
||||||
|
upper_wavelength_interp_limit=1900e-9,
|
||||||
|
ideal_gas=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get(section_dict, param, **kwargs):
|
||||||
|
"""checks if param is in the parameter section dict and attempts to fill in a default value
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
section_dict : dict
|
||||||
|
the parameters section {fiber, pulse, simulation, root} sub-dictionary
|
||||||
|
param : str
|
||||||
|
the name of the parameter (dict key)
|
||||||
|
kwargs : any
|
||||||
|
key word arguments passed to the MissingParameterError constructor
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
dict
|
||||||
|
the updated section_dict dictionary
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
MissingFiberParameterError
|
||||||
|
raised when a parameter is missing and no default exists
|
||||||
|
"""
|
||||||
|
|
||||||
|
# whether the parameter is in the right place and valid is checked elsewhere,
|
||||||
|
# here, we just make sure it is present.
|
||||||
|
if param not in section_dict and param not in section_dict.get("varying", {}):
|
||||||
|
try:
|
||||||
|
section_dict[param] = default_parameters[param]
|
||||||
|
# LOG
|
||||||
|
except KeyError:
|
||||||
|
raise MissingParameterError(param, **kwargs)
|
||||||
|
return section_dict
|
||||||
|
|
||||||
|
|
||||||
|
def get_fiber(section_dict, param, **kwargs):
|
||||||
|
"""wrapper for fiber parameters that depend on fiber model"""
|
||||||
|
return get(section_dict, param, fiber_model=section_dict["model"], **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def get_multiple(section_dict, params, num, **kwargs):
|
||||||
|
"""similar to th get method but works with several parameters
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
section_dict : dict
|
||||||
|
the parameters section {fiber, pulse, simulation, root}, sub-dictionary
|
||||||
|
params : list of str
|
||||||
|
names of the required parameters
|
||||||
|
num : int
|
||||||
|
how many of the parameters in params are required
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
dict
|
||||||
|
the updated section_dict
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
MissingParameterError
|
||||||
|
raised when not enough parameters are provided and no defaults exist
|
||||||
|
"""
|
||||||
|
gotten = 0
|
||||||
|
for param in params:
|
||||||
|
try:
|
||||||
|
section_dict = get(section_dict, param, **kwargs)
|
||||||
|
gotten += 1
|
||||||
|
except MissingParameterError:
|
||||||
|
pass
|
||||||
|
if gotten >= num:
|
||||||
|
return section_dict
|
||||||
|
raise MissingParameterError(params, num_required=num, **kwargs)
|
||||||
51
src/scgenerator/errors.py
Normal file
51
src/scgenerator/errors.py
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
class MissingParameterError(Exception):
|
||||||
|
def __init__(self, param, **kwargs):
|
||||||
|
self.param = param
|
||||||
|
|
||||||
|
# initial message
|
||||||
|
message = ""
|
||||||
|
if isinstance(param, str):
|
||||||
|
message += f"'{self.param}' is a required parameter "
|
||||||
|
elif isinstance(param, (tuple, list)):
|
||||||
|
num = kwargs["num_required"]
|
||||||
|
message += f"{num} of '{self.param}' {'is' if num == 1 else 'are'} required "
|
||||||
|
else:
|
||||||
|
raise TypeError(f"don't know what to do with param as {param}")
|
||||||
|
|
||||||
|
# complementary information
|
||||||
|
if "fiber_model" in kwargs:
|
||||||
|
message += f"for fiber model '{kwargs['fiber_model']}' "
|
||||||
|
if "specified_parameters" in kwargs:
|
||||||
|
if len(kwargs["specified_parameters"]) == 0:
|
||||||
|
pass
|
||||||
|
elif len(kwargs["specified_parameters"]) == 1:
|
||||||
|
message += f"when '{kwargs['specified_parameters'][0]}' is specified "
|
||||||
|
else:
|
||||||
|
message += f"when {kwargs['specified_parameters']} are specified "
|
||||||
|
|
||||||
|
# closing statement
|
||||||
|
message += "and no defaults have been set"
|
||||||
|
super().__init__(message)
|
||||||
|
|
||||||
|
|
||||||
|
class DuplicateParameterError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class IncompleteDataFolderError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# class MissingFiberParameterError(MissingParameterError):
|
||||||
|
# def __init__(self, param, model):
|
||||||
|
# self.param = param
|
||||||
|
# self.model = model
|
||||||
|
# super().__init__(
|
||||||
|
# f"'{self.param}' is a required parameter for fiber model '{self.model}' and no default value is set"
|
||||||
|
# )
|
||||||
|
|
||||||
|
|
||||||
|
# class MissingPulseParameterError(MissingParameterError):
|
||||||
|
# def __init__(self, param):
|
||||||
|
# self.param = param
|
||||||
|
# super().__init__(f"'{self.param}' is a required pulse parameter and no default value is set")
|
||||||
775
src/scgenerator/initialize.py
Normal file
775
src/scgenerator/initialize.py
Normal file
@@ -0,0 +1,775 @@
|
|||||||
|
from os import path
|
||||||
|
from typing import Iterator, Mapping, Tuple
|
||||||
|
import numpy as np
|
||||||
|
from numpy import pi
|
||||||
|
from numpy.core.fromnumeric import var
|
||||||
|
from ray.state import current_node_id
|
||||||
|
|
||||||
|
from . import io, state, defaults
|
||||||
|
from .math import length, power_fact
|
||||||
|
from .physics import fiber, pulse, units
|
||||||
|
from .const import valid_param_types, valid_varying, hc_model_specific_parameters
|
||||||
|
from .errors import *
|
||||||
|
from .io import get_logger
|
||||||
|
from .utilities import varying_iterator, count_variations
|
||||||
|
|
||||||
|
|
||||||
|
class ParamSequence(Mapping):
|
||||||
|
def __init__(self, config):
|
||||||
|
validate_types(config)
|
||||||
|
self.config = ensure_consistency(config)
|
||||||
|
self.name = self.config["name"]
|
||||||
|
|
||||||
|
self.num_sim, self.num_varying = count_variations(self.config)
|
||||||
|
self.single_sim = self.num_sim == 1
|
||||||
|
|
||||||
|
def get_pulse(self, key):
|
||||||
|
return self.config["pulse"][key]
|
||||||
|
|
||||||
|
def get_fiber(self, key):
|
||||||
|
return self.config["fiber"][key]
|
||||||
|
|
||||||
|
def get_simulation(self, key):
|
||||||
|
return self.config["pulse"][key]
|
||||||
|
|
||||||
|
def __iter__(self) -> Iterator[Tuple[list, dict]]:
|
||||||
|
"""iterates through all possible parameters, yielding a config as welle as a flattened
|
||||||
|
computed parameters set each time"""
|
||||||
|
for only_varying, full_config in varying_iterator(self.config):
|
||||||
|
yield only_varying, compute_init_parameters(full_config)
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return self.num_sim
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
return self.config[key[0]][key[1]]
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return f"dispatcher generated from config {self.name}"
|
||||||
|
|
||||||
|
|
||||||
|
def wspace(t, t_num=0):
|
||||||
|
"""frequency array such that x(t) <-> np.fft(x)(w)
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
t : float or array
|
||||||
|
float : total width of the time window
|
||||||
|
array : time array
|
||||||
|
t_num : int-
|
||||||
|
if t is a float, specifies the number of points
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
w : array
|
||||||
|
linspace of frencies corresponding to t
|
||||||
|
"""
|
||||||
|
if isinstance(t, (np.ndarray, list, tuple)):
|
||||||
|
dt = t[1] - t[0]
|
||||||
|
t_num = len(t)
|
||||||
|
t = t[-1] - t[0] + dt
|
||||||
|
else:
|
||||||
|
dt = t / t_num
|
||||||
|
w = 2 * pi * np.arange(t_num) / t
|
||||||
|
w = np.where(w >= pi / dt, w - 2 * pi / dt, w)
|
||||||
|
return w
|
||||||
|
|
||||||
|
|
||||||
|
def tspace(time_window=None, t_num=None, dt=None):
|
||||||
|
"""returns a time array centered on 0
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
time_window : float
|
||||||
|
total time spanned
|
||||||
|
t_num : int
|
||||||
|
number of points
|
||||||
|
dt : float
|
||||||
|
time resolution
|
||||||
|
|
||||||
|
at least 2 arguments must be given. They are prioritize as such
|
||||||
|
t_num > time_window > dt
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
t : array
|
||||||
|
a linearily spaced time array
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
TypeError
|
||||||
|
missing at least 1 argument
|
||||||
|
"""
|
||||||
|
if t_num is not None:
|
||||||
|
if isinstance(time_window, (float, int)):
|
||||||
|
return np.linspace(-time_window / 2, time_window / 2, int(t_num))
|
||||||
|
elif isinstance(dt, (float, int)):
|
||||||
|
time_window = (t_num - 1) * dt
|
||||||
|
return np.linspace(-time_window / 2, time_window / 2, t_num)
|
||||||
|
elif isinstance(time_window, (float, int)) and isinstance(dt, (float, int)):
|
||||||
|
t_num = int(time_window / dt) + 1
|
||||||
|
return np.linspace(-time_window / 2, time_window / 2, t_num)
|
||||||
|
else:
|
||||||
|
raise TypeError("not enough parameter to determine time vector")
|
||||||
|
|
||||||
|
|
||||||
|
def validate_single_parameter(parent, key, value):
|
||||||
|
try:
|
||||||
|
func = valid_param_types[parent][key]
|
||||||
|
except KeyError:
|
||||||
|
s = f"The parameter '{key}' does not belong "
|
||||||
|
if parent == "root":
|
||||||
|
s += "at the root of the config file"
|
||||||
|
else:
|
||||||
|
s += f"in the category '{parent}'"
|
||||||
|
s += ". Make sure it is a valid parameter in the first place"
|
||||||
|
raise TypeError(s)
|
||||||
|
if not func(value):
|
||||||
|
raise TypeError(
|
||||||
|
f"value '{value}' of type {type(value)} for key '{key}' is not valid, {func.__doc__}"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def validate_types(config):
|
||||||
|
"""validates the data types in the initial config dictionary
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
config : dict
|
||||||
|
the initial config dictionary
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
TypeError
|
||||||
|
raised when a parameter has the wrong type
|
||||||
|
"""
|
||||||
|
|
||||||
|
for domain, parameters in config.items():
|
||||||
|
if isinstance(parameters, dict):
|
||||||
|
for param_name, param_value in parameters.items():
|
||||||
|
if param_name == "varying":
|
||||||
|
for k_vary, v_vary in param_value.items():
|
||||||
|
if not isinstance(v_vary, list):
|
||||||
|
raise TypeError(f"Varying parameters should be specified in a list")
|
||||||
|
|
||||||
|
if len(v_vary) < 1:
|
||||||
|
raise ValueError(
|
||||||
|
f"Varying parameters lists should contain at least 1 element"
|
||||||
|
)
|
||||||
|
|
||||||
|
if k_vary not in valid_varying[domain]:
|
||||||
|
raise TypeError(f"'{k_vary}' is not a valid variable parameter")
|
||||||
|
|
||||||
|
[
|
||||||
|
validate_single_parameter(domain, k_vary, v_vary_indiv)
|
||||||
|
for v_vary_indiv in v_vary
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
validate_single_parameter(domain, param_name, param_value)
|
||||||
|
else:
|
||||||
|
validate_single_parameter("root", domain, parameters)
|
||||||
|
|
||||||
|
|
||||||
|
def _contains(sub_conf, param):
|
||||||
|
return param in sub_conf or param in sub_conf.get("varying", {})
|
||||||
|
|
||||||
|
|
||||||
|
def _ensure_consistency_fiber(fiber):
|
||||||
|
"""ensure the fiber sub-dictionary of the parameter set is consistent
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
fiber : dict
|
||||||
|
dictionary containing the fiber parameters
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
dict
|
||||||
|
the updated dictionary
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
MissingParameterError
|
||||||
|
When at least one required parameter with no default is missing
|
||||||
|
"""
|
||||||
|
|
||||||
|
if _contains(fiber, "beta"):
|
||||||
|
fiber = defaults.get(fiber, "gamma", specified_parameters=["beta"])
|
||||||
|
fiber["model"] = fiber.get("model", "custom")
|
||||||
|
|
||||||
|
else:
|
||||||
|
fiber = defaults.get(fiber, "model")
|
||||||
|
|
||||||
|
if fiber["model"] == "pcf":
|
||||||
|
fiber = defaults.get_fiber(fiber, "pitch")
|
||||||
|
fiber = defaults.get_fiber(fiber, "pitch_ratio")
|
||||||
|
|
||||||
|
elif fiber["model"] == "hasan":
|
||||||
|
fiber = defaults.get_multiple(
|
||||||
|
fiber, ["capillary_spacing", "capillary_outer_d"], 1, fiber_model="hasan"
|
||||||
|
)
|
||||||
|
for param in [
|
||||||
|
"core_radius",
|
||||||
|
"capillary_num",
|
||||||
|
"capillary_thickness",
|
||||||
|
"capillary_resonance_strengths",
|
||||||
|
"capillary_nested",
|
||||||
|
]:
|
||||||
|
fiber = defaults.get_fiber(fiber, param)
|
||||||
|
else:
|
||||||
|
for param in hc_model_specific_parameters[fiber["model"]]:
|
||||||
|
fiber = defaults.get_fiber(fiber, param)
|
||||||
|
|
||||||
|
fiber = defaults.get(fiber, "length")
|
||||||
|
return fiber
|
||||||
|
|
||||||
|
|
||||||
|
def _ensure_consistency_gas(gas):
|
||||||
|
"""ensure the gas sub-dictionary of the parameter set is consistent
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
gas : dict
|
||||||
|
dictionary containing the gas parameters
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
dict
|
||||||
|
the updated dictionary
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
MissingParameterError
|
||||||
|
When at least one required parameter with no default is missing
|
||||||
|
"""
|
||||||
|
for param in ["gas_name", "temperature", "pressure", "plasma_density"]:
|
||||||
|
gas = defaults.get(gas, param, specified_params=["gas"])
|
||||||
|
return gas
|
||||||
|
|
||||||
|
|
||||||
|
def _ensure_consistency_pulse(pulse):
|
||||||
|
"""ensure the pulse sub-dictionary of the parameter set is consistent
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
pulse : dict
|
||||||
|
dictionary of the pulse section of parameters
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
dict
|
||||||
|
the updated pulse dictionary
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
MissingParameterError
|
||||||
|
When at least one required parameter with no default is missing
|
||||||
|
"""
|
||||||
|
for param in ["wavelength", "shape", "quantum_noise", "intensity_noise"]:
|
||||||
|
pulse = defaults.get(pulse, param)
|
||||||
|
|
||||||
|
if _contains(pulse, "soliton_num"):
|
||||||
|
pulse = defaults.get_multiple(
|
||||||
|
pulse, ["power", "energy", "width", "t0"], 1, specified_parameters=["soliton_num"]
|
||||||
|
)
|
||||||
|
|
||||||
|
else:
|
||||||
|
pulse = defaults.get_multiple(pulse, ["t0", "width"], 1)
|
||||||
|
pulse = defaults.get_multiple(pulse, ["power", "energy"], 1)
|
||||||
|
return pulse
|
||||||
|
|
||||||
|
|
||||||
|
def _ensure_consistency_simulation(simulation):
|
||||||
|
"""ensure the simulation sub-dictionary of the parameter set is consistent
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
pulse : dict
|
||||||
|
dictionary of the pulse section of parameters
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
dict
|
||||||
|
the updated pulse dictionary
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
MissingParameterError
|
||||||
|
When at least one required parameter with no default is missing
|
||||||
|
"""
|
||||||
|
simulation = defaults.get_multiple(simulation, ["dt", "t_num", "time_window"], 2)
|
||||||
|
|
||||||
|
for param in [
|
||||||
|
"behaviors",
|
||||||
|
"z_num",
|
||||||
|
"frep",
|
||||||
|
"tolerated_error",
|
||||||
|
"parallel",
|
||||||
|
"repeat",
|
||||||
|
"lower_wavelength_interp_limit",
|
||||||
|
"upper_wavelength_interp_limit",
|
||||||
|
"ideal_gas",
|
||||||
|
]:
|
||||||
|
simulation = defaults.get(simulation, param)
|
||||||
|
|
||||||
|
if "raman" in simulation["behaviors"] or any(
|
||||||
|
["raman" in l for l in simulation.get("varying", {}).get("behaviors", [])]
|
||||||
|
):
|
||||||
|
simulation = defaults.get(simulation, "raman_type", specified_parameters=["raman"])
|
||||||
|
return simulation
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_consistency(config):
|
||||||
|
"""ensure the config dictionary is consistent and that certain parameters are set,
|
||||||
|
either by filling in defaults or by raising an error. This is not where new values are calculated.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
config : dict
|
||||||
|
original config dict loaded from the toml file
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
dict
|
||||||
|
the consistent config dict
|
||||||
|
"""
|
||||||
|
|
||||||
|
validate_types(config)
|
||||||
|
|
||||||
|
# ensure parameters are not specified multiple times
|
||||||
|
for sub_dict in valid_param_types.values():
|
||||||
|
for param_name in sub_dict:
|
||||||
|
for set_param in config.values():
|
||||||
|
if isinstance(set_param, dict):
|
||||||
|
if param_name in set_param and param_name in set_param.get("varying", {}):
|
||||||
|
raise DuplicateParameterError(
|
||||||
|
f"got multiple values for parameter '{param_name}'"
|
||||||
|
)
|
||||||
|
|
||||||
|
# ensure every required parameter has a value
|
||||||
|
config["name"] = config.get("name", "no name")
|
||||||
|
config["fiber"] = _ensure_consistency_fiber(config.get("fiber", {}))
|
||||||
|
|
||||||
|
if config["fiber"]["model"] in hc_model_specific_parameters:
|
||||||
|
config["gas"] = _ensure_consistency_gas(config.get("gas", {}))
|
||||||
|
|
||||||
|
config["pulse"] = _ensure_consistency_pulse(config.get("pulse", {}))
|
||||||
|
config["simulation"] = _ensure_consistency_simulation(config.get("simulation", {}))
|
||||||
|
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def compute_init_parameters(config):
|
||||||
|
"""computes all derived values from a config dictionary
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
config : dict
|
||||||
|
a configuration dictionary containing the pulse, fiber and simulation sections with no varying parameter.
|
||||||
|
Note : checking the validity of the configuration shall be done before calling this function.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
dict
|
||||||
|
a flattened dictionary (no fiber, pulse, simulation subsections) with all the necessary values to run RK4IP
|
||||||
|
"""
|
||||||
|
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
# copy and flatten the config
|
||||||
|
params = dict(name=config["name"])
|
||||||
|
for section in ["pulse", "fiber", "simulation", "gas"]:
|
||||||
|
for key, value in config.get(section, {}).items():
|
||||||
|
params[key] = value
|
||||||
|
|
||||||
|
params = _generate_sim_grid(params)
|
||||||
|
|
||||||
|
# FIBER
|
||||||
|
params["interp_range"] = _interp_range(
|
||||||
|
params["w"],
|
||||||
|
params["upper_wavelength_interp_limit"],
|
||||||
|
params["lower_wavelength_interp_limit"],
|
||||||
|
)
|
||||||
|
|
||||||
|
if "beta" in params:
|
||||||
|
params["beta"] = np.array(params["beta"])
|
||||||
|
temp_gamma = 0
|
||||||
|
params["dynamic_dispersion"] = False
|
||||||
|
else:
|
||||||
|
params["dynamic_dispersion"] = fiber.is_dynamic_dispersion(params)
|
||||||
|
params["beta"], temp_gamma = fiber.dispersion_central(params["model"], params)
|
||||||
|
if params["dynamic_dispersion"]:
|
||||||
|
params["gamma_func"] = temp_gamma
|
||||||
|
params["beta_func"] = params["beta"]
|
||||||
|
params["beta"] = params["beta_func"](0)
|
||||||
|
temp_gamma = temp_gamma(0)
|
||||||
|
|
||||||
|
if "gamma" not in params:
|
||||||
|
params["gamma"] = temp_gamma
|
||||||
|
logger.info(f"using computed \u0263 = {params['gamma']:.2e} W/m^2")
|
||||||
|
|
||||||
|
# Raman response
|
||||||
|
if "raman" in params["behaviors"]:
|
||||||
|
params["hr_w"] = fiber.delayed_raman_w(params["t"], params["dt"], params["raman_type"])
|
||||||
|
|
||||||
|
# PULSE
|
||||||
|
params = _update_pulse_parameters(params)
|
||||||
|
logger.info(f"computed initial N = {params['soliton_num']:.3g}")
|
||||||
|
|
||||||
|
params["L_D"] = params["t0"] ** 2 / abs(params["beta"][0])
|
||||||
|
params["L_NL"] = 1 / (params["gamma"] * params["power"]) if params["gamma"] else np.inf
|
||||||
|
params["L_sol"] = pi / 2 * params["L_D"]
|
||||||
|
|
||||||
|
# Technical noise
|
||||||
|
if "intensity_noise" in params:
|
||||||
|
params = _technical_noise(params)
|
||||||
|
|
||||||
|
# Initial field
|
||||||
|
if "field_0" in params:
|
||||||
|
params = _validate_custom_init_field(params)
|
||||||
|
else:
|
||||||
|
params["field_0"] = pulse.initial_field(
|
||||||
|
params["t"], params["shape"], params["t0"], params["power"]
|
||||||
|
)
|
||||||
|
|
||||||
|
if params["quantum_noise"]:
|
||||||
|
params["field_0"] = params["field_0"] + pulse.shot_noise(
|
||||||
|
params["w_c"], params["w0"], params["time_window"], params["dt"]
|
||||||
|
)
|
||||||
|
|
||||||
|
return params
|
||||||
|
|
||||||
|
|
||||||
|
def _update_pulse_parameters(params):
|
||||||
|
(
|
||||||
|
params["width"],
|
||||||
|
params["t0"],
|
||||||
|
params["power"],
|
||||||
|
params["energy"],
|
||||||
|
params["soliton_num"],
|
||||||
|
) = pulse.conform_pulse_params(
|
||||||
|
shape=params["shape"],
|
||||||
|
width=params.get("width", None),
|
||||||
|
t0=params.get("t0", None),
|
||||||
|
power=params.get("power", None),
|
||||||
|
energy=params.get("energy", None),
|
||||||
|
gamma=params["gamma"],
|
||||||
|
beta2=params["beta"][0],
|
||||||
|
)
|
||||||
|
return params
|
||||||
|
|
||||||
|
|
||||||
|
def _validate_custom_init_field(params):
|
||||||
|
if isinstance(params["field_0"], str):
|
||||||
|
field_0 = evaluate_field_equation(params["field_0"], **params)
|
||||||
|
params["field_0"] = field_0
|
||||||
|
elif len(params["field_0"]) != params["t_num"]:
|
||||||
|
raise ValueError(
|
||||||
|
"initial field is given but doesn't match size and type with the time array"
|
||||||
|
)
|
||||||
|
return params
|
||||||
|
|
||||||
|
|
||||||
|
def _technical_noise(params):
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
if params["intensity_noise"] > 0:
|
||||||
|
logger.info(f"intensity noise of {params['intensity_noise']}")
|
||||||
|
delta_int, delta_T0 = pulse.technical_noise(params["intensity_noise"])
|
||||||
|
params["power"] *= delta_int
|
||||||
|
params["t0"] *= delta_T0
|
||||||
|
params["width"] *= delta_T0
|
||||||
|
params = _update_pulse_parameters(params)
|
||||||
|
return params
|
||||||
|
|
||||||
|
|
||||||
|
def _interp_range(w, upper, lower):
|
||||||
|
# by default, the interpolation range of the dispersion polynomial stops exactly
|
||||||
|
# at the boundary of the frequency window we consider
|
||||||
|
|
||||||
|
interp_range = [
|
||||||
|
max(lower, units.m.inv(np.max(w[w > 0]))),
|
||||||
|
min(upper, units.m.inv(np.min(w[w > 0]))),
|
||||||
|
]
|
||||||
|
|
||||||
|
return interp_range
|
||||||
|
|
||||||
|
|
||||||
|
def _generate_sim_grid(params):
|
||||||
|
"""computes a bunch of values that relate to the simulation grid
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
params : dict
|
||||||
|
flattened parameter dictionary
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
dict
|
||||||
|
updated parameter dictionary
|
||||||
|
"""
|
||||||
|
t = tspace(
|
||||||
|
time_window=params.get("time_window", None),
|
||||||
|
t_num=params.get("t_num", None),
|
||||||
|
dt=params.get("dt", None),
|
||||||
|
)
|
||||||
|
params["t"] = t
|
||||||
|
params["time_window"] = length(t)
|
||||||
|
params["dt"] = t[1] - t[0]
|
||||||
|
params["t_num"] = len(t)
|
||||||
|
|
||||||
|
w_c = wspace(t)
|
||||||
|
w0 = units.m(params["wavelength"])
|
||||||
|
params["w0"] = w0
|
||||||
|
params["w_c"] = w_c
|
||||||
|
params["w"] = w_c + w0
|
||||||
|
params["w_power_fact"] = [power_fact(w_c, k) for k in range(2, 11)]
|
||||||
|
|
||||||
|
params["z_targets"] = np.linspace(0, params["length"], params["z_num"])
|
||||||
|
params["store_num"] = len(params["z_targets"])
|
||||||
|
|
||||||
|
return params
|
||||||
|
|
||||||
|
|
||||||
|
# def compute_init_parameters_old(dictionary):
|
||||||
|
# """
|
||||||
|
# computes the initial parameters required and sorts them in 3 categories : simulations, pulse and fiber
|
||||||
|
|
||||||
|
# Parameters
|
||||||
|
# ----------
|
||||||
|
# dictionary : dict, optional
|
||||||
|
# dictionary containing parameters for a single simulation
|
||||||
|
|
||||||
|
# Returns
|
||||||
|
# -------
|
||||||
|
# params : dict
|
||||||
|
# dictionary of parameters
|
||||||
|
|
||||||
|
# Note
|
||||||
|
# ----
|
||||||
|
|
||||||
|
# Parameter computation occurs in 3 different stages
|
||||||
|
# Simulation-specific parameters
|
||||||
|
# Fiber-specific parameters
|
||||||
|
# Initial pulse parameters
|
||||||
|
# """
|
||||||
|
|
||||||
|
# logger = state.CurrentLogger
|
||||||
|
|
||||||
|
# param_dico = dictionary.copy()
|
||||||
|
|
||||||
|
# if "name" not in param_dico:
|
||||||
|
# param_dico["name"] = "untitled_parameters"
|
||||||
|
|
||||||
|
# # convert units
|
||||||
|
# param_dico = units.standardize_dictionary(param_dico)
|
||||||
|
|
||||||
|
# #### SIMULATION SPECIFIC VALUES
|
||||||
|
|
||||||
|
# # time/frequency grid
|
||||||
|
# lambda0 = param_dico["lambda0"]
|
||||||
|
# t = tspace(
|
||||||
|
# T=param_dico.get("T", None), t_num=param_dico.get("nt", None), dt=param_dico.get("dt", None)
|
||||||
|
# ) # time grid
|
||||||
|
# w_c = wspace(t)
|
||||||
|
# w0 = units.m(lambda0)
|
||||||
|
# param_dico["T"] = length(t)
|
||||||
|
# param_dico["dt"] = t[1] - t[0]
|
||||||
|
# param_dico["nt"] = len(t)
|
||||||
|
# param_dico["w0"] = w0
|
||||||
|
# param_dico["w_c"] = w_c
|
||||||
|
# param_dico["w"] = w_c + w0
|
||||||
|
# param_dico["t"] = t
|
||||||
|
|
||||||
|
# # precompute (w - w0)^k / k!
|
||||||
|
# param_dico["w_power_fact"] = [power_fact(w_c, k) for k in range(2, 11)]
|
||||||
|
|
||||||
|
# logger.log(
|
||||||
|
# f"time window : {1e15*param_dico['T']:.1f}fs with {1e15*param_dico['dt']:.1f}fs resolution"
|
||||||
|
# )
|
||||||
|
# logger.log(
|
||||||
|
# f"wl window : {units.nm.inv(np.max(param_dico['w']))}nm to {units.nm.inv(np.min(param_dico['w'][param_dico['w'] > 0]))}nm"
|
||||||
|
# )
|
||||||
|
|
||||||
|
# # High frequencies can be a problem
|
||||||
|
# # We can ignore them with a lower_wavelength_interp_limit parameter
|
||||||
|
# if units.nm.inv(np.max(w_c + w0)) < 450 and "lower_wavelength_interp_limit" not in param_dico:
|
||||||
|
# pass
|
||||||
|
|
||||||
|
# if "lower_wavelength_interp_limit" in param_dico:
|
||||||
|
# lower_wavelength_interp_limit = units.nm(param_dico["lower_wavelength_interp_limit"])
|
||||||
|
# logger.log(
|
||||||
|
# f"ignoring wavelength below {lower_wavelength_interp_limit} for dispersion and photon number computation"
|
||||||
|
# )
|
||||||
|
# del param_dico["lower_wavelength_interp_limit"]
|
||||||
|
# else:
|
||||||
|
# lower_wavelength_interp_limit = np.inf
|
||||||
|
|
||||||
|
# #### FIBER PARAMETERS
|
||||||
|
|
||||||
|
# # Unify data whether we want spectra stored at certain places or just
|
||||||
|
# # a certain number of them uniformly spaced
|
||||||
|
# if "z_targets" not in param_dico:
|
||||||
|
# param_dico["z_targets"] = np.linspace(0, 1, state.default_z_target_size)
|
||||||
|
# else:
|
||||||
|
# param_dico["z_targets"] = sanitize_z_targets(param_dico["z_targets"])
|
||||||
|
# param_dico["store_num"] = len(param_dico["z_targets"])
|
||||||
|
|
||||||
|
# # Dispersion parameters of the fiber, as well as gamma
|
||||||
|
# if "interp_range" not in param_dico:
|
||||||
|
|
||||||
|
# # the interpolation range of the dispersion polynomial stops exactly
|
||||||
|
# # at the boundary of the frequency window we consider
|
||||||
|
# param_dico["interp_range"] = [
|
||||||
|
# units.nm.inv(max(np.max(w_c + w0), units.nm(lower_wavelength_interp_limit))),
|
||||||
|
# 1900,
|
||||||
|
# ]
|
||||||
|
|
||||||
|
# if "beta" in param_dico:
|
||||||
|
# param_dico["beta"] = np.array(param_dico["beta"])
|
||||||
|
# temp_gamma = 0
|
||||||
|
# param_dico["dynamic_dispersion"] = False
|
||||||
|
# else:
|
||||||
|
# param_dico["dynamic_dispersion"] = fiber.is_dynamic_dispersion(param_dico)
|
||||||
|
# param_dico["beta"], temp_gamma = fiber.dispersion_central(
|
||||||
|
# param_dico.get("fiber_model", "PCF"), param_dico
|
||||||
|
# )
|
||||||
|
# if param_dico["dynamic_dispersion"]:
|
||||||
|
# param_dico["gamma_func"] = temp_gamma
|
||||||
|
# param_dico["beta_func"] = param_dico["beta"]
|
||||||
|
# param_dico["beta"] = param_dico["beta_func"](0)
|
||||||
|
# temp_gamma = temp_gamma(0)
|
||||||
|
|
||||||
|
# if "gamma" not in param_dico:
|
||||||
|
# param_dico["gamma"] = temp_gamma
|
||||||
|
# logger.log(f"computed gamma coefficient of {temp_gamma:.2e}")
|
||||||
|
|
||||||
|
# # Raman response
|
||||||
|
# if "raman" in param_dico["behaviors"]:
|
||||||
|
# param_dico["hr_w"] = fiber.delayed_raman_w(
|
||||||
|
# t, param_dico["dt"], param_dico.get("raman_type", "stolen")
|
||||||
|
# )
|
||||||
|
|
||||||
|
# #### PULSE PARAMETERS
|
||||||
|
|
||||||
|
# # Convert if pulse energy is given
|
||||||
|
# if "E0" in param_dico:
|
||||||
|
# param_dico["P0"] = pulse.E0_to_P0(
|
||||||
|
# param_dico["E0"], param_dico["T0_FWHM"], param_dico.get("pulse_shape", "gaussian")
|
||||||
|
# )
|
||||||
|
# logger.log(
|
||||||
|
# f"Pulse energy of {1e6 * param_dico['E0']:.2f} microjoules converted to peak power of {1e-3 * param_dico['P0']:.0f}kW."
|
||||||
|
# )
|
||||||
|
|
||||||
|
# # Soliton Number
|
||||||
|
# param_dico["t0"] = (
|
||||||
|
# param_dico["T0_FWHM"] * pulse.fwhm_to_T0_fac[param_dico.get("pulse_shape", "gaussian")]
|
||||||
|
# )
|
||||||
|
# if "N" in param_dico:
|
||||||
|
# param_dico["P0"] = (
|
||||||
|
# param_dico["N"] ** 2
|
||||||
|
# * np.abs(param_dico["beta"][0])
|
||||||
|
# / (param_dico["gamma"] * param_dico["t0"] ** 2)
|
||||||
|
# )
|
||||||
|
|
||||||
|
# logger.log(
|
||||||
|
# "Pump power adjusted to {:.2f} W to match solition number {}".format(
|
||||||
|
# param_dico["P0"], param_dico["N"]
|
||||||
|
# )
|
||||||
|
# )
|
||||||
|
# else:
|
||||||
|
# param_dico["N"] = np.sqrt(
|
||||||
|
# param_dico["P0"]
|
||||||
|
# * param_dico["gamma"]
|
||||||
|
# * param_dico["t0"] ** 2
|
||||||
|
# / np.abs(param_dico["beta"][0])
|
||||||
|
# )
|
||||||
|
# logger.log("Soliton number : {:.2f}".format(param_dico["N"]))
|
||||||
|
|
||||||
|
# # Other caracteristic quantities
|
||||||
|
# param_dico["L_D"] = param_dico["t0"] ** 2 / np.abs(param_dico["beta"][0])
|
||||||
|
# param_dico["L_NL"] = 1 / (param_dico["gamma"] * param_dico["P0"])
|
||||||
|
# param_dico["L_sol"] = pi / 2 * param_dico["L_D"]
|
||||||
|
|
||||||
|
# # Technical noise
|
||||||
|
# if "delta_I" in param_dico:
|
||||||
|
# if param_dico["delta_I"] > 0:
|
||||||
|
# logger.log(f"intensity noise of {param_dico['delta_I']}")
|
||||||
|
# delta_int, delta_T0 = pulse.technical_noise(param_dico["delta_I"])
|
||||||
|
# param_dico["P0"] *= delta_int
|
||||||
|
# param_dico["t0"] *= delta_T0
|
||||||
|
# param_dico["T0_FWHM"] *= delta_T0
|
||||||
|
|
||||||
|
# # Initial field
|
||||||
|
# field_0 = np.zeros(param_dico["nt"], dtype="complex")
|
||||||
|
|
||||||
|
# # check validity if an array is given, otherwise compute it according to given values
|
||||||
|
# if "field_0" in param_dico:
|
||||||
|
# if isinstance(param_dico["field_0"], str):
|
||||||
|
# field_0 = evaluate_field_equation(param_dico["field_0"], **param_dico)
|
||||||
|
# elif len(param_dico["field_0"]) != param_dico["nt"] or not isinstance(
|
||||||
|
# param_dico["field_0"], (tuple, list, np.ndarray)
|
||||||
|
# ):
|
||||||
|
# raise ValueError(
|
||||||
|
# "initial field is given but doesn't match size and type with the time array"
|
||||||
|
# )
|
||||||
|
# else:
|
||||||
|
# shape = param_dico.get("pulse_shape", "gaussian")
|
||||||
|
# if shape.lower() == "gaussian":
|
||||||
|
# field_0 = pulse.gauss_pulse(param_dico["t"], param_dico["T0_FWHM"], param_dico["P0"])
|
||||||
|
# elif shape.lower() == "sech":
|
||||||
|
# field_0 = pulse.sech_pulse(param_dico["t"], param_dico["T0_FWHM"], param_dico["P0"])
|
||||||
|
|
||||||
|
# # Shot noise
|
||||||
|
# if "q_noise" in param_dico["behaviors"]:
|
||||||
|
# field_0 = field_0 + pulse.shot_noise(w_c, w0, param_dico["T"], param_dico["dt"])
|
||||||
|
|
||||||
|
# param_dico["field_0"] = np.array(field_0, dtype="complex")
|
||||||
|
|
||||||
|
# return param_dico
|
||||||
|
|
||||||
|
|
||||||
|
def sanitize_z_targets(z_targets):
|
||||||
|
"""
|
||||||
|
processes the 'z_targets' arguments and guarantees that:
|
||||||
|
- it is sorted
|
||||||
|
- it doesn't contain the same value twice
|
||||||
|
- it starts with 0
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
z_targets : float, int or array-like
|
||||||
|
float or int : end point of the fiber starting from 0
|
||||||
|
array-like of len(.) == 3 : `numpy.linspace` arguments
|
||||||
|
array-like of other length : target distances at which to store the spectra
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
z_targets : list (mutability is important)
|
||||||
|
"""
|
||||||
|
if isinstance(z_targets, (float, int)):
|
||||||
|
z_targets = np.linspace(0, z_targets, state.default_z_target_size)
|
||||||
|
else:
|
||||||
|
z_targets = np.array(z_targets).flatten()
|
||||||
|
|
||||||
|
if len(z_targets) == 3:
|
||||||
|
z_targets = np.linspace(*z_targets[:2], int(z_targets[2]))
|
||||||
|
|
||||||
|
z_targets = list(set(value for value in z_targets if value >= 0))
|
||||||
|
z_targets.sort()
|
||||||
|
|
||||||
|
if 0 not in z_targets:
|
||||||
|
z_targets = [0] + z_targets
|
||||||
|
|
||||||
|
return z_targets
|
||||||
|
|
||||||
|
|
||||||
|
def evaluate_field_equation(eq, **kwargs):
|
||||||
|
return eval(
|
||||||
|
eq,
|
||||||
|
dict(
|
||||||
|
sin=np.sin,
|
||||||
|
cos=np.cos,
|
||||||
|
tan=np.tan,
|
||||||
|
exp=np.exp,
|
||||||
|
pi=np.pi,
|
||||||
|
sqrt=np.sqrt,
|
||||||
|
**kwargs,
|
||||||
|
),
|
||||||
|
)
|
||||||
874
src/scgenerator/io.py
Normal file
874
src/scgenerator/io.py
Normal file
@@ -0,0 +1,874 @@
|
|||||||
|
import itertools
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
from glob import glob
|
||||||
|
from typing import Any, Dict, Iterable, List, Tuple
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
import pkg_resources as pkg
|
||||||
|
import toml
|
||||||
|
from matplotlib.gridspec import GridSpec
|
||||||
|
|
||||||
|
from scgenerator import utilities
|
||||||
|
from scgenerator.const import TMP_FOLDER_KEY_BASE, num
|
||||||
|
from scgenerator.errors import IncompleteDataFolderError
|
||||||
|
|
||||||
|
from . import state
|
||||||
|
|
||||||
|
|
||||||
|
def load_toml(path):
|
||||||
|
"""returns a dictionary parsed from the specified toml file"""
|
||||||
|
if not path.lower().endswith(".toml"):
|
||||||
|
path += ".toml"
|
||||||
|
with open(path, mode="r") as file:
|
||||||
|
dico = toml.load(file)
|
||||||
|
return dico
|
||||||
|
|
||||||
|
|
||||||
|
def save_toml(path, dico):
|
||||||
|
"""saves a dictionary into a toml file"""
|
||||||
|
if not path.lower().endswith(".toml"):
|
||||||
|
path += ".toml"
|
||||||
|
with open(path, mode="w") as file:
|
||||||
|
toml.dump(dico, file)
|
||||||
|
return dico
|
||||||
|
|
||||||
|
|
||||||
|
def get_logger(name=None):
|
||||||
|
"""returns a logging.Logger instance. This function is there because if scgenerator
|
||||||
|
is used with ray, workers are not aware of any configuration done with the logging
|
||||||
|
and so it must be reconfigured.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
name : str, optional
|
||||||
|
name of the logger, by default None
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
logging.Logger obj
|
||||||
|
logger
|
||||||
|
"""
|
||||||
|
name = __name__ if name is None else name
|
||||||
|
logger = logging.getLogger(name)
|
||||||
|
return configure_logger(logger)
|
||||||
|
|
||||||
|
|
||||||
|
def configure_logger(logger, logfile="scgenerator.log"):
|
||||||
|
"""configures a logging.Logger obj
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
logger : logging.Logger
|
||||||
|
logger to configure
|
||||||
|
logfile : str or None, optional
|
||||||
|
path to log file
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
logging.Logger obj
|
||||||
|
updated logger
|
||||||
|
"""
|
||||||
|
if not hasattr(logger, "already_configured"):
|
||||||
|
if logfile is not None:
|
||||||
|
file_handler = logging.FileHandler("scgenerator.log", "a+")
|
||||||
|
file_handler.setFormatter(logging.Formatter("{name}: {message}", style="{"))
|
||||||
|
logger.addHandler(file_handler)
|
||||||
|
|
||||||
|
stream_handler = logging.StreamHandler()
|
||||||
|
logger.addHandler(stream_handler)
|
||||||
|
logger.setLevel(logging.INFO)
|
||||||
|
|
||||||
|
logger.already_configured = True
|
||||||
|
return logger
|
||||||
|
|
||||||
|
|
||||||
|
class Paths:
|
||||||
|
home = os.path.expanduser("~")
|
||||||
|
_data_files = ["silica.toml", "gas.toml", "hr_t.npz"]
|
||||||
|
|
||||||
|
paths = {
|
||||||
|
f.split(".")[0]: os.path.abspath(
|
||||||
|
pkg.resource_filename("scgenerator", os.path.join("data", f))
|
||||||
|
)
|
||||||
|
for f in _data_files
|
||||||
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get(cls, key):
|
||||||
|
if key not in cls.paths:
|
||||||
|
if os.path.exists("paths.json"):
|
||||||
|
with open("paths.json") as file:
|
||||||
|
paths_dico = json.load(file)
|
||||||
|
for k, v in paths_dico.items():
|
||||||
|
cls.paths[k] = os.path.abspath(os.path.expanduser(v))
|
||||||
|
if key not in cls.paths:
|
||||||
|
print(f"{key} was not found in path index, returning current working directory.")
|
||||||
|
cls.paths[key] = os.getcwd()
|
||||||
|
|
||||||
|
return cls.paths[key]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def gets(cls, key):
|
||||||
|
"""returned the specified file as a string"""
|
||||||
|
with open(cls.get(key)) as file:
|
||||||
|
return file.read()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def tmp(task_id=0):
|
||||||
|
suffix = "" if task_id == 0 else str(task_id)
|
||||||
|
return ".scgenerator_tmp" + suffix
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def plot(cls, name):
|
||||||
|
"""returns the paths to the specified plot. Used to save new plot
|
||||||
|
example
|
||||||
|
---------
|
||||||
|
fig.savefig(Paths.plot("figure5.pdf"))
|
||||||
|
"""
|
||||||
|
return os.path.join(cls.get("plots"), name)
|
||||||
|
|
||||||
|
|
||||||
|
def serializable(val):
|
||||||
|
"""returns True if val is serializable into a Json file"""
|
||||||
|
types = (np.ndarray, float, int, str, list, tuple)
|
||||||
|
|
||||||
|
out = isinstance(val, types)
|
||||||
|
if isinstance(val, np.ndarray):
|
||||||
|
out &= val.dtype != "complex"
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def _prepare_for_serialization(dico):
|
||||||
|
"""prepares a dictionary for serialization. Some keys may not be preserved
|
||||||
|
(dropped due to no conversion available)
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
dico : dict
|
||||||
|
dictionary
|
||||||
|
"""
|
||||||
|
forbiden_keys = ["w_c", "w_power_fact", "field_0", "w"]
|
||||||
|
types = (np.ndarray, float, int, str, list, tuple, dict)
|
||||||
|
out = {}
|
||||||
|
for key, value in dico.items():
|
||||||
|
if key in forbiden_keys:
|
||||||
|
continue
|
||||||
|
if not isinstance(value, types):
|
||||||
|
continue
|
||||||
|
if isinstance(value, dict):
|
||||||
|
out[key] = _prepare_for_serialization(value)
|
||||||
|
elif isinstance(value, np.ndarray) and value.dtype == complex:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
out[key] = value
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def save_parameters(param_dict, file_name="param"):
|
||||||
|
"""Writes the flattened parameters dictionary specific to a single simulation into a toml file
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
param_dict : dictionary of parameters. Only floats, int and arrays of
|
||||||
|
non complex values are stored in the json
|
||||||
|
folder_name : folder where to save the files (relative to cwd)
|
||||||
|
file_name : name of the readable file.
|
||||||
|
"""
|
||||||
|
param = param_dict.copy()
|
||||||
|
|
||||||
|
folder_name, file_name = os.path.split(file_name)
|
||||||
|
folder_name = "tmp" if folder_name == "" else folder_name
|
||||||
|
file_name = os.path.splitext(file_name)[0]
|
||||||
|
|
||||||
|
if not os.path.exists(folder_name):
|
||||||
|
os.makedirs(folder_name)
|
||||||
|
|
||||||
|
param = _prepare_for_serialization(param)
|
||||||
|
param["datetime"] = datetime.now()
|
||||||
|
|
||||||
|
# save toml of the simulation
|
||||||
|
with open(os.path.join(folder_name, file_name + ".toml"), "w") as file:
|
||||||
|
toml.dump(param, file, encoder=toml.TomlNumpyEncoder())
|
||||||
|
|
||||||
|
return os.path.join(folder_name, file_name)
|
||||||
|
|
||||||
|
|
||||||
|
def load_previous_parameters(path):
|
||||||
|
"""loads a parameters json files and converts data to appropriate type
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
path : path-like
|
||||||
|
path to the json
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
params : dict
|
||||||
|
"""
|
||||||
|
params = load_toml(path)
|
||||||
|
for k, v in params.items():
|
||||||
|
if isinstance(v, list):
|
||||||
|
if isinstance(v[0], (float, int)):
|
||||||
|
params[k] = np.array(v)
|
||||||
|
return params
|
||||||
|
|
||||||
|
|
||||||
|
def load_material_dico(name):
|
||||||
|
"""loads a material dictionary
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
name : str
|
||||||
|
name of the material
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
material_dico : dict
|
||||||
|
"""
|
||||||
|
if name == "silica":
|
||||||
|
return toml.loads(Paths.gets("silica"))
|
||||||
|
else:
|
||||||
|
return toml.loads(Paths.gets("gas"))[name]
|
||||||
|
|
||||||
|
|
||||||
|
def load_sim_data(folder_name, ind=None, load_param=True):
|
||||||
|
"""
|
||||||
|
loads the data already simulated.
|
||||||
|
defauft shape is (z_targets, n, nt)
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
folder_name : (string) folder where the simulation data is stored
|
||||||
|
ind : list of indices if only certain spectra are desired.
|
||||||
|
- If left to None, returns every spectrum
|
||||||
|
- If only 1 int, will cast the (1, n, nt) array into a (n, nt) array
|
||||||
|
load_param : (bool) return the parameter dictionary as well. returns None
|
||||||
|
if not available
|
||||||
|
dico_name : name of the params dict stored in state.Params
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
spectra : array
|
||||||
|
squeezed array of complex spectra (n simulation on a nt size grid at each ind)
|
||||||
|
Raises
|
||||||
|
----------
|
||||||
|
FileNotFoundError : folder does not exist or does not contain sufficient
|
||||||
|
data
|
||||||
|
"""
|
||||||
|
|
||||||
|
print(f"opening {folder_name}")
|
||||||
|
|
||||||
|
# Check if file exists and assert how many z positions there are
|
||||||
|
if not os.path.exists(folder_name):
|
||||||
|
raise FileNotFoundError(f"Folder {folder_name} does not exist")
|
||||||
|
nmax = len(glob(os.path.join(folder_name, "spectra_*.npy")))
|
||||||
|
if nmax <= 0:
|
||||||
|
raise FileNotFoundError(f"No appropriate file in specified folder {folder_name}")
|
||||||
|
|
||||||
|
if ind is None:
|
||||||
|
ind = range(nmax)
|
||||||
|
elif isinstance(ind, int):
|
||||||
|
ind = [ind]
|
||||||
|
|
||||||
|
# Load the spectra
|
||||||
|
spectra = []
|
||||||
|
for i in ind:
|
||||||
|
spectra.append(load_single_spectrum(folder_name, i))
|
||||||
|
spectra = np.array(spectra)
|
||||||
|
|
||||||
|
# Load the parameters dictionary
|
||||||
|
try:
|
||||||
|
params = load_previous_parameters(os.path.join(folder_name, "params.toml"))
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(f"parameters corresponding to {folder_name} not found")
|
||||||
|
params = None
|
||||||
|
|
||||||
|
print("data successfully loaded")
|
||||||
|
if load_param:
|
||||||
|
return spectra.squeeze(), params
|
||||||
|
else:
|
||||||
|
return spectra.squeeze()
|
||||||
|
|
||||||
|
|
||||||
|
def get_all_environ() -> Dict[str, str]:
|
||||||
|
"""returns a dictionary of all environment variables set by any instance of scgenerator"""
|
||||||
|
return dict(filter(lambda el: el[0].startswith(TMP_FOLDER_KEY_BASE), os.environ.items()))
|
||||||
|
|
||||||
|
|
||||||
|
def load_single_spectrum(folder, index) -> np.ndarray:
|
||||||
|
return np.load(os.path.join(folder, f"spectra_{index}.npy"))
|
||||||
|
|
||||||
|
|
||||||
|
def iter_load_sim_data(folder_name, with_params=False) -> Iterable[np.ndarray]:
|
||||||
|
"""
|
||||||
|
similar to load_sim_data but works as an iterator
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not os.path.exists(folder_name):
|
||||||
|
raise FileNotFoundError(f"Folder {folder_name} does not exist")
|
||||||
|
nmax = len(glob(os.path.join(folder_name, "spectra_*.npy")))
|
||||||
|
if nmax <= 0:
|
||||||
|
raise FileNotFoundError(f"No appropriate file in specified folder {folder_name}")
|
||||||
|
|
||||||
|
params = {}
|
||||||
|
if with_params:
|
||||||
|
try:
|
||||||
|
params = load_previous_parameters(os.path.join(folder_name, "params.toml"))
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(f"parameters corresponding to {folder_name} not found")
|
||||||
|
params = None
|
||||||
|
|
||||||
|
print(f"iterating through {folder_name}")
|
||||||
|
for i in range(nmax):
|
||||||
|
if with_params:
|
||||||
|
yield load_single_spectrum(folder_name, i), params
|
||||||
|
else:
|
||||||
|
yield load_single_spectrum(folder_name, i)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_data_subfolders(path: str) -> List[str]:
|
||||||
|
"""returns a list of subfolders in the specified directory
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
path : str
|
||||||
|
path to directory containing the initial config file and the spectra sub folders
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
List[str]
|
||||||
|
paths to sub folders
|
||||||
|
"""
|
||||||
|
sub_folders = glob(os.path.join(path, "*"))
|
||||||
|
sub_folders = list(filter(os.path.isdir, sub_folders))
|
||||||
|
return sub_folders
|
||||||
|
|
||||||
|
|
||||||
|
# def _sort_subfolder_list(
|
||||||
|
# sub_folders: List[str], varying_lists: List[Tuple[str, Any]]
|
||||||
|
# ) -> Tuple[list]:
|
||||||
|
# """sorts the two lists in parallel according to parameter values
|
||||||
|
|
||||||
|
# Parameters
|
||||||
|
# ----------
|
||||||
|
# sub_folders : List[str]
|
||||||
|
# paths to where spectra are loaded
|
||||||
|
# varying_lists : List[Tuple]
|
||||||
|
# (param_name, value) tuples corresponding to the sub_folders
|
||||||
|
|
||||||
|
# Returns
|
||||||
|
# -------
|
||||||
|
# Tuple[list]
|
||||||
|
# the input, sorted
|
||||||
|
# """
|
||||||
|
# both_lists = list(zip(sub_folders, varying_lists))
|
||||||
|
# for i in range(len(varying_lists[0])):
|
||||||
|
# both_lists.sort(key=lambda el: el[1][i][1])
|
||||||
|
# return tuple(zip(*both_lists))
|
||||||
|
|
||||||
|
|
||||||
|
def check_data_integrity(sub_folders: List[str], init_z_num: int):
|
||||||
|
"""checks the integrity and completeness of a simulation data folder
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
path : str
|
||||||
|
path to the data folder
|
||||||
|
init_z_num : int
|
||||||
|
z_num as specified by the initial configuration file
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
IncompleteDataFolderError
|
||||||
|
raised if not all spectra are present in any folder
|
||||||
|
"""
|
||||||
|
for sub_folder in sub_folders:
|
||||||
|
params = load_toml(os.path.join(sub_folder, "params.toml"))
|
||||||
|
z_num = params["z_num"]
|
||||||
|
num_spectra = len(glob(os.path.join(sub_folder, "spectrum*.npy")))
|
||||||
|
|
||||||
|
if z_num != init_z_num:
|
||||||
|
raise IncompleteDataFolderError(
|
||||||
|
f"initial config specifies {init_z_num} spectra per"
|
||||||
|
+ f" but the parameter file in {sub_folder} specifies {z_num}"
|
||||||
|
)
|
||||||
|
|
||||||
|
if num_spectra != z_num:
|
||||||
|
raise IncompleteDataFolderError(
|
||||||
|
f"only {num_spectra} spectra found in {sub_folder} instead of the specified {z_num}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# def preprocess_data_folder(path: str) -> bool:
|
||||||
|
# config = load_toml(os.path.join(path, "initial_config.toml"))
|
||||||
|
# num_sims, _ = utilities.count_variations(config)
|
||||||
|
# sub_folders = _get_data_subfolders(path)
|
||||||
|
# init_z_num = config["simulation"]["z_num"]
|
||||||
|
|
||||||
|
# if len(sub_folders) != num_sims:
|
||||||
|
# raise IncompleteDataFolderError(
|
||||||
|
# f"only {len(sub_folders)} simulations out of {num_sims} have been made"
|
||||||
|
# )
|
||||||
|
|
||||||
|
# varying_lists = [utilities.varying_list_from_path(os.path.split(s)[1]) for s in sub_folders]
|
||||||
|
# varying_params = [el[0] for el in varying_lists[0]]
|
||||||
|
# sub_folders, varying_lists = _update_varying_lists(
|
||||||
|
# sub_folders, varying_lists, varying_params, init_z_num
|
||||||
|
# )
|
||||||
|
|
||||||
|
# possible_values = []
|
||||||
|
# for i, p in enumerate(varying_params):
|
||||||
|
# tmp = set()
|
||||||
|
# for v_list in varying_lists:
|
||||||
|
# tmp.add(v_list[i][1])
|
||||||
|
# tmp = list(tmp)
|
||||||
|
# possible_values.append(tmp)
|
||||||
|
|
||||||
|
# return sub_folders, varying_lists, varying_params, possible_values, init_z_num
|
||||||
|
|
||||||
|
|
||||||
|
# def merge_data(path: str):
|
||||||
|
# sub_folders, varying_lists, varying_params, possible_values, z_num = preprocess_data_folder(
|
||||||
|
# path
|
||||||
|
# )
|
||||||
|
# z_values = list(range(z_num))
|
||||||
|
# pt = utilities.ProgressTracker(z_num, auto_print=True)
|
||||||
|
# shape = tuple((len(l) for l in possible_values))
|
||||||
|
# for z_num in z_values:
|
||||||
|
# to_save = []
|
||||||
|
# for i in range(np.product(shape)):
|
||||||
|
# to_save.append(np.load(os.path.join(sub_folders[i], f"spectrum_{z_num}.npy")))
|
||||||
|
# out = np.array(to_save).reshape((*shape, len(to_save[0])))
|
||||||
|
# np.save(os.path.join(path, f"spectra_{z_num}.npy"), out)
|
||||||
|
# pt.update()
|
||||||
|
# _create_reference_file(varying_params, possible_values)
|
||||||
|
# return
|
||||||
|
|
||||||
|
|
||||||
|
def merge_same_simulations(path: str):
|
||||||
|
num_separator = "_num_"
|
||||||
|
sub_folders = _get_data_subfolders(path)
|
||||||
|
config = load_toml(os.path.join(path, "initial_config.toml"))
|
||||||
|
repeat = config["simulation"].get("repeat", 1)
|
||||||
|
z_num = config["simulation"]["z_num"]
|
||||||
|
|
||||||
|
check_data_integrity(sub_folders, z_num)
|
||||||
|
|
||||||
|
base_folders = set()
|
||||||
|
for sub_folder in sub_folders:
|
||||||
|
splitted_base_path = sub_folder.split(num_separator)[:-1]
|
||||||
|
base_folder = num_separator.join(splitted_base_path)
|
||||||
|
if len(base_folder) > 0:
|
||||||
|
base_folders.add(base_folder)
|
||||||
|
|
||||||
|
print(base_folders)
|
||||||
|
for base_folder in base_folders:
|
||||||
|
for j in range(z_num):
|
||||||
|
spectra = []
|
||||||
|
for i in range(repeat):
|
||||||
|
spectra.append(
|
||||||
|
np.load(os.path.join(f"{base_folder}{num_separator}{i}/spectrum_{j}.npy"))
|
||||||
|
)
|
||||||
|
dest_folder = ensure_folder(base_folder, prevent_overwrite=False)
|
||||||
|
spectra = np.array(spectra).reshape(repeat, len(spectra[0]))
|
||||||
|
np.save(os.path.join(dest_folder, f"spectra_{j}.npy"), spectra)
|
||||||
|
|
||||||
|
|
||||||
|
# class tmp_index_manager:
|
||||||
|
# """Manages a temporary index of files while the simulation is running
|
||||||
|
# and merge them at the end automatically"""
|
||||||
|
|
||||||
|
# def __init__(self, config_name="untitled", task_id=0, varying_keys=None):
|
||||||
|
|
||||||
|
# self.path = os.path.join(Paths.tmp(task_id), "index.json")
|
||||||
|
# self.config_name = config_name
|
||||||
|
# self.varying_keys = varying_keys
|
||||||
|
|
||||||
|
# # set up the directories
|
||||||
|
# if not os.path.exists(Paths.tmp(task_id)):
|
||||||
|
# os.makedirs(Paths.tmp(task_id))
|
||||||
|
|
||||||
|
# file_num = 0
|
||||||
|
# while os.path.exists(self.path):
|
||||||
|
# self.path = os.path.join(Paths.tmp(task_id), f"index_{file_num}.json")
|
||||||
|
# file_num += 1
|
||||||
|
|
||||||
|
# self.index = dict(spectra={}, z={}, params={})
|
||||||
|
# self.ids = set()
|
||||||
|
|
||||||
|
# with open(self.path, "w") as file:
|
||||||
|
# json.dump(self.index, file)
|
||||||
|
|
||||||
|
# def get_path(self):
|
||||||
|
# return self.path
|
||||||
|
|
||||||
|
# def append_to_index(self, param_id, spectra_file_name="", params_file_name=""):
|
||||||
|
# """add one or two files to the index
|
||||||
|
# Parameters
|
||||||
|
# ----------
|
||||||
|
# param_id : id of the parameter set
|
||||||
|
# spectra_file_name : name of the spectra file
|
||||||
|
# params_file_name : name of the parameters file
|
||||||
|
# Returns
|
||||||
|
# ----------
|
||||||
|
# None
|
||||||
|
# """
|
||||||
|
|
||||||
|
# # names of the recorded values in order
|
||||||
|
# # here : {"spectra":spectra_file_name, "params":params_file_name}
|
||||||
|
# file_names = [spectra_file_name, params_file_name]
|
||||||
|
# file_names_dict = dict(zip(state.recorded_types, file_names))
|
||||||
|
|
||||||
|
# param_id = str(param_id)
|
||||||
|
# self.ids.add(param_id)
|
||||||
|
|
||||||
|
# with open(self.path, "r") as file:
|
||||||
|
# self.index = json.loads(file.read())
|
||||||
|
|
||||||
|
# for type_name, file_name in file_names_dict.items():
|
||||||
|
# if file_name != "":
|
||||||
|
# if param_id not in self.index[type_name]:
|
||||||
|
# self.index[type_name][param_id] = []
|
||||||
|
# self.index[type_name][param_id].append(file_name)
|
||||||
|
|
||||||
|
# with open(self.path, "w") as file:
|
||||||
|
# json.dump(self.index, file)
|
||||||
|
|
||||||
|
# def convert_sim_data(self):
|
||||||
|
# return convert_sim_data(self.path, name=self.config_name, varying_keys=self.varying_keys)
|
||||||
|
|
||||||
|
|
||||||
|
# def convert_sim_data(path, name="untitled", ids=None, varying_keys=[], delete_temps=True):
|
||||||
|
# """Converts simulation data that are stored as 1 file/simulation to 1 file
|
||||||
|
# per parameters set
|
||||||
|
# Parameters
|
||||||
|
# ----------
|
||||||
|
# path : path to the index containing infos about how to group files together
|
||||||
|
# name : name of the final folder
|
||||||
|
# ids : list of ids, 1 per set of parameters
|
||||||
|
|
||||||
|
# Returns
|
||||||
|
# ----------
|
||||||
|
# path to the converted data
|
||||||
|
|
||||||
|
# """
|
||||||
|
# with open(path, "r") as file:
|
||||||
|
# index = json.loads(file.read())
|
||||||
|
|
||||||
|
# folder_0 = os.path.join(Paths.get("data"), name)
|
||||||
|
# folder_0 = ensure_folder(folder_0) # related to the set of simulation / job
|
||||||
|
|
||||||
|
# # find the ids if not stored already
|
||||||
|
# if ids is None:
|
||||||
|
# ids = set()
|
||||||
|
# for key in state.recorded_types:
|
||||||
|
# for k in index[key]:
|
||||||
|
# ids.add(k)
|
||||||
|
|
||||||
|
# not_found = []
|
||||||
|
|
||||||
|
# for param_id in ids:
|
||||||
|
|
||||||
|
# print("ids", ids)
|
||||||
|
|
||||||
|
# # Load the spectra
|
||||||
|
# spectra = []
|
||||||
|
# for f in index["spectra"][param_id]:
|
||||||
|
# try:
|
||||||
|
# spectra.append(np.load(f))
|
||||||
|
# except FileNotFoundError:
|
||||||
|
# not_found.append(f)
|
||||||
|
# index["spectra"][param_id].remove(f)
|
||||||
|
|
||||||
|
# spectra = np.array(spectra)
|
||||||
|
|
||||||
|
# # Load the params
|
||||||
|
# main_param_name = index["params"][param_id][0] + ".json"
|
||||||
|
# try:
|
||||||
|
# with open(main_param_name, "r") as file:
|
||||||
|
# params = json.load(file)
|
||||||
|
# except FileNotFoundError:
|
||||||
|
# print(f"no parameters for id {param_id} found. Skipping this one")
|
||||||
|
# not_found += index["params"][param_id]
|
||||||
|
# continue
|
||||||
|
|
||||||
|
# if len(not_found) > 0:
|
||||||
|
# print(f"{len(not_found)} files not found:")
|
||||||
|
# for file_not_found in not_found:
|
||||||
|
# print("\t" + file_not_found)
|
||||||
|
|
||||||
|
# # create sub folder
|
||||||
|
# if len(ids) > 1:
|
||||||
|
# complement = [param_id]
|
||||||
|
# for key in varying_keys:
|
||||||
|
# if key in ["T0_FWHM", "P0"]:
|
||||||
|
# key = "init_" + key
|
||||||
|
# complement.append(key)
|
||||||
|
# complement.append(format(params.get(key, 0), ".2e").split("e")[0])
|
||||||
|
|
||||||
|
# folder_1 = "_".join(complement) # related to specific parameter
|
||||||
|
# folder_name = os.path.join(folder_0, folder_1)
|
||||||
|
# else:
|
||||||
|
# folder_name = folder_0
|
||||||
|
|
||||||
|
# if not os.path.exists(folder_name):
|
||||||
|
# os.makedirs(folder_name)
|
||||||
|
# os.rename(main_param_name, os.path.join(folder_name, "param.json"))
|
||||||
|
|
||||||
|
# # Save the data in a more easily manageable format (one file per z position)
|
||||||
|
# for k in range(len(spectra[0])):
|
||||||
|
# np.save(os.path.join(folder_name, f"spectra_{k}"), spectra[:, k])
|
||||||
|
# print(f"{len(spectra)} simulations converted. Data saved in {folder_name}")
|
||||||
|
|
||||||
|
# deleted = 0
|
||||||
|
# if delete_temps:
|
||||||
|
# # once everything is saved, delete the temporary files to free up space
|
||||||
|
# param_file_names = [f + ".json" for f in index["params"][param_id]]
|
||||||
|
# try:
|
||||||
|
# param_file_names.remove(main_param_name)
|
||||||
|
# except ValueError:
|
||||||
|
# pass
|
||||||
|
|
||||||
|
# fail_list = []
|
||||||
|
# for f in index["spectra"][param_id] + param_file_names:
|
||||||
|
# try:
|
||||||
|
# os.remove(f)
|
||||||
|
# deleted += 1
|
||||||
|
# except FileNotFoundError:
|
||||||
|
# fail_list.append(f)
|
||||||
|
|
||||||
|
# if len(fail_list) > 0:
|
||||||
|
# print(f"could not remove {len(fail_list)} temporary files :")
|
||||||
|
# for failed in fail_list:
|
||||||
|
# print("\t" + failed)
|
||||||
|
|
||||||
|
# print(f"Merge finished, deleted {deleted} temporary files.")
|
||||||
|
|
||||||
|
# if delete_temps:
|
||||||
|
# os.remove(path)
|
||||||
|
# delete_tmp_folder()
|
||||||
|
# return folder_0
|
||||||
|
|
||||||
|
|
||||||
|
# def delete_tmp_folder():
|
||||||
|
# """deletes temporary folders if they are empty"""
|
||||||
|
# for folder in glob(Paths.tmp()):
|
||||||
|
# try:
|
||||||
|
# os.rmdir(folder)
|
||||||
|
# except OSError as err:
|
||||||
|
# print(err)
|
||||||
|
|
||||||
|
|
||||||
|
def get_data_folder(task_id: int, name_if_new: str = ""):
|
||||||
|
idstr = str(int(task_id))
|
||||||
|
tmp = os.getenv(TMP_FOLDER_KEY_BASE + idstr)
|
||||||
|
if tmp is None:
|
||||||
|
tmp = ensure_folder("scgenerator_" + name_if_new + idstr)
|
||||||
|
tmp = os.path.abspath(tmp)
|
||||||
|
os.environ[TMP_FOLDER_KEY_BASE + idstr] = tmp
|
||||||
|
return tmp
|
||||||
|
|
||||||
|
|
||||||
|
def generate_file_path(file_name: str, task_id: int, sub_folder: str = "") -> str:
|
||||||
|
"""generates a path for the desired file name
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
file_name : str
|
||||||
|
desired file name. May be altered if it already exists
|
||||||
|
task_id : int
|
||||||
|
unique id of the process
|
||||||
|
sub_folder : str
|
||||||
|
subfolder in which to store the file. default : ""
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
str
|
||||||
|
the full path
|
||||||
|
"""
|
||||||
|
base_name, ext = os.path.splitext(file_name)
|
||||||
|
folder = get_data_folder(task_id)
|
||||||
|
folder = os.path.join(folder, sub_folder)
|
||||||
|
folder = ensure_folder(folder, prevent_overwrite=False)
|
||||||
|
i = 0
|
||||||
|
base_name = os.path.join(folder, base_name)
|
||||||
|
new_name = base_name + ext
|
||||||
|
while os.path.exists(new_name):
|
||||||
|
print(f"{i=}")
|
||||||
|
new_name = f"{base_name}_{i}{ext}"
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
return new_name
|
||||||
|
|
||||||
|
|
||||||
|
def save_data(data: np.ndarray, file_name: str, task_id: int, subfolder: str = ""):
|
||||||
|
"""saves numpy array to disk
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
data : np.ndarray
|
||||||
|
data to save
|
||||||
|
file_name : str
|
||||||
|
file name
|
||||||
|
task_id : int
|
||||||
|
id that uniquely identifies the process
|
||||||
|
subfolder : str, optional
|
||||||
|
subfolder in the main data folder of the task, by default ""
|
||||||
|
"""
|
||||||
|
path = generate_file_path(file_name, task_id, subfolder)
|
||||||
|
np.save(path, data)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_tmp_file_name_old(file_name, job_id=0, param_id=0, task_id=0, ext=""):
|
||||||
|
"""returns a guaranteed available file name"""
|
||||||
|
main_suffix = f"_JOBID{job_id}_PARAMID{param_id}"
|
||||||
|
suffix = main_suffix + "_" + str(0)
|
||||||
|
|
||||||
|
no_dup = 1
|
||||||
|
while os.path.exists(os.path.join(Paths.tmp(task_id), file_name + suffix + ext)):
|
||||||
|
suffix = main_suffix + "_" + str(no_dup)
|
||||||
|
no_dup += 1
|
||||||
|
|
||||||
|
return os.path.join(Paths.tmp(task_id), file_name + suffix + ext)
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_folder(name, i=0, suffix="", prevent_overwrite=True):
|
||||||
|
"""creates a folder for simulation data named name and prevents overwrite
|
||||||
|
by adding a suffix if necessary and returning the name"""
|
||||||
|
prefix, last_dir = os.path.split(os.path.abspath(name))
|
||||||
|
exploded = [prefix]
|
||||||
|
sub_prefix = prefix
|
||||||
|
while sub_prefix != os.path.abspath("/"):
|
||||||
|
sub_prefix, _ = os.path.split(sub_prefix)
|
||||||
|
exploded.append(sub_prefix)
|
||||||
|
if any(os.path.isfile(el) for el in exploded):
|
||||||
|
prefix = ensure_folder(prefix)
|
||||||
|
name = os.path.join(prefix, last_dir)
|
||||||
|
folder_name = name
|
||||||
|
if i > 0:
|
||||||
|
folder_name += f"_{i}"
|
||||||
|
folder_name += suffix
|
||||||
|
if not os.path.exists(folder_name):
|
||||||
|
os.makedirs(folder_name)
|
||||||
|
else:
|
||||||
|
if prevent_overwrite:
|
||||||
|
return ensure_folder(name, i + 1)
|
||||||
|
else:
|
||||||
|
return folder_name
|
||||||
|
return folder_name
|
||||||
|
|
||||||
|
|
||||||
|
# class Logger:
|
||||||
|
# def __init__(self, print_level=10000):
|
||||||
|
# """
|
||||||
|
# Parameters
|
||||||
|
# ----------
|
||||||
|
# print_level : messages above this priority will be printed as well as recorded
|
||||||
|
# """
|
||||||
|
# log_file_name = (
|
||||||
|
# "scgenerator_log_"
|
||||||
|
# + format(datetime.today())[:-7].replace(" ", "_").replace(":", "-")
|
||||||
|
# + ".txt"
|
||||||
|
# )
|
||||||
|
# self.log_file = os.path.join(Paths.get("logs"), log_file_name)
|
||||||
|
# self.print_level = print_level
|
||||||
|
# self.prefix_length = 0
|
||||||
|
# self.default_prefix = "Main Thread"
|
||||||
|
|
||||||
|
# if not os.path.exists(self.log_file):
|
||||||
|
# with open(self.log_file, "w"):
|
||||||
|
# pass
|
||||||
|
|
||||||
|
# with open(self.log_file, "a") as file:
|
||||||
|
# file.write(
|
||||||
|
# f"\n---------------------------\nNew Log {str(datetime.today()):19.19}\n---------------------------\n"
|
||||||
|
# )
|
||||||
|
|
||||||
|
# def log(self, s, priority=0, prefix=None):
|
||||||
|
# """logs a message
|
||||||
|
# Parameters
|
||||||
|
# ----------
|
||||||
|
# s : the string to log
|
||||||
|
# priority : will be compared to the logger's print_level to decide whether to print the string
|
||||||
|
# prefix : string identifying which thread or part of the program is giving the message
|
||||||
|
# Returns
|
||||||
|
# ----------
|
||||||
|
# nothing
|
||||||
|
# """
|
||||||
|
# if prefix is None:
|
||||||
|
# prefix = self.default_prefix
|
||||||
|
# if priority >= self.print_level:
|
||||||
|
# print(s)
|
||||||
|
# with open(self.log_file, "a") as file:
|
||||||
|
# if len(prefix) > self.prefix_length:
|
||||||
|
# self.prefix_length = len(prefix)
|
||||||
|
# prefix = format(prefix[: self.prefix_length], str(self.prefix_length))
|
||||||
|
# file.write(prefix + " : " + str(s) + "\n")
|
||||||
|
|
||||||
|
|
||||||
|
def plot_setup(
|
||||||
|
folder_name=None,
|
||||||
|
file_name=None,
|
||||||
|
file_type="png",
|
||||||
|
figsize=state.plot_default_figsize,
|
||||||
|
params=None,
|
||||||
|
mode="default",
|
||||||
|
):
|
||||||
|
"""It should return :
|
||||||
|
- a folder_name
|
||||||
|
- a file name
|
||||||
|
- a fig
|
||||||
|
- an axis
|
||||||
|
"""
|
||||||
|
file_name = state.plot_default_name if file_name is None else file_name
|
||||||
|
|
||||||
|
if params is not None:
|
||||||
|
folder_name = params.get("plot.folder_name", folder_name)
|
||||||
|
file_name = params.get("plot.file_name", file_name)
|
||||||
|
file_type = params.get("plot.file_type", file_type)
|
||||||
|
figsize = params.get("plot.figsize", figsize)
|
||||||
|
|
||||||
|
# ensure output folder_name exists
|
||||||
|
folder_name, file_name = (
|
||||||
|
os.path.split(file_name)
|
||||||
|
if folder_name is None
|
||||||
|
else (folder_name, os.path.split(file_name)[1])
|
||||||
|
)
|
||||||
|
folder_name = os.path.join(Paths.get("plots"), folder_name)
|
||||||
|
if not os.path.exists(os.path.abspath(folder_name)):
|
||||||
|
os.makedirs(os.path.abspath(folder_name))
|
||||||
|
|
||||||
|
# ensure no overwrite
|
||||||
|
ind = 0
|
||||||
|
while os.path.exists(os.path.join(folder_name, file_name + "_" + str(ind) + "." + file_type)):
|
||||||
|
ind += 1
|
||||||
|
file_name = file_name + "_" + str(ind) + "." + file_type
|
||||||
|
|
||||||
|
if mode == "default":
|
||||||
|
fig, ax = plt.subplots(figsize=figsize)
|
||||||
|
elif mode == "coherence":
|
||||||
|
n = state.plot_avg_default_main_to_coherence_ratio
|
||||||
|
gs1 = GridSpec(n + 1, 1, hspace=0.4)
|
||||||
|
fig = plt.figure(figsize=state.plot_default_figsize)
|
||||||
|
top = fig.add_subplot(gs1[:n])
|
||||||
|
top.tick_params(labelbottom=False)
|
||||||
|
bot = fig.add_subplot(gs1[n], sharex=top)
|
||||||
|
|
||||||
|
bot.set_ylim(-0.1, 1.1)
|
||||||
|
bot.set_ylabel(r"|$g_{12}$|")
|
||||||
|
ax = (top, bot)
|
||||||
|
elif mode == "coherence_T":
|
||||||
|
n = state.plot_avg_default_main_to_coherence_ratio
|
||||||
|
gs1 = GridSpec(1, n + 1, wspace=0.4)
|
||||||
|
fig = plt.figure(figsize=state.plot_default_figsize)
|
||||||
|
top = fig.add_subplot(gs1[:n])
|
||||||
|
top.tick_params(labelleft=False, left=False, right=True)
|
||||||
|
bot = fig.add_subplot(gs1[n], sharey=top)
|
||||||
|
|
||||||
|
bot.set_xlim(1.1, -0.1)
|
||||||
|
bot.set_xlabel(r"|$g_{12}$|")
|
||||||
|
ax = (top, bot)
|
||||||
|
else:
|
||||||
|
raise ValueError(f"mode {mode} not understood")
|
||||||
|
|
||||||
|
return folder_name, file_name, fig, ax
|
||||||
125
src/scgenerator/math.py
Normal file
125
src/scgenerator/math.py
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
from typing import Type
|
||||||
|
import numpy as np
|
||||||
|
from scipy.special import jn_zeros
|
||||||
|
from scipy.interpolate import interp1d, griddata
|
||||||
|
|
||||||
|
|
||||||
|
def span(*vec):
|
||||||
|
"""returns the min and max of whatever array-like is given. can accept many args"""
|
||||||
|
out = (np.inf, -np.inf)
|
||||||
|
for x in vec:
|
||||||
|
x = np.atleast_1d(x)
|
||||||
|
if len(x.shape) > 1:
|
||||||
|
x = x.ravel()
|
||||||
|
minx = np.min(x)
|
||||||
|
maxx = np.max(x)
|
||||||
|
out = (np.min([minx, out[0]]), np.max([maxx, out[1]]))
|
||||||
|
|
||||||
|
if out[0] == np.inf or out[1] == -np.inf:
|
||||||
|
out = (0, 1)
|
||||||
|
print(f"failed to evaluate the span of {vec}")
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def argclosest(array, target):
|
||||||
|
"""returns the index/indices corresponding to the closest matches of target in array"""
|
||||||
|
min_dist = np.inf
|
||||||
|
index = None
|
||||||
|
if isinstance(target, (list, tuple, np.ndarray)):
|
||||||
|
return np.array([argclosest(array, t) for t in target])
|
||||||
|
for k, val in enumerate(array):
|
||||||
|
dist = abs(val - target)
|
||||||
|
if dist < min_dist:
|
||||||
|
min_dist = dist
|
||||||
|
index = k
|
||||||
|
|
||||||
|
return index
|
||||||
|
|
||||||
|
|
||||||
|
def length(x):
|
||||||
|
return np.max(x) - np.min(x)
|
||||||
|
|
||||||
|
|
||||||
|
def power_fact(x, n):
|
||||||
|
"""
|
||||||
|
returns x ^ n / n!
|
||||||
|
"""
|
||||||
|
if isinstance(x, (int, float)):
|
||||||
|
x = float(x)
|
||||||
|
result = 1.0
|
||||||
|
|
||||||
|
elif isinstance(x, np.ndarray):
|
||||||
|
if x.dtype == int:
|
||||||
|
x = np.array(x, dtype=float)
|
||||||
|
result = np.ones(len(x))
|
||||||
|
else:
|
||||||
|
raise TypeError(f"type {type(x)} of x not supported.")
|
||||||
|
|
||||||
|
for k in range(n):
|
||||||
|
result = result * x / (n - k)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def abs2(z):
|
||||||
|
return z.real ** 2 + z.imag ** 2
|
||||||
|
|
||||||
|
|
||||||
|
def sigmoid(x):
|
||||||
|
return 1 / (np.exp(-x) + 1)
|
||||||
|
|
||||||
|
|
||||||
|
def u_nm(n, m):
|
||||||
|
"""returns the mth zero of the Bessel function of order n-1
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
n-1 : order of the Bessel function
|
||||||
|
m : order of the zero
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
float
|
||||||
|
"""
|
||||||
|
return jn_zeros(n - 1, m)[-1]
|
||||||
|
|
||||||
|
|
||||||
|
def make_uniform_2D(values, x_axis, y_axis, n=1024, method="linear"):
|
||||||
|
"""Interpolates a 2D array with the help of griddata
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
values : 2D array of real values
|
||||||
|
x_axis : x-coordinates of values
|
||||||
|
y_axis : y-coordinates of values
|
||||||
|
method : method of interpolation to be passed to griddata
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
array of shape n
|
||||||
|
"""
|
||||||
|
xx, yy = np.meshgrid(x_axis, y_axis)
|
||||||
|
xx = xx.flatten()
|
||||||
|
yy = yy.flatten()
|
||||||
|
|
||||||
|
if not isinstance(n, tuple):
|
||||||
|
n = (n, n)
|
||||||
|
|
||||||
|
# old_points = np.array([gridx.ravel(), gridy.ravel()])
|
||||||
|
|
||||||
|
newx, newy = np.meshgrid(np.linspace(*span(x_axis), n[0]), np.linspace(*span(y_axis), n[1]))
|
||||||
|
|
||||||
|
print("interpolating")
|
||||||
|
out = griddata((xx, yy), values.flatten(), (newx, newy), method=method, fill_value=0)
|
||||||
|
print("interpolating done!")
|
||||||
|
return out.reshape(n[1], n[0])
|
||||||
|
|
||||||
|
|
||||||
|
def make_uniform_1D(values, x_axis, n=1024, method="linear"):
|
||||||
|
"""Interpolates a 2D array with the help of interp1d
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
values : 1D array of real values
|
||||||
|
x_axis : x-coordinates of values
|
||||||
|
method : method of interpolation to be passed to interp1d
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
array of length n
|
||||||
|
"""
|
||||||
|
xx = np.linspace(*span(x_axis), len(x_axis))
|
||||||
|
return interp1d(x_axis, values, kind=method)(xx)
|
||||||
0
src/scgenerator/physics/__init__.py
Normal file
0
src/scgenerator/physics/__init__.py
Normal file
962
src/scgenerator/physics/fiber.py
Normal file
962
src/scgenerator/physics/fiber.py
Normal file
@@ -0,0 +1,962 @@
|
|||||||
|
import numpy as np
|
||||||
|
import toml
|
||||||
|
from numpy.fft import fft, ifft
|
||||||
|
from numpy.polynomial.chebyshev import Chebyshev, cheb2poly
|
||||||
|
from scipy.interpolate import interp1d
|
||||||
|
|
||||||
|
from scgenerator.state import _DEBUG
|
||||||
|
|
||||||
|
from .. import io
|
||||||
|
from ..const import hc_model_specific_parameters
|
||||||
|
from ..math import abs2, argclosest, power_fact, u_nm
|
||||||
|
from . import materials as mat
|
||||||
|
from . import units
|
||||||
|
from .units import c, pi
|
||||||
|
|
||||||
|
|
||||||
|
def lambda_for_dispersion():
|
||||||
|
"""Returns a wl vector for dispersion calculation
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
array of wl values
|
||||||
|
"""
|
||||||
|
return np.linspace(190e-9, 3000e-9, 4000)
|
||||||
|
|
||||||
|
|
||||||
|
def is_dynamic_dispersion(params):
|
||||||
|
"""tests if the parameter dictionary implies that the dispersion profile of the fiber changes with z
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
params : dict
|
||||||
|
flattened parameters dict
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
bool : True if dispersion is supposed to change with z
|
||||||
|
"""
|
||||||
|
out = False
|
||||||
|
if "pressure" in params:
|
||||||
|
out |= isinstance(params["pressure"], (tuple, list)) and len(params["pressure"]) == 2
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def HCARF_gap(core_radius, capillary_num, capillary_outer_d):
|
||||||
|
"""computes the gap length between capillaries of a hollow core anti-resonance fiber
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
core_radius : float
|
||||||
|
radius of the core (m) (from cented to edge of a capillary)
|
||||||
|
capillary_num : int
|
||||||
|
number of capillaries
|
||||||
|
capillary_outer_d : float
|
||||||
|
diameter of the capillaries including the wall thickness(m). The core together with the microstructure has a diameter of 2R + 2d
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
gap : float
|
||||||
|
"""
|
||||||
|
return (core_radius + capillary_outer_d / 2) * 2 * np.sin(
|
||||||
|
pi / capillary_num
|
||||||
|
) - capillary_outer_d
|
||||||
|
|
||||||
|
|
||||||
|
def dispersion_parameter(n_eff, lambda_):
|
||||||
|
"""computes the dispersion parameter D from an effective index of refraction n_eff
|
||||||
|
Since computing gradients/derivatives of discrete arrays is not well defined on the boundary, it is
|
||||||
|
advised to chop off the two values on either end of the returned array
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
n_eff : 1D array
|
||||||
|
a wl-dependent index of refraction
|
||||||
|
lambda_ : 1D array
|
||||||
|
the wavelength array (len must match n_eff)
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
D : 1D array
|
||||||
|
wl-dependent dispersion parameter as function of lambda_
|
||||||
|
"""
|
||||||
|
|
||||||
|
return -lambda_ / c * (np.gradient(np.gradient(n_eff, lambda_), lambda_))
|
||||||
|
|
||||||
|
|
||||||
|
def beta2_to_D(beta2, lambda_):
|
||||||
|
"""returns the beta2 parameters corresponding to D(lambda_)"""
|
||||||
|
return -(2 * pi * c) / (lambda_ ** 2) * beta2
|
||||||
|
|
||||||
|
|
||||||
|
def D_to_beta2(D, lambda_):
|
||||||
|
"""returns the D parameter corresponding to beta2(lambda_)"""
|
||||||
|
return -(lambda_ ** 2) / (2 * pi * c) * D
|
||||||
|
|
||||||
|
|
||||||
|
def plasma_dispersion(lambda_, number_density, simple=False):
|
||||||
|
"""computes dispersion (beta2) for constant plasma
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
lambda_ : array-like
|
||||||
|
wavelengths over which to calculate the dispersion
|
||||||
|
number_density : number of ionized atoms /m^3
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
beta2 : ndarray
|
||||||
|
WL-dependent dispersion parameter
|
||||||
|
"""
|
||||||
|
|
||||||
|
e2_me_e0 = 3182.60735 # e^2 /(m_e * epsilon_0)
|
||||||
|
w = units.m(lambda_)
|
||||||
|
if simple:
|
||||||
|
w_pl = number_density * e2_me_e0
|
||||||
|
return -(w_pl ** 2) / (c * w ** 2)
|
||||||
|
|
||||||
|
beta = w / c * np.sqrt(1 - number_density * e2_me_e0 / w ** 2)
|
||||||
|
beta2 = np.gradient(np.gradient(beta, w), w)
|
||||||
|
return beta2
|
||||||
|
|
||||||
|
|
||||||
|
def n_eff_marcatili(lambda_, n_gas_2, core_radius, he_mode=(1, 1)):
|
||||||
|
"""computes the effective refractive index according to the Marcatili model of a capillary
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
lambda_ : ndarray, shape (n, )
|
||||||
|
wavelengths array (m)
|
||||||
|
n_gas_2 : ndarray, shape (n, )
|
||||||
|
refractive index of the gas as function of lambda_
|
||||||
|
core_radius : float
|
||||||
|
inner radius of the capillary (m)
|
||||||
|
he_mode : tuple, shape (2, ), optional
|
||||||
|
n and m value of the HE_nm mode. 1 and 1 corresponds to the fundamental mode
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
n_eff : ndarray, shape (n, )
|
||||||
|
|
||||||
|
Reference
|
||||||
|
---------
|
||||||
|
Marcatili, E., and core_radius. Schmeltzer, 1964, Bell Syst. Tech. J. 43, 1783.
|
||||||
|
"""
|
||||||
|
u = u_nm(*he_mode)
|
||||||
|
|
||||||
|
return np.sqrt(n_gas_2 - (lambda_ * u / (2 * pi * core_radius)) ** 2)
|
||||||
|
|
||||||
|
|
||||||
|
def n_eff_marcatili_adjusted(lambda_, n_gas_2, core_radius, he_mode=(1, 1), fit_parameters=()):
|
||||||
|
"""computes the effective refractive index according to the Marcatili model of a capillary but adjusted at longer wavelengths
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
lambda_ : ndarray, shape (n, )
|
||||||
|
wavelengths array (m)
|
||||||
|
n_gas_2 : ndarray, shape (n, )
|
||||||
|
refractive index of the gas as function of lambda_
|
||||||
|
core_radius : float
|
||||||
|
inner radius of the capillary (m)
|
||||||
|
he_mode : tuple, shape (2, ), optional
|
||||||
|
n and m value of the HE_nm mode. 1 and 1 corresponds to the fundamental mode
|
||||||
|
fit_parameters : tuple, shape (2, ), optional
|
||||||
|
fitting parameters (s, h). See reference for more info
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
n_eff : ndarray, shape (n, )
|
||||||
|
|
||||||
|
Reference
|
||||||
|
----------
|
||||||
|
Köttig, F., et al. "Novel mid-infrared dispersive wave generation in gas-filled PCF by transient ionization-driven changes in dispersion." arXiv preprint arXiv:1701.04843 (2017).
|
||||||
|
"""
|
||||||
|
u = u_nm(*he_mode)
|
||||||
|
|
||||||
|
corrected_radius = effective_core_radius(lambda_, core_radius, *fit_parameters)
|
||||||
|
|
||||||
|
return np.sqrt(n_gas_2 - (lambda_ * u / (2 * pi * corrected_radius)) ** 2)
|
||||||
|
|
||||||
|
|
||||||
|
def n_eff_hasan(
|
||||||
|
lambda_,
|
||||||
|
n_gas_2,
|
||||||
|
core_radius,
|
||||||
|
capillary_num,
|
||||||
|
capillary_thickness,
|
||||||
|
capillary_outer_d=None,
|
||||||
|
capillary_spacing=None,
|
||||||
|
capillary_resonance_strengths=[],
|
||||||
|
capillary_nested=0,
|
||||||
|
):
|
||||||
|
"""computes the effective refractive index of the fundamental mode according to the Hasan model for a anti-resonance fiber
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
lambda_
|
||||||
|
wavelenghs array (m)
|
||||||
|
n_gas_2 : ndarray, shape (n, )
|
||||||
|
squared refractive index of the gas as a function of lambda_
|
||||||
|
core_radius : float
|
||||||
|
radius of the core (m) (from cented to edge of a capillary)
|
||||||
|
capillary_num : int
|
||||||
|
number of capillaries
|
||||||
|
capillary_thickness : float
|
||||||
|
thickness of the capillaries (m)
|
||||||
|
capillary_outer_d : float, optional if capillary_spacing is given
|
||||||
|
diameter of the capillaries including the wall thickness(m). The core together with the microstructure has a diameter of 2R + 2d
|
||||||
|
capillary_spacing : float, optional if capillary_outer_d is given
|
||||||
|
spacing between capillaries (m)
|
||||||
|
capillary_resonance_strengths : list or tuple, optional
|
||||||
|
strengths of the resonance lines. default : []
|
||||||
|
capillary_nested : int, optional
|
||||||
|
number of levels of nested capillaries. default : 0
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
n_eff : ndarray, shape (n, )
|
||||||
|
the effective refractive index as function of wavelength
|
||||||
|
|
||||||
|
Reference
|
||||||
|
----------
|
||||||
|
Hasan, Md Imran, Nail Akhmediev, and Wonkeun Chang. "Empirical formulae for dispersion and effective mode area in hollow-core antiresonant fibers." Journal of Lightwave Technology 36.18 (2018): 4060-4065.
|
||||||
|
"""
|
||||||
|
u = u_nm(1, 1)
|
||||||
|
if capillary_spacing is None:
|
||||||
|
capillary_spacing = HCARF_gap(core_radius, capillary_num, capillary_outer_d)
|
||||||
|
elif capillary_outer_d is None:
|
||||||
|
capillary_outer_d = (2 * core_radius * np.sin(pi / capillary_num) - capillary_spacing) / (
|
||||||
|
1 - np.sin(pi / capillary_num)
|
||||||
|
)
|
||||||
|
Rg = core_radius / capillary_spacing
|
||||||
|
|
||||||
|
f1 = 1.095 * np.exp(0.097041 / Rg)
|
||||||
|
f2 = 0.007584 * capillary_num * np.exp(0.76246 / Rg) - capillary_num * 0.002 + 0.012
|
||||||
|
if capillary_nested > 0:
|
||||||
|
f2 += 0.0045 * np.exp(-4.1589 / (capillary_nested * Rg))
|
||||||
|
|
||||||
|
R_eff = f1 * core_radius * (1 - f2 * lambda_ ** 2 / (core_radius * capillary_thickness))
|
||||||
|
|
||||||
|
n_eff_2 = n_gas_2 - (u * lambda_ / (2 * pi * R_eff)) ** 2
|
||||||
|
|
||||||
|
chi_sil = mat.sellmeier(lambda_, io.load_material_dico("silica"))
|
||||||
|
|
||||||
|
with np.errstate(divide="ignore", invalid="ignore"):
|
||||||
|
for m, strength in enumerate(capillary_resonance_strengths):
|
||||||
|
n_eff_2 += (
|
||||||
|
strength
|
||||||
|
* lambda_ ** 2
|
||||||
|
/ (lambda_ ** 2 - chi_sil * (2 * capillary_thickness / (m + 1)) ** 2)
|
||||||
|
)
|
||||||
|
|
||||||
|
return np.sqrt(n_eff_2)
|
||||||
|
|
||||||
|
|
||||||
|
def A_eff_hasan(core_radius, capillary_num, capillary_spacing):
|
||||||
|
"""computed the effective mode area
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
core_radius : float
|
||||||
|
radius of the core (m) (from cented to edge of a capillary)
|
||||||
|
capillary_num : int
|
||||||
|
number of capillaries
|
||||||
|
capillary_spacing : float
|
||||||
|
spacing between capillaries (m)
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
A_eff : 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)
|
||||||
|
|
||||||
|
|
||||||
|
def HCPCF_find_with_given_ZDW(
|
||||||
|
varying,
|
||||||
|
target,
|
||||||
|
search_range,
|
||||||
|
material_dico,
|
||||||
|
model="marcatili",
|
||||||
|
model_params={},
|
||||||
|
pressure=None,
|
||||||
|
temperature=None,
|
||||||
|
ideal=False,
|
||||||
|
):
|
||||||
|
"""finds the parameters (pressure or temperature) to yield the target ZDW. assign the string value 'vary' to the parameter
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
varying : str {"pressure", "temperature"}
|
||||||
|
which parameter to vary
|
||||||
|
target : float
|
||||||
|
the ZDW target, in m
|
||||||
|
search_range : array, shape (2,)
|
||||||
|
(min, max) of the search range
|
||||||
|
other parameters : see HCPCF_dispersion. Pressure or temperature is used as initial value if it is varying
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
the parameter that satisfies the ZDW
|
||||||
|
"""
|
||||||
|
from scipy import optimize
|
||||||
|
|
||||||
|
l_search = [120e-9, 6000e-9]
|
||||||
|
#
|
||||||
|
fixed = [material_dico, model, model_params, ideal]
|
||||||
|
|
||||||
|
if varying == "pressure":
|
||||||
|
fixed.append(temperature)
|
||||||
|
x0 = 1e5 if pressure is None else pressure
|
||||||
|
|
||||||
|
def zdw(x, *args):
|
||||||
|
current_ZDW = HCPF_ZDW(
|
||||||
|
l_search,
|
||||||
|
args[0],
|
||||||
|
model=args[1],
|
||||||
|
model_params=args[2],
|
||||||
|
pressure=x,
|
||||||
|
temperature=args[4],
|
||||||
|
ideal=args[3],
|
||||||
|
)
|
||||||
|
out = current_ZDW - target
|
||||||
|
return out
|
||||||
|
|
||||||
|
elif varying == "temperature":
|
||||||
|
fixed.append(pressure)
|
||||||
|
x0 = 273.15 if temperature is None else temperature
|
||||||
|
|
||||||
|
def zdw(x, *args):
|
||||||
|
current_ZDW = HCPF_ZDW(
|
||||||
|
l_search,
|
||||||
|
args[0],
|
||||||
|
model=args[1],
|
||||||
|
model_params=args[2],
|
||||||
|
pressure=args[4],
|
||||||
|
temperature=x,
|
||||||
|
ideal=args[3],
|
||||||
|
)
|
||||||
|
out = current_ZDW - target
|
||||||
|
return out
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise AttributeError(f"'varying' arg must be 'pressure' or 'temperature', not {varying}")
|
||||||
|
|
||||||
|
optimized = optimize.root_scalar(
|
||||||
|
zdw, x0=x0, args=tuple(fixed), method="brentq", bracket=search_range
|
||||||
|
)
|
||||||
|
|
||||||
|
return optimized.root
|
||||||
|
|
||||||
|
|
||||||
|
def HCPF_ZDW(
|
||||||
|
search_range,
|
||||||
|
material_dico,
|
||||||
|
model="marcatili",
|
||||||
|
model_params={},
|
||||||
|
pressure=None,
|
||||||
|
temperature=None,
|
||||||
|
ideal=False,
|
||||||
|
max_iter=10,
|
||||||
|
threshold=1e-36,
|
||||||
|
):
|
||||||
|
"""finds one Zero Dispersion Wavelength (ZDW) of a given HC-PCF fiber
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
see HCPCF_dispersion for description of most arguments
|
||||||
|
max_iter : float
|
||||||
|
How many iterations are allowed at most to reach the threashold
|
||||||
|
threshold : float
|
||||||
|
upper bound of what counts as beta2 == 0 (in si units)
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
float:
|
||||||
|
the ZDW in m
|
||||||
|
"""
|
||||||
|
prev_find = np.inf
|
||||||
|
l = np.linspace(*search_range, 50)
|
||||||
|
|
||||||
|
core_radius = model_params["core_radius"]
|
||||||
|
|
||||||
|
zdw_ind = 0
|
||||||
|
for i in range(max_iter):
|
||||||
|
beta2 = HCPCF_dispersion(
|
||||||
|
l,
|
||||||
|
material_dico,
|
||||||
|
model=model,
|
||||||
|
model_params=model_params,
|
||||||
|
pressure=pressure,
|
||||||
|
temperature=temperature,
|
||||||
|
ideal=ideal,
|
||||||
|
)
|
||||||
|
zdw_ind = argclosest(beta2, 0)
|
||||||
|
if beta2[zdw_ind] < threshold:
|
||||||
|
break
|
||||||
|
elif beta2[zdw_ind] < prev_find:
|
||||||
|
l = np.linspace(
|
||||||
|
l[zdw_ind] - (100 / (i + 1)) * 1e-9, l[zdw_ind] + (100 / (i + 1)) * 1e-9, 50
|
||||||
|
)
|
||||||
|
prev_find = beta2[zdw_ind]
|
||||||
|
else:
|
||||||
|
raise RuntimeError(
|
||||||
|
f"Could not find a ZDW with parameters {1e6*core_radius} um, {1e-5 * pressure} bar, {temperature} K."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
print(f"Could not get to threshold in {max_iter} iterations")
|
||||||
|
|
||||||
|
return l[zdw_ind]
|
||||||
|
|
||||||
|
|
||||||
|
def beta2(w, n_eff):
|
||||||
|
"""computes the dispersion parameter beta2 according to the effective refractive index of the fiber and the frequency range
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
w : ndarray, shape (n, )
|
||||||
|
angular frequencies over which to calculate the dispersion
|
||||||
|
n_eff : ndarray_ shape (n, )
|
||||||
|
effective refractive index of the fiber computed with one of the n_eff_* methods
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
beta2 : ndarray, shape (n, )
|
||||||
|
"""
|
||||||
|
return np.gradient(np.gradient(n_eff * w / c, w), w)
|
||||||
|
|
||||||
|
|
||||||
|
def HCPCF_dispersion(
|
||||||
|
lambda_,
|
||||||
|
material_dico=None,
|
||||||
|
model="marcatili",
|
||||||
|
model_params={},
|
||||||
|
pressure=None,
|
||||||
|
temperature=None,
|
||||||
|
ideal=False,
|
||||||
|
):
|
||||||
|
"""returns the dispersion profile (beta_2) of a hollow-core photonic crystal fiber.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
lambda_ : ndarray, shape (n, )
|
||||||
|
wavelengths over which to calculate the dispersion
|
||||||
|
material_dico : dict
|
||||||
|
material dictionary respecting standard format explained in FIXME
|
||||||
|
model : string {"marcatili", "marcatili_adjusted", "hasan"}
|
||||||
|
which model of effective refractive index to use
|
||||||
|
model_params : tuple
|
||||||
|
to be cast to the function in charge of computing the effective index of the fiber. Every n_eff_* function has a signature
|
||||||
|
n_eff_(lambda_, n_gas_2, radius, *args) and model_params corresponds to args
|
||||||
|
temperature : float
|
||||||
|
Temperature of the material
|
||||||
|
pressure : float
|
||||||
|
constant pressure
|
||||||
|
FIXME tupple : a pressure gradient from pressure[0] to pressure[1] is computed
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
out : 1D array
|
||||||
|
beta2 as function of wavelength
|
||||||
|
"""
|
||||||
|
|
||||||
|
w = units.m(lambda_)
|
||||||
|
if material_dico is None:
|
||||||
|
n_gas_2 = np.ones_like(lambda_)
|
||||||
|
else:
|
||||||
|
if ideal:
|
||||||
|
n_gas_2 = mat.sellmeier(lambda_, material_dico, pressure, temperature) + 1
|
||||||
|
else:
|
||||||
|
N_1 = mat.number_density_van_der_waals(
|
||||||
|
pressure=pressure, temperature=temperature, material_dico=material_dico
|
||||||
|
)
|
||||||
|
N_0 = mat.number_density_van_der_waals(material_dico=material_dico)
|
||||||
|
n_gas_2 = mat.sellmeier(lambda_, material_dico) * N_1 / N_0 + 1
|
||||||
|
|
||||||
|
n_eff_func = dict(
|
||||||
|
marcatili=n_eff_marcatili, marcatili_adjusted=n_eff_marcatili_adjusted, hasan=n_eff_hasan
|
||||||
|
)[model]
|
||||||
|
n_eff = n_eff_func(lambda_, n_gas_2, **model_params)
|
||||||
|
|
||||||
|
return beta2(w, n_eff)
|
||||||
|
|
||||||
|
|
||||||
|
def dynamic_HCPCF_dispersion(lambda_, params, material_dico, deg):
|
||||||
|
"""returns functions for beta2 coefficients and gamma instead of static values
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
lambda_ : wavelength array
|
||||||
|
params : dict
|
||||||
|
flattened parameter dictionary
|
||||||
|
material_dico : dict
|
||||||
|
material dictionary (see README for details)
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
beta2_coef : func(r), r is the relative position in the fiber
|
||||||
|
a function that returns an array of coefficients as function of the relative position in the fiber
|
||||||
|
to be used in disp_op
|
||||||
|
gamma : func(r), r is the relative position in the fiber
|
||||||
|
a function that returns a float corresponding to the nonlinear parameter at the relative position
|
||||||
|
in the fiber
|
||||||
|
"""
|
||||||
|
|
||||||
|
# store values because storing functions acts weird with dict
|
||||||
|
pressure_values = params["pressure"]
|
||||||
|
a = params["core_radius"]
|
||||||
|
fiber_model = params["fiber_model"]
|
||||||
|
model_params = {k: params[k] for k in hc_model_specific_parameters[fiber_model]}
|
||||||
|
temp = params["temperature"]
|
||||||
|
ideal_gas = params["ideal_gas"]
|
||||||
|
w0 = params["w0"]
|
||||||
|
interp_range = params["interp_range"]
|
||||||
|
|
||||||
|
A_eff = 1.5 * a ** 2
|
||||||
|
|
||||||
|
# defining function instead of storing every possilble value
|
||||||
|
pressure = lambda r: mat.pressure_from_gradient(r, *pressure_values)
|
||||||
|
beta2 = lambda r: HCPCF_dispersion(
|
||||||
|
lambda_, a, material_dico, fiber_model, model_params, pressure(r), temp, ideal_gas
|
||||||
|
)
|
||||||
|
|
||||||
|
n2 = lambda r: mat.non_linear_refractive_index(material_dico, pressure(r), temp)
|
||||||
|
ratio_range = np.linspace(0, 1, 256)
|
||||||
|
|
||||||
|
gamma_grid = np.array([n2(r) * w0 / (A_eff * c) for r in ratio_range])
|
||||||
|
gamma_interp = interp1d(ratio_range, gamma_grid)
|
||||||
|
|
||||||
|
beta2_grid = np.array(
|
||||||
|
[dispersion_coefficients(lambda_, beta2(r), w0, interp_range, deg) for r in ratio_range]
|
||||||
|
)
|
||||||
|
beta2_interp = [
|
||||||
|
interp1d(ratio_range, beta2_grid[:, i], assume_sorted=True) for i in range(deg + 1)
|
||||||
|
]
|
||||||
|
|
||||||
|
def beta2_func(r):
|
||||||
|
return [beta2_interp[i](r)[()] for i in range(deg + 1)]
|
||||||
|
|
||||||
|
def gamma_func(r):
|
||||||
|
return gamma_interp(r)[()]
|
||||||
|
|
||||||
|
return beta2_func, gamma_func
|
||||||
|
|
||||||
|
|
||||||
|
def PCF_dispersion(lambda_, pitch, ratio_d, w0=None):
|
||||||
|
"""
|
||||||
|
semi-analytical computation of the dispersion profile of a triangular Index-guiding PCF
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
lambda_ : 1D array-like
|
||||||
|
wavelengths over which to calculate the dispersion
|
||||||
|
pitch : float
|
||||||
|
distance between air holes in m
|
||||||
|
ratio_d : float
|
||||||
|
ratio diameter of hole / pitch
|
||||||
|
w0 : float, optional
|
||||||
|
pump angular frequency. If given, the gamma value is also returned in adition to the GVD. default : None
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
beta2 : 1D array
|
||||||
|
Dispersion parameter as function of wavelength
|
||||||
|
gamma : float
|
||||||
|
non-linear coefficient
|
||||||
|
|
||||||
|
Reference
|
||||||
|
---------
|
||||||
|
Formulas and values are from Saitoh K and Koshiba M, "Empirical relations for simple design of photonic crystal fibers" (2005)
|
||||||
|
|
||||||
|
"""
|
||||||
|
# Check validity
|
||||||
|
if ratio_d < 0.2 or ratio_d > 0.8:
|
||||||
|
print("WARNING : Fitted formula valid only for pitch ratio between 0.2 and 0.8")
|
||||||
|
|
||||||
|
n_co = 1.45
|
||||||
|
a_eff = pitch / np.sqrt(3)
|
||||||
|
pi2a = 2 * pi * a_eff
|
||||||
|
|
||||||
|
ratio_l = lambda_ / pitch
|
||||||
|
|
||||||
|
# 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])
|
||||||
|
ai2 = np.array([-10.43248, 47.41496, 18.96849, 1.93229])
|
||||||
|
ai3 = np.array([8.22992, -437.50962, -42.4318, 3.89])
|
||||||
|
bi1 = np.array([5, 1.8, 1.7, -0.84])
|
||||||
|
bi2 = np.array([7, 7.32, 10, 1.02])
|
||||||
|
bi3 = np.array([9, 22.8, 14, 13.4])
|
||||||
|
ci0 = np.array([-0.0973, 0.53193, 0.24876, 5.29801])
|
||||||
|
ci1 = np.array([-16.70566, 6.70858, 2.72423, 0.05142])
|
||||||
|
ci2 = np.array([67.13845, 52.04855, 13.28649, -5.18302])
|
||||||
|
ci3 = np.array([-50.25518, -540.66947, -36.80372, 2.7641])
|
||||||
|
di1 = np.array([7, 1.49, 3.85, -2])
|
||||||
|
di2 = np.array([9, 6.58, 10, 0.41])
|
||||||
|
di3 = np.array([10, 24.8, 15, 6])
|
||||||
|
|
||||||
|
A = ai0 + ai1 * ratio_d ** bi1 + ai2 * ratio_d ** bi2 + ai3 * ratio_d ** bi3
|
||||||
|
B = ci0 + ci1 * ratio_d ** di1 + ci2 * ratio_d ** di2 + ci3 * ratio_d ** di3
|
||||||
|
|
||||||
|
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))
|
||||||
|
|
||||||
|
n_FSM2 = 1.45 ** 2 - (lambda_ * V / (pi2a)) ** 2
|
||||||
|
n_eff2 = (lambda_ * W / (pi2a)) ** 2 + n_FSM2
|
||||||
|
n_eff = np.sqrt(n_eff2)
|
||||||
|
|
||||||
|
D_wave_guide = dispersion_parameter(n_eff, lambda_)
|
||||||
|
|
||||||
|
material_dico = io.load_material_dico("silica")
|
||||||
|
chi_mat = mat.sellmeier(lambda_, material_dico)
|
||||||
|
D_mat = dispersion_parameter(np.sqrt(chi_mat + 1), lambda_)
|
||||||
|
|
||||||
|
# material index of refraction (Sellmeier formula)
|
||||||
|
|
||||||
|
D = D_wave_guide + D_mat
|
||||||
|
|
||||||
|
beta2 = D_to_beta2(D, lambda_)
|
||||||
|
|
||||||
|
if w0 is None:
|
||||||
|
return beta2
|
||||||
|
|
||||||
|
else:
|
||||||
|
# effective mode field area (koshiba2004)
|
||||||
|
V_eff = pi2a / lambda_ * np.sqrt(n_co ** 2 - n_FSM2)
|
||||||
|
w_eff = a_eff * (0.65 + 1.619 / V_eff ** 1.5 + 2.879 / V_eff ** 6)
|
||||||
|
A_eff = interp1d(lambda_, w_eff, kind="linear")(units.m.inv(w0)) ** 2 * pi
|
||||||
|
|
||||||
|
n2 = 2.6e-20 # FIXME
|
||||||
|
gamma = n2 * w0 / (A_eff * c)
|
||||||
|
|
||||||
|
return beta2, gamma
|
||||||
|
|
||||||
|
|
||||||
|
def dispersion_central(fiber_model, params, deg=8):
|
||||||
|
"""dispatch function depending on what type of fiber is used
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
fiber_model : str {"PCF", "HCPCF"}
|
||||||
|
describes the type of fiber
|
||||||
|
- PCF : triangular Index-guiding photonic crystal fiber
|
||||||
|
- HCPCF : hollow core fiber (filled with gas, or not)
|
||||||
|
params : dict
|
||||||
|
parameter dictionary as in `parameters.toml`
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
beta2_coef : 1D array of size deg
|
||||||
|
beta coefficients to be used in disp_op
|
||||||
|
gamma : float
|
||||||
|
nonlinear parameter
|
||||||
|
"""
|
||||||
|
lambda_ = lambda_for_dispersion()
|
||||||
|
beta2 = np.zeros_like(lambda_)
|
||||||
|
|
||||||
|
fiber_model = fiber_model.lower()
|
||||||
|
|
||||||
|
if fiber_model == "pcf":
|
||||||
|
beta2, gamma = PCF_dispersion(
|
||||||
|
lambda_,
|
||||||
|
params["pitch"],
|
||||||
|
params["pitch_ratio"],
|
||||||
|
w0=params["w0"],
|
||||||
|
)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Load material info
|
||||||
|
gas_name = params["gas_name"]
|
||||||
|
|
||||||
|
if gas_name == "vacuum":
|
||||||
|
material_dico = None
|
||||||
|
else:
|
||||||
|
material_dico = toml.loads(io.Paths.gets("gas"))[gas_name]
|
||||||
|
|
||||||
|
# compute dispersion
|
||||||
|
if params.get("dynamic_dispersion", False):
|
||||||
|
return dynamic_HCPCF_dispersion(lambda_, params, material_dico, deg)
|
||||||
|
else:
|
||||||
|
|
||||||
|
# actually compute the dispersion
|
||||||
|
|
||||||
|
beta2 = HCPCF_dispersion(
|
||||||
|
lambda_,
|
||||||
|
material_dico,
|
||||||
|
fiber_model,
|
||||||
|
{k: params[k] for k in hc_model_specific_parameters[fiber_model]},
|
||||||
|
params["pressure"],
|
||||||
|
params["temperature"],
|
||||||
|
params["ideal_gas"],
|
||||||
|
)
|
||||||
|
|
||||||
|
if material_dico is not None:
|
||||||
|
A_eff = 1.5 * params["core_radius"] ** 2
|
||||||
|
n2 = mat.non_linear_refractive_index(
|
||||||
|
material_dico, params["pressure"], params["temperature"]
|
||||||
|
)
|
||||||
|
gamma = n2 * params["w0"] / (A_eff * c)
|
||||||
|
else:
|
||||||
|
gamma = 0
|
||||||
|
|
||||||
|
# add plasma if wanted
|
||||||
|
if params["plasma_density"] > 0:
|
||||||
|
beta2 += plasma_dispersion(lambda_, params["plasma_density"])
|
||||||
|
|
||||||
|
beta2_coef = dispersion_coefficients(lambda_, beta2, params["w0"], params["interp_range"], deg)
|
||||||
|
|
||||||
|
return beta2_coef, gamma
|
||||||
|
|
||||||
|
|
||||||
|
def dispersion_coefficients(lambda_, beta2, w0, interp_range=None, deg=8):
|
||||||
|
"""Computes the taylor expansion of beta2 to be used in dispersion_op
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
lambda_ : 1D array
|
||||||
|
wavelength
|
||||||
|
beta2 : 1D array
|
||||||
|
beta2 as function of lambda_
|
||||||
|
w0 : float
|
||||||
|
pump angular frequency
|
||||||
|
interp_range : slice-like
|
||||||
|
index-style specifying wl range over which to fit to get beta2 coefficients
|
||||||
|
deg : int
|
||||||
|
degree of polynomial fit. Will return deg+1 coefficients
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
beta2_coef : 1D array
|
||||||
|
Taylor coefficients in decreasing order
|
||||||
|
"""
|
||||||
|
|
||||||
|
if interp_range is None:
|
||||||
|
r = slice(2, -2)
|
||||||
|
else:
|
||||||
|
# 2 discrete gradients are computed before getting to
|
||||||
|
# beta2, so we need to make sure coefficients are not affected
|
||||||
|
# by edge effects
|
||||||
|
r = (lambda_ > max(lambda_[2], interp_range[0])) & (
|
||||||
|
lambda_ < min(lambda_[-2], interp_range[1])
|
||||||
|
)
|
||||||
|
|
||||||
|
# we get the beta2 Taylor coeffiecients by making a fit around w0
|
||||||
|
w_c = units.m(lambda_) - w0
|
||||||
|
fit = Chebyshev.fit(w_c[r], beta2[r], deg)
|
||||||
|
beta2_coef = cheb2poly(fit.convert().coef) * np.cumprod([1] + list(range(1, deg + 1)))
|
||||||
|
|
||||||
|
return beta2_coef
|
||||||
|
|
||||||
|
|
||||||
|
def delayed_raman_t(t, raman_type="stolen"):
|
||||||
|
"""
|
||||||
|
computes the unnormalized temporal Raman response function applied to the array t
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
t : 1D array
|
||||||
|
time in the co-moving frame of reference
|
||||||
|
raman_type : str {"stolen", "agrawal", "measured"}
|
||||||
|
indicates what type of Raman effect modelization to use
|
||||||
|
default : "stolen"
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
hr_arr : 1D array
|
||||||
|
temporal response function
|
||||||
|
"""
|
||||||
|
tau1 = 12.2e-15
|
||||||
|
tau2 = 32e-15
|
||||||
|
t_ = t - t[0]
|
||||||
|
t = t_
|
||||||
|
if raman_type == "stolen":
|
||||||
|
hr_arr = (tau1 / tau2 ** 2 + 1 / tau1) * np.exp(-t_ / tau2) * np.sin(t_ / tau1)
|
||||||
|
|
||||||
|
elif raman_type == "agrawal":
|
||||||
|
taub = 96e-15
|
||||||
|
h_a = (tau1 / tau2 ** 2 + 1 / tau1) * np.exp(-t_ / tau2) * np.sin(t_ / tau1)
|
||||||
|
h_b = (2 * taub - t_) / taub ** 2 * np.exp(-t_ / taub)
|
||||||
|
hr_arr = 0.79 * h_a + 0.21 * h_b
|
||||||
|
|
||||||
|
elif raman_type == "measured":
|
||||||
|
try:
|
||||||
|
path = io.Paths.get("hr_t")
|
||||||
|
loaded = np.load(path)
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(
|
||||||
|
f"Not able to find the measured Raman response function. Going with agrawal model"
|
||||||
|
)
|
||||||
|
return delayed_raman_t(t, raman_type="agrawal")
|
||||||
|
|
||||||
|
t_stored, hr_arr_stored = loaded["t"], loaded["hr_arr"]
|
||||||
|
hr_arr = interp1d(t_stored, hr_arr_stored, bounds_error=False, fill_value=0)(t)
|
||||||
|
else:
|
||||||
|
print("invalid raman response function, aborting")
|
||||||
|
quit()
|
||||||
|
|
||||||
|
return hr_arr
|
||||||
|
|
||||||
|
|
||||||
|
def delayed_raman_w(t, dt, raman_type="stolen"):
|
||||||
|
"""returns the delayed raman response function as function of w
|
||||||
|
see delayed_raman_t for detailes"""
|
||||||
|
return fft(delayed_raman_t(t, raman_type)) * dt
|
||||||
|
|
||||||
|
|
||||||
|
def create_non_linear_op(behaviors, w_c, w0, gamma, raman_type="stolen", f_r=None, hr_w=None):
|
||||||
|
"""
|
||||||
|
Creates a non-linear operator with the desired features
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
behaviors : list of str
|
||||||
|
behaviors wanted
|
||||||
|
w_c : 1d array
|
||||||
|
symetric frequency array generated by scgenerator.initialize.wspace
|
||||||
|
w0 : float
|
||||||
|
pump angular frenquency
|
||||||
|
gamma : float
|
||||||
|
nonlinear parameter
|
||||||
|
raman_type : str, optional
|
||||||
|
name of the raman response function model. default : "stolen"
|
||||||
|
hr_w : 1d array, optional unless "raman" in behaviors
|
||||||
|
pre-calculated frequency-dependent delayed raman response function
|
||||||
|
f_r : float, optional
|
||||||
|
overwrite fractional contribution of the delayed raman effect. default : None
|
||||||
|
|
||||||
|
returns
|
||||||
|
-------
|
||||||
|
func
|
||||||
|
a function to be passed to RK4IP which takes a spectrum as input and returns
|
||||||
|
a new spectrum modified with the non-linear interactions.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Compute raman response function if necessary
|
||||||
|
if "raman" in behaviors:
|
||||||
|
if "hr_w" == None:
|
||||||
|
raise TypeError("freq-dependent Raman response must be give")
|
||||||
|
else:
|
||||||
|
if f_r is None:
|
||||||
|
if raman_type in ["stolen", "measured"]:
|
||||||
|
f_r = 0.18
|
||||||
|
elif raman_type == "agrawal":
|
||||||
|
f_r = 0.245
|
||||||
|
|
||||||
|
# Define the non linear operator
|
||||||
|
def N_func(spectrum, r=0):
|
||||||
|
field = ifft(spectrum)
|
||||||
|
|
||||||
|
ss_part = w_c / w0 if "ss" in behaviors else 0
|
||||||
|
spm_part = (1 - f_r) * abs2(field) if "spm" in behaviors else 0
|
||||||
|
raman_part = f_r * ifft(hr_w * fft(abs2(field))) if "raman" in behaviors else 0
|
||||||
|
raman_noise_part = 1j * 0
|
||||||
|
if isinstance(gamma, (float, int)):
|
||||||
|
return (
|
||||||
|
-1j
|
||||||
|
* gamma
|
||||||
|
* (1 + ss_part)
|
||||||
|
* fft(field * (spm_part + raman_part) + raman_noise_part)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return (
|
||||||
|
-1j
|
||||||
|
* gamma(r)
|
||||||
|
* (1 + ss_part)
|
||||||
|
* fft(field * (spm_part + raman_part) + raman_noise_part)
|
||||||
|
)
|
||||||
|
|
||||||
|
return N_func
|
||||||
|
|
||||||
|
|
||||||
|
def fast_dispersion_op(w_c, beta_arr, power_fact, where=slice(None)):
|
||||||
|
"""
|
||||||
|
dispersive operator
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
w_c : 1d array
|
||||||
|
angular frequencies centered around 0
|
||||||
|
beta_arr : 1d array
|
||||||
|
beta coefficients returned by scgenerator.physics.fiber.dispersion_coefficients
|
||||||
|
power_fact : list of arrays of len == len(w_c)
|
||||||
|
precomputed values for w_c^k / k!
|
||||||
|
where : slice-like
|
||||||
|
indices over which to apply the operator, otherwise 0
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
array of len == len(w_c)
|
||||||
|
dispersive component
|
||||||
|
"""
|
||||||
|
|
||||||
|
dispersion = np.zeros_like(w_c)
|
||||||
|
|
||||||
|
for k, beta in reversed(list(enumerate(beta_arr))):
|
||||||
|
dispersion = dispersion + beta * power_fact[k]
|
||||||
|
|
||||||
|
out = np.zeros_like(dispersion)
|
||||||
|
out[where] = dispersion[where]
|
||||||
|
|
||||||
|
return -1j * out
|
||||||
|
|
||||||
|
|
||||||
|
def dispersion_op(w_c, beta_arr, where=None):
|
||||||
|
"""
|
||||||
|
dispersive operator
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
w_c : 1d array
|
||||||
|
angular frequencies centered around 0
|
||||||
|
beta_arr : 1d array
|
||||||
|
beta coefficients returned by scgenerator.physics.fiber.dispersion_coefficients
|
||||||
|
where : indices over which to apply the operatory, otherwise 0
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
disp_arr : dispersive component as an array of len = len(w_c)
|
||||||
|
"""
|
||||||
|
|
||||||
|
dispersion = np.zeros_like(w_c)
|
||||||
|
|
||||||
|
for k, beta in reversed(list(enumerate(beta_arr))):
|
||||||
|
dispersion = dispersion + beta * power_fact(w_c, k + 2)
|
||||||
|
|
||||||
|
out = np.zeros_like(dispersion)
|
||||||
|
out[where] = dispersion[where]
|
||||||
|
|
||||||
|
return -1j * out
|
||||||
|
|
||||||
|
|
||||||
|
def _get_radius(radius_param, lambda_=None):
|
||||||
|
if isinstance(radius_param, tuple) and lambda_ is not None:
|
||||||
|
return effective_core_radius(lambda_, *radius_param)
|
||||||
|
else:
|
||||||
|
return radius_param
|
||||||
|
|
||||||
|
|
||||||
|
def effective_core_radius(lambda_, core_radius, s=0.08, h=200e-9):
|
||||||
|
"""return the variable core radius according to Eq. S2.2 from Köttig2017
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
lambda_ : ndarray, shape (n, )
|
||||||
|
array of wl over which to calculate the effective core radius
|
||||||
|
core_radius : float
|
||||||
|
physical core radius in m
|
||||||
|
s : float
|
||||||
|
s parameter from the equation S2.2
|
||||||
|
h : float
|
||||||
|
wall thickness in m
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
effective_core_radius : ndarray, shape (n, )
|
||||||
|
"""
|
||||||
|
return core_radius / (1 + s * lambda_ ** 2 / (core_radius * h))
|
||||||
|
|
||||||
|
|
||||||
|
def effective_radius_HCARF(core_radius, t, f1, f2, lambda_):
|
||||||
|
"""eq. 3 in Hasan 2018"""
|
||||||
|
return f1 * core_radius * (1 - f2 * lambda_ ** 2 / (core_radius * t))
|
||||||
167
src/scgenerator/physics/materials.py
Normal file
167
src/scgenerator/physics/materials.py
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from .. import state
|
||||||
|
from . import units
|
||||||
|
from .units import NA, c, kB
|
||||||
|
|
||||||
|
|
||||||
|
def pressure_from_gradient(ratio, p0, p1):
|
||||||
|
"""returns the pressure as function of distance with eq. 20 in Markos et al. (2017)
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
ratio : relative position in the fiber (0 = start, 1 = end)
|
||||||
|
p0 : pressure at the start
|
||||||
|
p1 : pressure at the end
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
the pressure (float)
|
||||||
|
"""
|
||||||
|
return np.sqrt(p0 ** 2 - ratio * (p0 ** 2 - p1 ** 2))
|
||||||
|
|
||||||
|
|
||||||
|
def number_density_van_der_waals(
|
||||||
|
a=None, b=None, pressure=None, temperature=None, material_dico=None
|
||||||
|
):
|
||||||
|
"""returns the number density of a gas
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
P : pressure
|
||||||
|
T : temperature
|
||||||
|
for pressure and temperature, the default
|
||||||
|
a : Van der Waals a coefficient
|
||||||
|
b : Van der Waals b coefficient
|
||||||
|
material_dico : optional. If passed, will compute the number density at given reference values found in material_dico
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
the numbers density (/m^3)
|
||||||
|
Raises
|
||||||
|
----------
|
||||||
|
ValueError : Since the Van der Waals equation is a cubic one, there could be more than one real, positive solution
|
||||||
|
"""
|
||||||
|
if pressure == 0:
|
||||||
|
return 0
|
||||||
|
if material_dico is not None:
|
||||||
|
a = material_dico.get("a", 0) if a is None else a
|
||||||
|
b = material_dico.get("b", 0) if b is None else b
|
||||||
|
pressure = material_dico["sellmeier"].get("P0", 101325) if pressure is None else pressure
|
||||||
|
temperature = (
|
||||||
|
material_dico["sellmeier"].get("t0", 273.15) if temperature is None else temperature
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
a = 0 if a is None else a
|
||||||
|
b = 0 if b is None else b
|
||||||
|
pressure = 101325 if pressure is None else pressure
|
||||||
|
temperature = 273.15 if temperature is None else temperature
|
||||||
|
|
||||||
|
ap = a / NA ** 2
|
||||||
|
bp = b / NA
|
||||||
|
|
||||||
|
# setup van der Waals equation for the number density
|
||||||
|
p3 = -ap * bp
|
||||||
|
p2 = ap
|
||||||
|
p1 = -(pressure * bp + kB * temperature)
|
||||||
|
p0 = pressure
|
||||||
|
|
||||||
|
# filter out unwanted matches
|
||||||
|
roots = np.roots([p3, p2, p1, p0])
|
||||||
|
roots = roots[np.isreal(roots)].real
|
||||||
|
roots = roots[roots > 0]
|
||||||
|
if len(roots) != 1:
|
||||||
|
s = f"Van der Waals eq with parameters P={pressure}, T={temperature}, a={a}, b={b}"
|
||||||
|
s += f"\nThere is more than one possible number density : {roots}."
|
||||||
|
s += f"\n{np.min(roots)} was returned"
|
||||||
|
state.CurrentLogger.log(s)
|
||||||
|
return np.min(roots)
|
||||||
|
|
||||||
|
|
||||||
|
def sellmeier(lambda_, material_dico, pressure=None, temperature=None):
|
||||||
|
"""reads a file containing the Sellmeier values corresponding to the choses material and returns the real susceptibility
|
||||||
|
pressure and temperature adjustments are made according to ideal gas law.
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
lambda_ : wl vector over which to compute the refractive index
|
||||||
|
material_dico : material dictionary as explained in scgenerator.io.load_material_dico
|
||||||
|
pressure : pressure in mbar if material is a gas. Can be a constant or a tupple if a presure gradient is considered
|
||||||
|
temperature : temperature of the gas in Kelvin
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
an array n(lambda_)^2 - 1
|
||||||
|
"""
|
||||||
|
WL_THRESHOLD = 8.285e-6
|
||||||
|
temp_l = lambda_[lambda_ < WL_THRESHOLD]
|
||||||
|
kind = 1
|
||||||
|
|
||||||
|
B = material_dico["sellmeier"]["B"]
|
||||||
|
C = material_dico["sellmeier"]["C"]
|
||||||
|
const = material_dico["sellmeier"].get("const", 0)
|
||||||
|
P0 = material_dico["sellmeier"].get("P0", 1e5)
|
||||||
|
t0 = material_dico["sellmeier"].get("t0", 273.15)
|
||||||
|
kind = material_dico["sellmeier"].get("kind", 1)
|
||||||
|
|
||||||
|
# Sellmeier equation
|
||||||
|
chi = np.zeros_like(lambda_) # = n^2 - 1
|
||||||
|
if kind == 1:
|
||||||
|
for b, c in zip(B, C):
|
||||||
|
chi[lambda_ < WL_THRESHOLD] += temp_l ** 2 * b / (temp_l ** 2 - c)
|
||||||
|
elif kind == 2: # gives n-1
|
||||||
|
for b, c in zip(B, C):
|
||||||
|
chi[lambda_ < WL_THRESHOLD] += b / (c - 1 / temp_l ** 2)
|
||||||
|
chi += const
|
||||||
|
chi = (chi + 1) ** 2 - 1
|
||||||
|
else:
|
||||||
|
raise ValueError(f"kind {kind} is not recognized.")
|
||||||
|
|
||||||
|
if temperature is not None:
|
||||||
|
chi *= t0 / temperature
|
||||||
|
|
||||||
|
if pressure is not None:
|
||||||
|
chi *= pressure / P0
|
||||||
|
|
||||||
|
return chi
|
||||||
|
|
||||||
|
|
||||||
|
def delta_gas(w, material_dico):
|
||||||
|
"""returns the value delta_t (eq. 24 in Markos(2017))
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
w : angular frequency array
|
||||||
|
material_dico : material dictionary as explained in scgenerator.io.load_material_dico
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
delta_t
|
||||||
|
since 2 gradients are computed, it is recommended to exclude the 2 extremum values
|
||||||
|
"""
|
||||||
|
chi = sellmeier(units.m.inv(w), material_dico)
|
||||||
|
N0 = number_density_van_der_waals(material_dico=material_dico)
|
||||||
|
|
||||||
|
dchi_dw = np.gradient(chi, w)
|
||||||
|
return 1 / (N0 * c) * (dchi_dw + w / 2 * np.gradient(dchi_dw, w))
|
||||||
|
|
||||||
|
|
||||||
|
def non_linear_refractive_index(material_dico, pressure=None, temperature=None):
|
||||||
|
"""returns the non linear refractive index n2 adjusted for pressure and temperature
|
||||||
|
NOTE : so far, there is no adjustment made for wavelength
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
lambda_ : wavelength array
|
||||||
|
material_dico :
|
||||||
|
pressure : pressure in Pa
|
||||||
|
temperature : temperature in Kelvin
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
n2
|
||||||
|
"""
|
||||||
|
|
||||||
|
n2_ref = material_dico["kerr"]["n2"]
|
||||||
|
|
||||||
|
# if pressure and/or temperature are specified, adjustment is made according to number density ratio
|
||||||
|
if pressure is not None or temperature is not None:
|
||||||
|
N0 = number_density_van_der_waals(material_dico=material_dico)
|
||||||
|
N = number_density_van_der_waals(
|
||||||
|
pressure=pressure, temperature=temperature, material_dico=material_dico
|
||||||
|
)
|
||||||
|
ratio = N / N0
|
||||||
|
else:
|
||||||
|
ratio = 1
|
||||||
|
|
||||||
|
return ratio * n2_ref
|
||||||
795
src/scgenerator/physics/pulse.py
Normal file
795
src/scgenerator/physics/pulse.py
Normal file
@@ -0,0 +1,795 @@
|
|||||||
|
"""
|
||||||
|
This files incluedes funcitons used by the scgenerator module to compute properties of pulses.
|
||||||
|
This include computing initial pulse shape and pulse noise as well as transforming the pulse
|
||||||
|
or measuring its properties.
|
||||||
|
|
||||||
|
NOTE
|
||||||
|
the term `sc-ordering` is used throughout this module. An array that follows sc-ordering is
|
||||||
|
of shape `([what, ever,] n, nt)` (could be just `(n, nt)` for 2D sc-ordered array) such that
|
||||||
|
n is the number of spectra at the same z position and nt is the size of the time/frequency grid
|
||||||
|
"""
|
||||||
|
|
||||||
|
import itertools
|
||||||
|
import os
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
from numpy import pi
|
||||||
|
from numpy.fft import fft, fftshift, ifft
|
||||||
|
from scipy.interpolate import UnivariateSpline
|
||||||
|
|
||||||
|
from .. import state
|
||||||
|
from ..io import plot_setup
|
||||||
|
from ..math import *
|
||||||
|
|
||||||
|
c = 299792458.0
|
||||||
|
hbar = 1.05457148e-34
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
fwhm_to_T0_fac = dict(
|
||||||
|
sech=1 / (2 * np.log(1 + np.sqrt(2))),
|
||||||
|
gaussian=1 / (np.sqrt(2 * np.log(2))),
|
||||||
|
)
|
||||||
|
"""relates the fwhm of the intensity profile (amplitue^2) to the t0 parameter of the amplitude"""
|
||||||
|
|
||||||
|
P0T0_to_E0_fac = dict(
|
||||||
|
sech=2, # int(a * sech(x / b)^2 * dx) from -inf to inf = 2 * a * b
|
||||||
|
gaussian=np.sqrt(pi / 2), # int(a * exp(-(x/b)^2)^2 * dx) from -inf to inf = sqrt(pi/2) * a * b
|
||||||
|
)
|
||||||
|
"""relates the total energy (amplitue^2) to the t0 parameter of the amplitude and the peak intensity (peak_amplitude^2)"""
|
||||||
|
|
||||||
|
|
||||||
|
def initial_field(t, shape, t0, power):
|
||||||
|
"""returns the initial field
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
t : 1d array
|
||||||
|
time array
|
||||||
|
shape : str {"gaussian", "sech"}
|
||||||
|
shape of the pulse
|
||||||
|
t0 : float
|
||||||
|
time parameters. Can be obtained by dividing the FWHM by
|
||||||
|
`scgenerator.physics.pulse.fwhm_to_T0_fac[shape]`
|
||||||
|
power : float
|
||||||
|
peak power
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
1d array
|
||||||
|
field array
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
ValueError
|
||||||
|
raised when shape is not recognized
|
||||||
|
"""
|
||||||
|
if shape == "gaussian":
|
||||||
|
return gauss_pulse(t, t0, power)
|
||||||
|
elif shape == "sech":
|
||||||
|
return sech_pulse(t, t0, power)
|
||||||
|
else:
|
||||||
|
raise ValueError(f"shape '{shape}' not understood")
|
||||||
|
|
||||||
|
|
||||||
|
def conform_pulse_params(
|
||||||
|
shape,
|
||||||
|
width=None,
|
||||||
|
t0=None,
|
||||||
|
power=None,
|
||||||
|
energy=None,
|
||||||
|
soliton_num=None,
|
||||||
|
gamma=None,
|
||||||
|
beta2=None,
|
||||||
|
):
|
||||||
|
"""makes sure all parameters of the pulse are set and consistent
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
shape : str {"gaussian", "sech"}
|
||||||
|
shape of the pulse
|
||||||
|
width : float, optional
|
||||||
|
fwhm of the intensity pulse, by default None
|
||||||
|
t0 : float, optional
|
||||||
|
time parameter of the amplitude pulse, by default None
|
||||||
|
power : float, optional
|
||||||
|
peak power, by default None
|
||||||
|
energy : float, optional
|
||||||
|
total energy of the pulse, by default None
|
||||||
|
soliton_num : float, optional
|
||||||
|
soliton number, by default None
|
||||||
|
gamma : float, optional
|
||||||
|
nonlinear parameter, by default None
|
||||||
|
beta2 : float, optional
|
||||||
|
second order dispersion coefficient, by default None
|
||||||
|
|
||||||
|
if more parameters than required are specified, the order of precedence
|
||||||
|
indicated by the order in which the parameters are enumerated below holds,
|
||||||
|
meaning the superflous parameters will be overwritten.
|
||||||
|
choose one of the possible combinations :
|
||||||
|
1 of (width, t0), 1 of (power, energy), gamma and beta2 together optional (not one without the other)
|
||||||
|
soliton_num, gamma, 1 of (width, power, energy, t0)
|
||||||
|
examples :
|
||||||
|
specify width, power and energy -> t0 and energy will be computed
|
||||||
|
specify soliton_num, gamma, power, t0 -> width, t0 and energy will be computed
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
width, t0, power, energy
|
||||||
|
when no gamma is specified
|
||||||
|
width, t0, power, energy, soliton_num
|
||||||
|
when gamma is specified
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
TypeError
|
||||||
|
[description]
|
||||||
|
"""
|
||||||
|
|
||||||
|
if gamma is not None and beta2 is None or beta2 is not None and gamma is None:
|
||||||
|
raise TypeError("when soliton number is desired, both gamma and beta2 must be specified")
|
||||||
|
|
||||||
|
if soliton_num is not None:
|
||||||
|
if gamma is None:
|
||||||
|
raise TypeError("gamma must be specified when soliton_num is")
|
||||||
|
|
||||||
|
if width is not None:
|
||||||
|
power = soliton_num ** 2 * abs(beta2) / (gamma * t0 ** 2)
|
||||||
|
elif power is not None:
|
||||||
|
t0 = np.sqrt(soliton_num ** 2 * abs(beta2) / (power * gamma))
|
||||||
|
elif energy is not None:
|
||||||
|
t0 = P0T0_to_E0_fac[shape] * soliton_num ** 2 * abs(beta2) / (energy * gamma)
|
||||||
|
elif t0 is not None:
|
||||||
|
width = t0 / fwhm_to_T0_fac[shape]
|
||||||
|
power = soliton_num ** 2 * abs(beta2) / (gamma * t0 ** 2)
|
||||||
|
else:
|
||||||
|
raise TypeError("not enough parameters to determine pulse")
|
||||||
|
|
||||||
|
if width is not None:
|
||||||
|
t0 = width * fwhm_to_T0_fac[shape]
|
||||||
|
else:
|
||||||
|
width = t0 / fwhm_to_T0_fac[shape]
|
||||||
|
|
||||||
|
if power is not None:
|
||||||
|
energy = P0_to_E0(power, t0, shape)
|
||||||
|
else:
|
||||||
|
power = E0_to_P0(energy, t0, shape)
|
||||||
|
|
||||||
|
if gamma is None:
|
||||||
|
return width, t0, power, energy
|
||||||
|
else:
|
||||||
|
if soliton_num is None:
|
||||||
|
soliton_num = np.sqrt(power * gamma * t0 ** 2 / abs(beta2))
|
||||||
|
return width, t0, power, energy, soliton_num
|
||||||
|
|
||||||
|
|
||||||
|
def E0_to_P0(E0, t0, shape="gaussian"):
|
||||||
|
"""convert an initial total pulse energy to a pulse peak power"""
|
||||||
|
return E0 / (t0 * P0T0_to_E0_fac[shape])
|
||||||
|
|
||||||
|
|
||||||
|
def P0_to_E0(P0, t0, shape="gaussian"):
|
||||||
|
"""converts initial peak power to pulse energy"""
|
||||||
|
return P0 * t0 * P0T0_to_E0_fac[shape]
|
||||||
|
|
||||||
|
|
||||||
|
def sech_pulse(t, t0, P0, offset=0):
|
||||||
|
return np.sqrt(P0) / np.cosh((t - offset) / t0)
|
||||||
|
|
||||||
|
|
||||||
|
def gauss_pulse(t, t0, P0, offset=0):
|
||||||
|
return np.sqrt(P0) * np.exp(-(((t - offset) / t0) ** 2))
|
||||||
|
|
||||||
|
|
||||||
|
def photon_number(spectrum, w, dw, gamma):
|
||||||
|
return np.sum(1 / gamma * abs2(spectrum) / w * dw)
|
||||||
|
|
||||||
|
|
||||||
|
def pulse_energy(spectrum, w, dw, _):
|
||||||
|
return np.sum(abs2(spectrum) * dw)
|
||||||
|
|
||||||
|
|
||||||
|
def technical_noise(rms_noise, relative_factor=0.4):
|
||||||
|
"""
|
||||||
|
To implement technical noise as described in Grenier2019, we need to know the
|
||||||
|
noise properties of the laser, summarized into the RMS amplitude noise
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
rms_noise : float
|
||||||
|
RMS amplitude noise of the laser
|
||||||
|
relative factor : float
|
||||||
|
magnitude of the anticorrelation between power and pulse width noise
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
delta_int : float
|
||||||
|
delta_T0 : float
|
||||||
|
"""
|
||||||
|
psy = np.random.normal(1, rms_noise)
|
||||||
|
return psy, 1 - relative_factor * (psy - 1)
|
||||||
|
|
||||||
|
|
||||||
|
def shot_noise(w_c, w0, T, dt):
|
||||||
|
"""
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
w_c : 1D array
|
||||||
|
angular frequencies centered around 0
|
||||||
|
w0 : float
|
||||||
|
pump angular frequency
|
||||||
|
T : float
|
||||||
|
length of the time windows
|
||||||
|
dt : float
|
||||||
|
resolution of time grid
|
||||||
|
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
out : 1D array of size len(w_c)
|
||||||
|
noise field to be added on top of initial field in time domain
|
||||||
|
"""
|
||||||
|
rand_phase = np.random.rand(len(w_c)) * 2 * pi
|
||||||
|
A_oppm = np.sqrt(hbar * (np.abs(w_c + w0)) * T) * np.exp(-1j * rand_phase)
|
||||||
|
out = ifft(A_oppm / dt * np.sqrt(2 * pi))
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def mean_phase(spectra):
|
||||||
|
"""computes the mean phase of spectra
|
||||||
|
Parameter
|
||||||
|
----------
|
||||||
|
spectra : 2D array
|
||||||
|
The mean is taken on the 0th axis. This means the array has to be of shape (n, nt)
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
mean_phase : 1D array of shape (len(spectra[0]))
|
||||||
|
array of complex numbers of unit length representing the mean phase
|
||||||
|
Example
|
||||||
|
----------
|
||||||
|
>>> x = np.array([[1 + 1j, 0 + 2j, -3 - 1j],
|
||||||
|
[1 + 0j, 2 + 3j, -3 + 1j]])
|
||||||
|
>>> mean_phase(x)
|
||||||
|
array([ 0.92387953+0.38268343j, 0.28978415+0.95709203j, -1. +0.j ])
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
total_phase = np.sum(
|
||||||
|
spectra / np.abs(spectra),
|
||||||
|
axis=0,
|
||||||
|
where=spectra != 0,
|
||||||
|
out=np.zeros(len(spectra[0]), dtype="complex"),
|
||||||
|
)
|
||||||
|
return (total_phase) / np.abs(total_phase)
|
||||||
|
|
||||||
|
|
||||||
|
def flatten_phase(spectra):
|
||||||
|
"""
|
||||||
|
takes the mean phase out of an array of complex numbers
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
spectra : 2D array of shape (n, nt)
|
||||||
|
spectra arranged in the same fashion as in `scgenerator.physics.pulse.mean_phase`
|
||||||
|
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
output : array of same dimensions and amplitude, but with a flattened phase
|
||||||
|
"""
|
||||||
|
mean_theta = mean_phase(spectra)
|
||||||
|
tiled = np.tile(mean_theta, (len(spectra), 1))
|
||||||
|
output = spectra * np.conj(tiled)
|
||||||
|
return output
|
||||||
|
|
||||||
|
|
||||||
|
def compress_pulse(spectra):
|
||||||
|
"""given some complex spectrum, returns the compressed pulse in the time domain
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
spectra : ND array
|
||||||
|
spectra to compress. The shape must be at least 2D. Compression occurs along the -2th axis.
|
||||||
|
This means spectra have to be of shape ([what, ever,] n, nt) where n is the number of spectra
|
||||||
|
brought together for one compression operation and nt the resolution of the grid.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
out : array of shape ([what, ever,] nt)
|
||||||
|
compressed inverse Fourier-transformed pulse
|
||||||
|
"""
|
||||||
|
if spectra.ndim > 2:
|
||||||
|
return np.array([compress_pulse(spec) for spec in spectra])
|
||||||
|
else:
|
||||||
|
return fftshift(ifft(flatten_phase(spectra)), axes=1)
|
||||||
|
|
||||||
|
|
||||||
|
def ideal_compressed_pulse(spectra):
|
||||||
|
"""returns the ideal compressed pulse assuming flat phase
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
spectra : 2D array, sc-ordering
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
compressed : 1D array
|
||||||
|
time envelope of the compressed field
|
||||||
|
"""
|
||||||
|
return abs2(fftshift(ifft(np.sqrt(np.mean(abs2(spectra), axis=0)))))
|
||||||
|
|
||||||
|
|
||||||
|
def spectrogram(time, values, t_res=256, t_win=24e-12, gate_width=200e-15, shift=False):
|
||||||
|
"""
|
||||||
|
returns the spectorgram of the field given in values
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
time : 1D array-like
|
||||||
|
time in the co-moving frame of reference
|
||||||
|
values : 1D array-like
|
||||||
|
field array that matches the time array
|
||||||
|
t_res : int, optional
|
||||||
|
how many "bins" the time array is subdivided into. Default : 256
|
||||||
|
t_win : float, optional
|
||||||
|
total time window (=length of time) over which the spectrogram is computed. Default : 24e-12
|
||||||
|
gate_width : float, optional
|
||||||
|
width of the gaussian gate function (=sqrt(2 log(2)) * FWHM). Default : 200e-15
|
||||||
|
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
spec : 2D array
|
||||||
|
real 2D spectrogram
|
||||||
|
delays : 1D array of size t_res
|
||||||
|
new time axis
|
||||||
|
"""
|
||||||
|
t_lim = t_win / 2
|
||||||
|
delays = np.linspace(-t_lim, t_lim, t_res)
|
||||||
|
spec = np.zeros((t_res, len(time)))
|
||||||
|
for i, delay in enumerate(delays):
|
||||||
|
masked = values * np.exp(-(((time - delay) / gate_width) ** 2))
|
||||||
|
spec[i] = abs2(fft(masked))
|
||||||
|
if shift:
|
||||||
|
spec[i] = fftshift(spec[i])
|
||||||
|
return spec, delays
|
||||||
|
|
||||||
|
|
||||||
|
def g12(values):
|
||||||
|
"""
|
||||||
|
computes the first order coherence function of a ensemble of values
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
values : 2D array
|
||||||
|
complex values following sc-ordering
|
||||||
|
return:
|
||||||
|
g12_arr : coherence function as a n-D array
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Create all the possible pairs of values
|
||||||
|
n = len(values)
|
||||||
|
field_pairs = itertools.combinations(values, 2)
|
||||||
|
corr = np.zeros_like(values[0])
|
||||||
|
for pair in field_pairs:
|
||||||
|
corr += pair[0].conj() * pair[1]
|
||||||
|
g12_arr = corr / (n * (n - 1) / 2 * np.mean(abs2(values), axis=0))
|
||||||
|
|
||||||
|
return np.abs(g12_arr)
|
||||||
|
|
||||||
|
|
||||||
|
def avg_g12(values):
|
||||||
|
"""
|
||||||
|
comptutes the average of the coherence function weighted by amplitude of spectrum
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
values : (m, n)-D array containing m complex values
|
||||||
|
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
(float) average g12
|
||||||
|
"""
|
||||||
|
|
||||||
|
if len(values.shape) > 2:
|
||||||
|
pass
|
||||||
|
|
||||||
|
avg_values = np.mean(abs2(values), axis=0)
|
||||||
|
coherence = g12(values)
|
||||||
|
return np.sum(coherence * avg_values) / np.sum(avg_values)
|
||||||
|
|
||||||
|
|
||||||
|
def fwhm_ind(values, mam=None):
|
||||||
|
"""returns the indices where values is bigger than half its maximum
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
values : array
|
||||||
|
real values with ideally only one smooth peak
|
||||||
|
mam : tupple (float, int)
|
||||||
|
(maximum value, index of the maximum value)
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
left_ind, right_ind : int
|
||||||
|
indices of the the left and right spots where values drops below 1/2 the maximum
|
||||||
|
"""
|
||||||
|
|
||||||
|
if mam is None:
|
||||||
|
m = np.max(values)
|
||||||
|
am = np.argmax(values)
|
||||||
|
else:
|
||||||
|
m, am = mam
|
||||||
|
|
||||||
|
left_ind = am - np.where(values[am::-1] < m / 2)[0][0]
|
||||||
|
right_ind = am + np.where(values[am:] < m / 2)[0][0]
|
||||||
|
return left_ind - 1, right_ind + 1
|
||||||
|
|
||||||
|
|
||||||
|
def peak_ind(values, mam=None):
|
||||||
|
"""returns the indices that encapsulate the entire peak
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
values : array
|
||||||
|
real values with ideally only one smooth peak
|
||||||
|
mam : tupple (float, int)
|
||||||
|
(maximum value, index of the maximum value)
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
left_ind, right_ind : int
|
||||||
|
indices of the the left and right spots where values starts rising again, with a margin of 3
|
||||||
|
"""
|
||||||
|
|
||||||
|
if mam is None:
|
||||||
|
m = np.max(values)
|
||||||
|
am = np.argmax(values)
|
||||||
|
else:
|
||||||
|
m, am = mam
|
||||||
|
left_ind = (
|
||||||
|
am
|
||||||
|
- np.where((values[am:0:-1] - values[am - 1 :: -1] < 0) & (values[am:0:-1] < m / 2))[0][0]
|
||||||
|
)
|
||||||
|
right_ind = (
|
||||||
|
am + np.where((values[am:-1] - values[am + 1 :] < 0) & (values[am:-1] < m / 2))[0][0]
|
||||||
|
)
|
||||||
|
return left_ind - 3, right_ind + 3
|
||||||
|
|
||||||
|
|
||||||
|
def setup_splines(x_axis, values, mam=None):
|
||||||
|
"""sets up spline interpolation to better measure a peak. Different splines with different orders are
|
||||||
|
necessary because derivatives and second derivatives are computed to find extremea and inflection points
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
x_axis : 1D array
|
||||||
|
domain of values
|
||||||
|
values : 1D array
|
||||||
|
real values that ideally contain only one smooth peak to measure
|
||||||
|
mam : tupple (float, int)
|
||||||
|
(maximum value, index of the maximum value)
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
small_spline : scipy.interpolate.UnivariateSpline
|
||||||
|
order 3 spline that interpolates `values - m/2` around the peak
|
||||||
|
spline_4 : scipy.interpolate.UnivariateSpline
|
||||||
|
order 4 spline that interpolate values around the peak
|
||||||
|
spline 5 : scipy.interpolate.UnivariateSpline
|
||||||
|
order 5 spline that interpolates values around the peak
|
||||||
|
d_spline : scipy.interpolate.UnivariateSpline
|
||||||
|
order 3 spline that interpolates the derivative of values around the peak
|
||||||
|
d_roots : list
|
||||||
|
roots of d_spline
|
||||||
|
dd_roots : list
|
||||||
|
inflection points of spline_5
|
||||||
|
l_ind, r_ind : int
|
||||||
|
return values of peak_ind
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Isolate part thats roughly above max/2
|
||||||
|
l_ind_h, r_ind_h = fwhm_ind(values, mam)
|
||||||
|
l_ind, r_ind = peak_ind(values, mam)
|
||||||
|
|
||||||
|
if mam is None:
|
||||||
|
mm = np.max(values)
|
||||||
|
else:
|
||||||
|
mm, _ = mam
|
||||||
|
|
||||||
|
# Only roots of deg=3 splines can be computed, so we need 3 splines to find
|
||||||
|
# zeros, local extrema and inflection points
|
||||||
|
small_spline = UnivariateSpline(
|
||||||
|
x_axis[l_ind_h : r_ind_h + 1], values[l_ind_h : r_ind_h + 1] - mm / 2, k=3, s=0
|
||||||
|
)
|
||||||
|
spline_4 = UnivariateSpline(x_axis[l_ind : r_ind + 1], values[l_ind : r_ind + 1], k=4, s=0)
|
||||||
|
spline_5 = UnivariateSpline(x_axis[l_ind : r_ind + 1], values[l_ind : r_ind + 1], k=5, s=0)
|
||||||
|
d_spline = spline_4.derivative()
|
||||||
|
d_roots = spline_4.derivative().roots()
|
||||||
|
dd_roots = spline_5.derivative(2).roots()
|
||||||
|
|
||||||
|
return small_spline, spline_4, spline_5, d_spline, d_roots, dd_roots, l_ind, r_ind
|
||||||
|
|
||||||
|
|
||||||
|
def find_lobe_limits(x_axis, values, debug="", already_sorted=True):
|
||||||
|
"""find the limits of the centra lobe given 2 derivatives of the values and
|
||||||
|
the position of the FWHM
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
x_axis : 1D array
|
||||||
|
domain of values
|
||||||
|
values : 1D array
|
||||||
|
real values that present a peak whose properties we want to meausure
|
||||||
|
debug : str
|
||||||
|
if the peak is not distinct, a plot is made to assess the measurement
|
||||||
|
providing a debug label can help identify which plot correspond to which function call
|
||||||
|
sorted : bool
|
||||||
|
faster computation if arrays are already sorted
|
||||||
|
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
peak_lim : 1D array (left_lim, right_lim, peak_pos)
|
||||||
|
values that delimit the left, right and maximum of the peak in units of x_axis
|
||||||
|
fwhm_pos : 1D array (left_pos, right_pos)
|
||||||
|
values corresponding to fwhm positions in units of x_axis
|
||||||
|
good_roots : 1D array
|
||||||
|
all candidate values that could delimit the peak position
|
||||||
|
spline_4 : scipy.interpolate.UnivariateSpline
|
||||||
|
order 4 spline that interpolate values around the peak
|
||||||
|
"""
|
||||||
|
if not already_sorted:
|
||||||
|
x_axis, values = x_axis.copy(), values.copy()
|
||||||
|
values = values[np.argsort(x_axis)]
|
||||||
|
x_axis.sort()
|
||||||
|
|
||||||
|
debug_str = f"debug : {debug}" if debug != "" else ""
|
||||||
|
|
||||||
|
small_spline, spline_4, spline_5, d_spline, d_roots, dd_roots, l_ind, r_ind = setup_splines(
|
||||||
|
x_axis, values
|
||||||
|
)
|
||||||
|
|
||||||
|
# get premliminary values for fwhm limits and peak limits
|
||||||
|
# if the peak is distinct, it should be sufficient
|
||||||
|
fwhm_pos = np.array(small_spline.roots())
|
||||||
|
peak_pos = d_roots[np.argmax(spline_4(d_roots))]
|
||||||
|
|
||||||
|
# if there are more than 2 fwhm position, a detailed analysis can help
|
||||||
|
# determining the true ones. If that fails, there is no meaningful peak to measure
|
||||||
|
detailed_measurement = len(fwhm_pos) > 2 or state._DEBUG.get(
|
||||||
|
"find_lobe_limits.always_plot", False
|
||||||
|
)
|
||||||
|
if detailed_measurement:
|
||||||
|
|
||||||
|
print("trouble measuring the peak.{}".format(debug_str))
|
||||||
|
(
|
||||||
|
spline_4,
|
||||||
|
d_spline,
|
||||||
|
d_roots,
|
||||||
|
dd_roots,
|
||||||
|
fwhm_pos,
|
||||||
|
peak_pos,
|
||||||
|
folder_name,
|
||||||
|
file_name,
|
||||||
|
fig,
|
||||||
|
ax,
|
||||||
|
color,
|
||||||
|
) = _detailed_find_lobe_limits(
|
||||||
|
x_axis,
|
||||||
|
values,
|
||||||
|
debug,
|
||||||
|
debug_str,
|
||||||
|
spline_4,
|
||||||
|
spline_5,
|
||||||
|
fwhm_pos,
|
||||||
|
peak_pos,
|
||||||
|
d_spline,
|
||||||
|
d_roots,
|
||||||
|
dd_roots,
|
||||||
|
l_ind,
|
||||||
|
r_ind,
|
||||||
|
)
|
||||||
|
|
||||||
|
good_roots, left_lim, right_lim = _select_roots(d_spline, d_roots, dd_roots, fwhm_pos)
|
||||||
|
|
||||||
|
ax.scatter(
|
||||||
|
[left_lim, right_lim],
|
||||||
|
spline_4([left_lim, right_lim]),
|
||||||
|
marker="|",
|
||||||
|
label="lobe pos",
|
||||||
|
c=color[5],
|
||||||
|
)
|
||||||
|
if not "find_lobe_limits.ax" in state._DEBUG:
|
||||||
|
ax.legend()
|
||||||
|
fig.savefig(os.path.join(folder_name, file_name), bbox_inches="tight")
|
||||||
|
plt.close(fig)
|
||||||
|
|
||||||
|
else:
|
||||||
|
good_roots, left_lim, right_lim = _select_roots(d_spline, d_roots, dd_roots, fwhm_pos)
|
||||||
|
|
||||||
|
return np.array([left_lim, right_lim, peak_pos]), fwhm_pos, np.array(good_roots), spline_4
|
||||||
|
|
||||||
|
|
||||||
|
def _select_roots(d_spline, d_roots, dd_roots, fwhm_pos):
|
||||||
|
"""selects the limits of a lobe
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
d_spline : scipy.interpolate.UnivariateSpline
|
||||||
|
spline of the first derivative of the lobe
|
||||||
|
d_roots : list
|
||||||
|
roots of the first derivarive (extrema of the original function)
|
||||||
|
dd_roots : list
|
||||||
|
roots of the second derivative (inflection points of the original function)
|
||||||
|
fwhm_pos : list
|
||||||
|
locations where the lobe is half of its maximum
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
good_roots : list
|
||||||
|
valid roots
|
||||||
|
left_lim : list
|
||||||
|
location of the left limit
|
||||||
|
right_lim : list
|
||||||
|
location of the right limit
|
||||||
|
"""
|
||||||
|
# includes inflection points when slope is low (avoids considering the inflection points around fwhm limits)
|
||||||
|
|
||||||
|
all_roots = np.append(d_roots, dd_roots)
|
||||||
|
good_roots = all_roots[np.abs(d_spline(all_roots)) < np.max(d_spline(all_roots)) / 10]
|
||||||
|
|
||||||
|
try:
|
||||||
|
left_lim = np.max(good_roots[good_roots < np.min(fwhm_pos)])
|
||||||
|
except ValueError:
|
||||||
|
left_lim = np.min(good_roots)
|
||||||
|
|
||||||
|
try:
|
||||||
|
right_lim = np.min(good_roots[good_roots > np.max(fwhm_pos)])
|
||||||
|
except ValueError:
|
||||||
|
right_lim = np.max(good_roots)
|
||||||
|
|
||||||
|
return good_roots, left_lim, right_lim
|
||||||
|
|
||||||
|
|
||||||
|
def _detailed_find_lobe_limits(
|
||||||
|
x_axis,
|
||||||
|
values,
|
||||||
|
debug,
|
||||||
|
debug_str,
|
||||||
|
spline_4,
|
||||||
|
spline_5,
|
||||||
|
fwhm_pos,
|
||||||
|
peak_pos,
|
||||||
|
d_spline,
|
||||||
|
d_roots,
|
||||||
|
dd_roots,
|
||||||
|
l_ind,
|
||||||
|
r_ind,
|
||||||
|
):
|
||||||
|
|
||||||
|
left_pos = fwhm_pos[fwhm_pos < peak_pos]
|
||||||
|
right_pos = fwhm_pos[fwhm_pos > peak_pos]
|
||||||
|
|
||||||
|
iterations = 0
|
||||||
|
|
||||||
|
# spline maximum may not be on same peak as the original one. In this
|
||||||
|
# case it means that there is no distinct peak, but we try to
|
||||||
|
# compute everything again anyway. If spline inaccuracies lead to a cycle,
|
||||||
|
# we break it by choosing two values arbitrarily
|
||||||
|
|
||||||
|
while len(left_pos) == 0 or len(right_pos) == 0:
|
||||||
|
if iterations > 4:
|
||||||
|
|
||||||
|
left_pos, right_pos = [np.min(peak_pos)], [np.max(peak_pos)]
|
||||||
|
print(
|
||||||
|
"Cycle had to be broken. Peak measurement is probably wrong : {}".format(debug_str)
|
||||||
|
)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
iterations += 1
|
||||||
|
|
||||||
|
mam = (spline_4(peak_pos), argclosest(x_axis, peak_pos))
|
||||||
|
|
||||||
|
small_spline, spline_4, spline_5, d_spline, d_roots, dd_roots, l_ind, r_ind = setup_splines(
|
||||||
|
x_axis, values, mam
|
||||||
|
)
|
||||||
|
|
||||||
|
fwhm_pos = np.array(small_spline.roots())
|
||||||
|
peak_pos = d_roots[np.argmax(spline_4(d_roots))]
|
||||||
|
|
||||||
|
left_pos = fwhm_pos[fwhm_pos < peak_pos]
|
||||||
|
right_pos = fwhm_pos[fwhm_pos > peak_pos]
|
||||||
|
|
||||||
|
# if measurement of the peak is not straightforward, we plot the situation to see
|
||||||
|
# if the final measurement is good or not
|
||||||
|
|
||||||
|
folder_name, file_name, fig, ax = plot_setup(
|
||||||
|
file_name=f"it_{iterations}_{debug}", folder_name="measurements_errors_plots"
|
||||||
|
)
|
||||||
|
ax = state._DEBUG.get("find_lobe_limits.ax", ax)
|
||||||
|
plt.sca(ax)
|
||||||
|
state._DEBUG["x"] = x_axis
|
||||||
|
|
||||||
|
new_fwhm_pos = np.array([np.max(left_pos), np.min(right_pos)])
|
||||||
|
|
||||||
|
# PLOT
|
||||||
|
|
||||||
|
newx = np.linspace(*span(x_axis[l_ind : r_ind + 1]), 1000)
|
||||||
|
color = state._DEBUG.get("color", state.plot_default_color_cycle)
|
||||||
|
if state._DEBUG.get("find_lobe_limits.draw_raw_data", True):
|
||||||
|
ax.plot(x_axis[l_ind - 5 : r_ind + 6], values[l_ind - 5 : r_ind + 6], c=color[0])
|
||||||
|
ax.plot(newx, spline_5(newx), c=color[1])
|
||||||
|
ax.scatter(fwhm_pos, spline_4(fwhm_pos), marker="+", label="all fwhm", c=color[2])
|
||||||
|
ax.scatter(peak_pos, spline_4(peak_pos), marker=".", label="peak pos", c=color[3])
|
||||||
|
ax.scatter(new_fwhm_pos, spline_4(new_fwhm_pos), marker="_", label="2 chosen", c=color[4])
|
||||||
|
|
||||||
|
fwhm_pos = new_fwhm_pos
|
||||||
|
return (
|
||||||
|
spline_4,
|
||||||
|
d_spline,
|
||||||
|
d_roots,
|
||||||
|
dd_roots,
|
||||||
|
fwhm_pos,
|
||||||
|
peak_pos,
|
||||||
|
folder_name,
|
||||||
|
file_name,
|
||||||
|
fig,
|
||||||
|
ax,
|
||||||
|
color,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def measure_properties(spectra, t, compress=True, debug=""):
|
||||||
|
"""measure the quality factor, the fwhm variation, the peak power variation,
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
spectra : 2D array
|
||||||
|
set of n spectra in sc-ordering that differ only by noise
|
||||||
|
t : 1D array
|
||||||
|
time axis of the simulation
|
||||||
|
compress : bool, optional
|
||||||
|
whether to perform pulse compression. Default value is True, but this
|
||||||
|
should be set to False to measure the initial pulse as output by gaussian_pulse
|
||||||
|
or sech_pulse because compressing it would result in glitches and wrong measurements
|
||||||
|
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
qf : float
|
||||||
|
quality factor of the pulse ensemble
|
||||||
|
mean_g12 : float
|
||||||
|
mean coherence of the spectra ensemble
|
||||||
|
fwhm_var : float
|
||||||
|
relative noise in temporal width of the compressed pulse
|
||||||
|
fwhm_abs : float
|
||||||
|
width of the mean compressed pulse
|
||||||
|
int_var : flaot
|
||||||
|
relative noise in the compressed pulse peak intensity
|
||||||
|
t_jitter : float
|
||||||
|
standard deviantion in absolute temporal peak position
|
||||||
|
"""
|
||||||
|
if compress:
|
||||||
|
fields = abs2(compress_pulse(spectra))
|
||||||
|
else:
|
||||||
|
print("Skipping compression")
|
||||||
|
fields = abs2(ifft(spectra))
|
||||||
|
|
||||||
|
field = np.mean(fields, axis=0)
|
||||||
|
ideal_field = abs2(fftshift(ifft(np.sqrt(np.mean(abs2(spectra), axis=0)))))
|
||||||
|
|
||||||
|
# Isolate whole central lobe of bof mean and ideal field
|
||||||
|
lobe_lim, fwhm_lim, _, big_spline = find_lobe_limits(t, field, debug)
|
||||||
|
lobe_lim_i, _, _, big_spline_i = find_lobe_limits(t, ideal_field, debug)
|
||||||
|
|
||||||
|
# Compute quality factor
|
||||||
|
energy_fraction = (big_spline.integral(*span(lobe_lim[:2]))) / np.trapz(field, x=t)
|
||||||
|
energy_fraction_i = (big_spline_i.integral(*span(lobe_lim_i[:2]))) / np.trapz(ideal_field, x=t)
|
||||||
|
qf = energy_fraction / energy_fraction_i
|
||||||
|
|
||||||
|
# Compute mean coherence
|
||||||
|
mean_g12 = avg_g12(spectra)
|
||||||
|
fwhm_abs = length(fwhm_lim)
|
||||||
|
|
||||||
|
# To compute amplitude and fwhm fluctuations, we need to measure every single peak
|
||||||
|
P0 = []
|
||||||
|
fwhm = []
|
||||||
|
t_offset = []
|
||||||
|
for f in fields:
|
||||||
|
lobe_lim, fwhm_lim, _, big_spline = find_lobe_limits(t, f, debug)
|
||||||
|
P0.append(big_spline(lobe_lim[2]))
|
||||||
|
fwhm.append(length(fwhm_lim))
|
||||||
|
t_offset.append(lobe_lim[2])
|
||||||
|
fwhm_var = np.std(fwhm) / np.mean(fwhm)
|
||||||
|
int_var = np.std(P0) / np.mean(P0)
|
||||||
|
t_jitter = np.std(t_offset)
|
||||||
|
|
||||||
|
return qf, mean_g12, fwhm_var, fwhm_abs, int_var, t_jitter
|
||||||
722
src/scgenerator/physics/simulate.py
Normal file
722
src/scgenerator/physics/simulate.py
Normal file
@@ -0,0 +1,722 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
from numpy.fft import fft, ifft
|
||||||
|
|
||||||
|
|
||||||
|
from .. import initialize
|
||||||
|
from .. import io, state
|
||||||
|
from .. import utilities
|
||||||
|
from ..io import generate_file_path, get_logger
|
||||||
|
from ..math import abs2
|
||||||
|
from ..utilities import ProgressTracker, format_varying_list
|
||||||
|
from . import pulse, units
|
||||||
|
from .fiber import create_non_linear_op, fast_dispersion_op
|
||||||
|
|
||||||
|
using_ray = False
|
||||||
|
try:
|
||||||
|
import ray
|
||||||
|
|
||||||
|
using_ray = True
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Simulations:
|
||||||
|
"""The recommended way to run simulations.
|
||||||
|
New Simulations child classes can be written and must implement the following
|
||||||
|
"""
|
||||||
|
|
||||||
|
_available_simulation_methods = []
|
||||||
|
|
||||||
|
def __init_subclass__(cls, available: bool, priority=0, **kwargs):
|
||||||
|
cls._available = available
|
||||||
|
if available:
|
||||||
|
Simulations._available_simulation_methods.append((cls, priority))
|
||||||
|
Simulations._available_simulation_methods.sort(key=lambda el: el[1])
|
||||||
|
super().__init_subclass__(**kwargs)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_best_method(cls):
|
||||||
|
return Simulations._available_simulation_methods[-1][0]
|
||||||
|
|
||||||
|
def __init__(self, param_seq: initialize.ParamSequence, task_id=0, data_folder="scgenerator/"):
|
||||||
|
"""
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
param_seq : scgenerator.initialize.ParamSequence obj
|
||||||
|
parameter sequence
|
||||||
|
task_id : int, optional
|
||||||
|
a unique id that identifies the simulation, by default 0
|
||||||
|
data_folder : str, optional
|
||||||
|
path to the folder where data is saved, by default "scgenerator/"
|
||||||
|
"""
|
||||||
|
self.logger = io.get_logger(__name__)
|
||||||
|
self.id = int(task_id)
|
||||||
|
|
||||||
|
self.param_seq = param_seq
|
||||||
|
self.name = param_seq.name
|
||||||
|
self.data_folder = io.get_data_folder(self.id, name_if_new=self.name)
|
||||||
|
io.save_toml(os.path.join(self.data_folder, "initial_config.toml"), self.param_seq.config)
|
||||||
|
|
||||||
|
self.using_ray = False
|
||||||
|
self.sim_jobs = 1
|
||||||
|
|
||||||
|
self.propagation_func = lambda params, varying_list: RK4IP(
|
||||||
|
params,
|
||||||
|
save_data=True,
|
||||||
|
job_identifier=utilities.format_varying_list(varying_list),
|
||||||
|
task_id=self.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.progress_tracker = utilities.ProgressTracker(
|
||||||
|
max=len(self.param_seq),
|
||||||
|
auto_print=True,
|
||||||
|
percent_incr=1,
|
||||||
|
callback=lambda s, logger: logger.info(s),
|
||||||
|
)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
for varying_params, params in self.param_seq:
|
||||||
|
for i in range(self.param_seq["simulation", "repeat"]):
|
||||||
|
varying = varying_params + [("num", i)]
|
||||||
|
io.save_parameters(
|
||||||
|
params,
|
||||||
|
io.generate_file_path(
|
||||||
|
"params.toml", self.id, utilities.format_varying_list(varying)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
self.new_sim(varying, params.copy())
|
||||||
|
|
||||||
|
self.finish()
|
||||||
|
self.logger.info(f"Merging data...")
|
||||||
|
|
||||||
|
self.merge_data()
|
||||||
|
self.logger.info(f"Finished simulations from config {self.name} !")
|
||||||
|
|
||||||
|
def new_sim(self, varying_list: List[tuple], params: dict):
|
||||||
|
"""responsible to launch a new simulation
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
varying_list : list[tuple]
|
||||||
|
list of tuples (name, value) where name is the name of a
|
||||||
|
varying parameter and value is its current value
|
||||||
|
params : dict
|
||||||
|
a flattened parameter dictionary, as returned by scgenerator.initialize.compute_init_parameters
|
||||||
|
"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def finish(self):
|
||||||
|
"""called once all the simulations are launched."""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def merge_data(self):
|
||||||
|
io.merge_data(self.data_folder)
|
||||||
|
|
||||||
|
|
||||||
|
class SequencialSimulations(Simulations, available=True, priority=0):
|
||||||
|
def new_sim(self, varying_list: List[tuple], params: dict):
|
||||||
|
self.logger.info(f"launching simulation with {varying_list}")
|
||||||
|
self.propagation_func(params, varying_list)
|
||||||
|
self.progress_tracker.update(1, [self.logger])
|
||||||
|
|
||||||
|
def finish(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class RaySimulations(Simulations, available=using_ray, priority=1):
|
||||||
|
"""runs simulation with the help of the ray module. ray must be initialized before creating an instance of RaySimulations"""
|
||||||
|
|
||||||
|
def __init__(self, param_seq: initialize.ParamSequence, task_id=0, data_folder="scgenerator/"):
|
||||||
|
super().__init__(param_seq, task_id, data_folder)
|
||||||
|
self._init_ray()
|
||||||
|
|
||||||
|
def _init_ray(self):
|
||||||
|
nodes = ray.nodes()
|
||||||
|
nodes_num = len(nodes)
|
||||||
|
self.logger.info(
|
||||||
|
f"{nodes_num} node{'s' if nodes_num > 1 else ''} in the Ray cluster : "
|
||||||
|
+ str([node.get("NodeManagerHostname", "unknown") for node in nodes])
|
||||||
|
)
|
||||||
|
|
||||||
|
self.sim_jobs = min(self.param_seq.num_sim, self.param_seq["simulation", "parallel"])
|
||||||
|
self.propagation_func = ray.remote(self.propagation_func).options(
|
||||||
|
override_environment_variables=io.get_all_environ()
|
||||||
|
)
|
||||||
|
self.jobs = []
|
||||||
|
|
||||||
|
def new_sim(self, varying_list: List[tuple], params: dict):
|
||||||
|
if len(self.jobs) >= self.sim_jobs:
|
||||||
|
|
||||||
|
# wait for a slot to free before starting a new job
|
||||||
|
_, self.jobs = ray.wait(self.jobs)
|
||||||
|
ray.get(_)
|
||||||
|
self.progress_tracker.update(1, [self.logger])
|
||||||
|
|
||||||
|
self.jobs.append(self.propagation_func.remote(params, varying_list))
|
||||||
|
|
||||||
|
self.logger.info(f"launching simulation with {varying_list}, job : {self.jobs[-1].hex()}")
|
||||||
|
|
||||||
|
def finish(self):
|
||||||
|
for job in self.jobs:
|
||||||
|
ray.get(job)
|
||||||
|
self.progress_tracker.update(1, [self.logger])
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
ray.shutdown()
|
||||||
|
|
||||||
|
|
||||||
|
def new_simulations(config_file: str, task_id: int, data_folder="scgenerator/"):
|
||||||
|
|
||||||
|
config = io.load_toml(config_file)
|
||||||
|
param_seq = initialize.ParamSequence(config)
|
||||||
|
|
||||||
|
if param_seq.num_sim > 1 and param_seq["simulation", "parallel"] > 1 and using_ray:
|
||||||
|
return Simulations.get_best_method()(param_seq, task_id, data_folder=data_folder)
|
||||||
|
else:
|
||||||
|
return SequencialSimulations(param_seq, task_id, data_folder=data_folder)
|
||||||
|
|
||||||
|
|
||||||
|
def RK4IP(sim_params, save_data=False, job_identifier="", task_id=0, n_percent=10):
|
||||||
|
"""Computes the spectrum of a pulse as it propagates through a PCF
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
sim_params : a dictionary containing the following :
|
||||||
|
w_c : array
|
||||||
|
angular frequencies centered around 0 generated with scgenerator.initialize.wspace
|
||||||
|
w0 : float
|
||||||
|
central angular frequency of the pulse
|
||||||
|
t : array
|
||||||
|
time
|
||||||
|
dt : float
|
||||||
|
time resolution
|
||||||
|
field_0 : array
|
||||||
|
initial field envelope as function of w_c
|
||||||
|
z_targets : list
|
||||||
|
target distances
|
||||||
|
beta : array
|
||||||
|
beta coeficients (Taylor expansion of beta(w))
|
||||||
|
gamma : float
|
||||||
|
non-linear parameter
|
||||||
|
behaviors : list(str {'ss', 'raman', 'spm'})
|
||||||
|
behaviors to include in the simulation given as a list of strings
|
||||||
|
raman_type : str, optional
|
||||||
|
type of raman modelisation if raman effect is present
|
||||||
|
f_r, hr_w : (opt) arguments of delayed_raman_t (see there for infos)
|
||||||
|
adapt_step_size : bool, optional
|
||||||
|
if True (default), adapts the step size with conserved quantity methode
|
||||||
|
error_ok : float
|
||||||
|
tolerated relative error for the adaptive step size if adaptive
|
||||||
|
step size is turned on, otherwise length of fixed steps in m
|
||||||
|
save_data : bool
|
||||||
|
False : return the spectra (recommended, save manually later if necessary)
|
||||||
|
True : save in a temporary folder and return the folder name
|
||||||
|
to be used for merging later
|
||||||
|
job_id : int
|
||||||
|
id of this particular simulation
|
||||||
|
param_id : int
|
||||||
|
id corresponding to the set of paramters. Files created with the same param_id will be
|
||||||
|
merged if an indexer is passed (this feature is mainly used for automated parallel simulations
|
||||||
|
using the parallel_simulations function).
|
||||||
|
task_id : int
|
||||||
|
id of the whole program (useful when many python instances run at once). None if not running in parallel
|
||||||
|
n_percent : int, float
|
||||||
|
log message every n_percent of the simulation done
|
||||||
|
pt : scgenerator.progresstracker.ProgressTracker object
|
||||||
|
indexer : indexer object
|
||||||
|
debug_return : bool
|
||||||
|
if True and save_data False, will return photon number and step sizes as well as the spectra.
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
stored_spectra : (store_num, nt) array
|
||||||
|
spectrum aligned on w_c array
|
||||||
|
h_stored : 1D array
|
||||||
|
length of each valid step
|
||||||
|
cons_qty : 1D array
|
||||||
|
conserved quantity at each valid step
|
||||||
|
cons_qty_change : 1D array
|
||||||
|
conserved quantity change at each valid step
|
||||||
|
|
||||||
|
"""
|
||||||
|
# DEBUG
|
||||||
|
debug = False
|
||||||
|
|
||||||
|
w_c = sim_params.pop("w_c")
|
||||||
|
w0 = sim_params.pop("w0")
|
||||||
|
w_power_fact = sim_params.pop("w_power_fact")
|
||||||
|
field_0 = sim_params.pop("field_0")
|
||||||
|
z_targets = sim_params.pop("z_targets")
|
||||||
|
z_final = sim_params.pop("length")
|
||||||
|
beta = sim_params.pop("beta_func", sim_params.pop("beta"))
|
||||||
|
gamma = sim_params.pop("gamma_func", sim_params.pop("gamma"))
|
||||||
|
behaviors = sim_params.pop("behaviors")
|
||||||
|
raman_type = sim_params.pop("raman_type", "stolen")
|
||||||
|
f_r = sim_params.pop("f_r", 0)
|
||||||
|
hr_w = sim_params.pop("hr_w", None)
|
||||||
|
adapt_step_size = sim_params.pop("adapt_step_size", True)
|
||||||
|
error_ok = sim_params.pop("error_ok", 1e-10)
|
||||||
|
dynamic_dispersion = sim_params.pop("dynamic_dispersion", False)
|
||||||
|
del sim_params
|
||||||
|
|
||||||
|
logger = get_logger(job_identifier)
|
||||||
|
|
||||||
|
# Initial setup of both non linear and linear operators
|
||||||
|
N_func = create_non_linear_op(behaviors, w_c, w0, gamma, raman_type, f_r, hr_w)
|
||||||
|
if dynamic_dispersion:
|
||||||
|
disp = lambda r: fast_dispersion_op(w_c, beta(r), w_power_fact)
|
||||||
|
else:
|
||||||
|
disp = lambda r: fast_dispersion_op(w_c, beta, w_power_fact)
|
||||||
|
|
||||||
|
# Set up which quantity is conserved for adaptive step size
|
||||||
|
if adapt_step_size:
|
||||||
|
if "raman" in behaviors:
|
||||||
|
conserved_quantity_func = pulse.photon_number
|
||||||
|
else:
|
||||||
|
print("energy conserved")
|
||||||
|
conserved_quantity_func = pulse.pulse_energy
|
||||||
|
else:
|
||||||
|
conserved_quantity_func = lambda a, b, c, d: 0
|
||||||
|
|
||||||
|
# making sure to keep only the z that we want
|
||||||
|
z_targets = list(set(value for value in z_targets if value > 0))
|
||||||
|
z_targets.sort()
|
||||||
|
store_num = len(z_targets)
|
||||||
|
|
||||||
|
# Initial setup of simulation parameters
|
||||||
|
d_w = w_c[1] - w_c[0] # resolution of the frequency grid
|
||||||
|
z_stored, z = [0], 0 # position of each stored spectrum (for display)
|
||||||
|
|
||||||
|
pt = utilities.ProgressTracker(
|
||||||
|
z_final,
|
||||||
|
auto_print=True,
|
||||||
|
percent_incr=n_percent,
|
||||||
|
callback=_gen_RK4IP_progress_callback(),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Setup initial values for every physical quantity that we want to track
|
||||||
|
current_spectrum = fft(field_0)
|
||||||
|
stored_spectra = [current_spectrum.copy()]
|
||||||
|
stored_field = [ifft(current_spectrum.copy())]
|
||||||
|
cons_qty = [conserved_quantity_func(current_spectrum, w_c + w0, d_w, gamma), 0]
|
||||||
|
cons_qty_change = [0, 0]
|
||||||
|
size_fac = 2 ** (1 / 5)
|
||||||
|
|
||||||
|
if save_data:
|
||||||
|
_save_current_spectrum(current_spectrum, 0, task_id, job_identifier)
|
||||||
|
|
||||||
|
# Initial step size
|
||||||
|
if adapt_step_size:
|
||||||
|
h = z_targets[0] / 2
|
||||||
|
else:
|
||||||
|
h = error_ok
|
||||||
|
newh = h
|
||||||
|
|
||||||
|
# Print introduction
|
||||||
|
logger.info("Storing {} new spectra, first one at {}m".format(store_num, z_targets[0]))
|
||||||
|
|
||||||
|
# Start of the integration
|
||||||
|
step = 1
|
||||||
|
keep = True # keep a step
|
||||||
|
store = False # store a spectrum
|
||||||
|
time_start = datetime.today()
|
||||||
|
|
||||||
|
while z < z_final:
|
||||||
|
h = newh
|
||||||
|
z_ratio = z / z_final
|
||||||
|
|
||||||
|
# Store Exp(h/2 * disp) to be used several times
|
||||||
|
expD = np.exp(h / 2 * disp(z_ratio))
|
||||||
|
|
||||||
|
# RK4 algorithm
|
||||||
|
A_I = expD * current_spectrum
|
||||||
|
k1 = expD * (h * N_func(current_spectrum, z_ratio))
|
||||||
|
k2 = h * N_func(A_I + k1 / 2, z_ratio)
|
||||||
|
k3 = h * N_func(A_I + k2 / 2, z_ratio)
|
||||||
|
k4 = h * N_func(expD * (A_I + k3), z_ratio)
|
||||||
|
|
||||||
|
end_spectrum = expD * (A_I + k1 / 6 + k2 / 3 + k3 / 3) + k4 / 6
|
||||||
|
|
||||||
|
# Check relative error and adjust next step size
|
||||||
|
if adapt_step_size:
|
||||||
|
cons_qty[step] = conserved_quantity_func(end_spectrum, w_c + w0, d_w, gamma)
|
||||||
|
curr_p_change = np.abs(cons_qty[step - 1] - cons_qty[step])
|
||||||
|
cons_qty_change[step] = cons_qty_change[step - 1] + curr_p_change
|
||||||
|
cons_qty_change_ok = error_ok * cons_qty[step - 1]
|
||||||
|
|
||||||
|
if curr_p_change > 2 * cons_qty_change_ok:
|
||||||
|
keep = False
|
||||||
|
newh = h / 2
|
||||||
|
elif cons_qty_change_ok < curr_p_change <= 2 * cons_qty_change_ok:
|
||||||
|
keep = True
|
||||||
|
newh = h / size_fac
|
||||||
|
elif curr_p_change < 0.1 * cons_qty_change_ok:
|
||||||
|
keep = True
|
||||||
|
newh = h * size_fac
|
||||||
|
else:
|
||||||
|
keep = True
|
||||||
|
newh = h
|
||||||
|
|
||||||
|
# consider storing anythin only if the step was valid
|
||||||
|
if keep:
|
||||||
|
|
||||||
|
# If step is accepted, z becomes the current position
|
||||||
|
z += h
|
||||||
|
step += 1
|
||||||
|
cons_qty.append(0)
|
||||||
|
cons_qty_change.append(0)
|
||||||
|
|
||||||
|
current_spectrum = end_spectrum.copy()
|
||||||
|
|
||||||
|
# Whether the current spectrum has to be stored depends on previous step
|
||||||
|
if store:
|
||||||
|
pt.set(z, [logger, step, z, h])
|
||||||
|
|
||||||
|
stored_spectra.append(end_spectrum)
|
||||||
|
stored_field.append(ifft(end_spectrum))
|
||||||
|
if save_data:
|
||||||
|
_save_current_spectrum(
|
||||||
|
end_spectrum, len(stored_spectra) - 1, task_id, job_identifier
|
||||||
|
)
|
||||||
|
|
||||||
|
z_stored.append(z)
|
||||||
|
del z_targets[0]
|
||||||
|
|
||||||
|
# No more spectrum to store
|
||||||
|
if len(z_targets) == 0:
|
||||||
|
break
|
||||||
|
store = False
|
||||||
|
|
||||||
|
# reset the constant step size after a spectrum is stored
|
||||||
|
if not adapt_step_size:
|
||||||
|
newh = error_ok
|
||||||
|
|
||||||
|
# if the next step goes over a position at which we want to store
|
||||||
|
# a spectrum, we shorten the step to reach this position exactly
|
||||||
|
if z + newh >= z_targets[0]:
|
||||||
|
store = True
|
||||||
|
newh = z_targets[0] - z
|
||||||
|
else:
|
||||||
|
progress_str = f"step {step} rejected with h = {h:.4e}, doing over"
|
||||||
|
logger.info(progress_str)
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
"propagation finished in {} steps ({} seconds)".format(
|
||||||
|
step, (datetime.today() - time_start).total_seconds()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if save_data:
|
||||||
|
io.save_data(z_stored, "z.npy", task_id, job_identifier)
|
||||||
|
|
||||||
|
return stored_spectra
|
||||||
|
|
||||||
|
|
||||||
|
def _save_current_spectrum(spectrum: np.ndarray, num: int, task_id: int, job_identifier: str):
|
||||||
|
base_name = f"spectrum_{num}.npy"
|
||||||
|
io.save_data(spectrum, base_name, task_id, job_identifier)
|
||||||
|
|
||||||
|
|
||||||
|
def _gen_RK4IP_progress_callback():
|
||||||
|
def callback(s, logger, step, z, h):
|
||||||
|
progress_str = " ({} steps). z = {:.4f}, h = {:.5g}".format(step, z, h)
|
||||||
|
logger.info(s + progress_str)
|
||||||
|
|
||||||
|
return callback
|
||||||
|
|
||||||
|
|
||||||
|
def _RK4IP_extract_params(sim_params):
|
||||||
|
"""extracts the right parameters from the the flattened params dict
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
sim_params : dict
|
||||||
|
flattened parameters dictionary
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
tuple
|
||||||
|
all the necessary parameters
|
||||||
|
"""
|
||||||
|
w_c = sim_params.pop("w_c")
|
||||||
|
w0 = sim_params.pop("w0")
|
||||||
|
w_power_fact = sim_params.pop("w_power_fact")
|
||||||
|
field_0 = sim_params.pop("field_0")
|
||||||
|
z_targets = sim_params.pop("z_targets")
|
||||||
|
beta = sim_params.pop("beta_func", sim_params.pop("beta"))
|
||||||
|
gamma = sim_params.pop("gamma_func", sim_params.pop("gamma"))
|
||||||
|
behaviors = sim_params.pop("behaviors")
|
||||||
|
raman_type = sim_params.pop("raman_type", "stolen")
|
||||||
|
f_r = sim_params.pop("f_r", 0)
|
||||||
|
hr_w = sim_params.pop("hr_w", None)
|
||||||
|
adapt_step_size = sim_params.pop("adapt_step_size", True)
|
||||||
|
error_ok = sim_params.pop("error_ok", 1e-10)
|
||||||
|
dynamic_dispersion = sim_params.pop("dynamic_dispersion", False)
|
||||||
|
del sim_params
|
||||||
|
return (
|
||||||
|
behaviors,
|
||||||
|
w_c,
|
||||||
|
w0,
|
||||||
|
gamma,
|
||||||
|
raman_type,
|
||||||
|
f_r,
|
||||||
|
hr_w,
|
||||||
|
dynamic_dispersion,
|
||||||
|
beta,
|
||||||
|
w_power_fact,
|
||||||
|
adapt_step_size,
|
||||||
|
z_targets,
|
||||||
|
field_0,
|
||||||
|
error_ok,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _prepare_grid(z_targets, w_c):
|
||||||
|
"""prepares some derived values for the propagation
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
z_targets : array
|
||||||
|
array of target z positions
|
||||||
|
w_c : array
|
||||||
|
angular frequency array (centered on 0)
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
d_w : float
|
||||||
|
angular frequency grid size
|
||||||
|
z_targets : list
|
||||||
|
list of target z positions
|
||||||
|
store_num : int
|
||||||
|
number of spectra to store
|
||||||
|
z_final : float
|
||||||
|
final z position
|
||||||
|
z_sored : list
|
||||||
|
where the spectra are already stored
|
||||||
|
|
||||||
|
"""
|
||||||
|
# making sure to keep only the z that we want
|
||||||
|
z_targets = list(set(value for value in z_targets if value > 0))
|
||||||
|
z_targets.sort()
|
||||||
|
z_final = z_targets[-1]
|
||||||
|
store_num = len(z_targets)
|
||||||
|
|
||||||
|
# Initial setup of simulation parameters
|
||||||
|
d_w = w_c[1] - w_c[0] # resolution of the frequency grid
|
||||||
|
z_stored = [0] # position of each stored spectrum (for display)
|
||||||
|
return d_w, z_targets, store_num, z_final, z_stored
|
||||||
|
|
||||||
|
|
||||||
|
def parallel_simulations(config_file, num_cpu_per_task=1, task_id=0):
|
||||||
|
"""runs simulations in parallel thanks to Ray
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
config_file : str
|
||||||
|
name of the config file
|
||||||
|
should be a json containing all necessary parameters for the simulation. Varying parameters should be placed in a subdictionary
|
||||||
|
called "varying" (see scgenerator.utilities.dictionary_iterator for details)
|
||||||
|
num_cpu_per_task : int
|
||||||
|
number of concurrent job per node
|
||||||
|
task_id : give an id for book keeping purposes (must be set if multiple ray instances run at once so their files do not overlap)
|
||||||
|
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
name of the folder where the data is stored
|
||||||
|
"""
|
||||||
|
logger = ray.remote(io.Logger).remote()
|
||||||
|
state.CurrentLogger.focus_logger(logger)
|
||||||
|
|
||||||
|
print("Nodes in the Ray cluster:", len(ray.nodes()))
|
||||||
|
for node in ray.nodes():
|
||||||
|
print(" " + node.get("NodeManagerHostname", "unknown"))
|
||||||
|
|
||||||
|
config_name, config_dict, store_num, n, m = _sim_preps(config_file)
|
||||||
|
|
||||||
|
# Override number of simultaneous jobs if provided by config file
|
||||||
|
sim_jobs = config_dict.pop("sim_jobs", len(ray.nodes()) * num_cpu_per_task)
|
||||||
|
print(f"number of simultaneous jobs : {sim_jobs}")
|
||||||
|
|
||||||
|
if n * m < sim_jobs:
|
||||||
|
sim_jobs = n * m
|
||||||
|
|
||||||
|
# Initiate helper workers (a logger, a progress tracker to give estimates of
|
||||||
|
# completion time and an indexer to keep track of the individual files
|
||||||
|
# created after each simulation. The indexer can then automatically merge them)
|
||||||
|
pt = ray.remote(ProgressTracker).remote(max=n * m * store_num, auto_print=True, percent_incr=1)
|
||||||
|
indexer = ray.remote(io.tmp_index_manager).remote(
|
||||||
|
config_name=config_name, task_id=task_id, varying_keys=config_dict.get("varying", None)
|
||||||
|
)
|
||||||
|
ray.get(
|
||||||
|
logger.log.remote(f"CRITICAL FILE at {ray.get(indexer.get_path.remote())}, do not touch it")
|
||||||
|
)
|
||||||
|
RK4IP_parallel = ray.remote(RK4IP)
|
||||||
|
|
||||||
|
jobs = []
|
||||||
|
|
||||||
|
# we treat loops over different parameters differently
|
||||||
|
for k, dico in enumerate(utilities.dictionary_iterator(config_dict, varying_dict="varying")):
|
||||||
|
# loop over same parameter set
|
||||||
|
for i in range(n):
|
||||||
|
# because of random processes, initial conditions are recalculated every time
|
||||||
|
params = initialize.compute_init_parameters(dictionary=config_dict, replace=dico)
|
||||||
|
|
||||||
|
# make sure initial conditions are saved
|
||||||
|
params["init_P0"] = dico.get("P0", config_dict.get("P0", 0))
|
||||||
|
params["init_T0_FWHM"] = dico.get("T0_FWHM", config_dict.get("T0_FWHM", 0))
|
||||||
|
params["param_id"] = k
|
||||||
|
params_file_name = io.generate_file_path("param", i, k, task_id, "")
|
||||||
|
io.save_parameters(params, params_file_name)
|
||||||
|
ray.get(indexer.append_to_index.remote(k, params_file_name=params_file_name))
|
||||||
|
|
||||||
|
if len(jobs) >= sim_jobs:
|
||||||
|
# update the number of jobs if new nodes connect
|
||||||
|
sim_jobs = min(n * (m - k) - i, len(ray.nodes()) * num_cpu_per_task)
|
||||||
|
|
||||||
|
# print(f"Nodes in the Ray cluster: {len(ray.nodes())}, {sim_jobs} simultaneous jobs")
|
||||||
|
# for node in ray.nodes():
|
||||||
|
# print(" " + node.get("NodeManagerHostname", "unknown"))
|
||||||
|
|
||||||
|
# wait for a slot to free before starting a new job
|
||||||
|
_, jobs = ray.wait(jobs)
|
||||||
|
ray.get(_)
|
||||||
|
|
||||||
|
# start a new simulation
|
||||||
|
ray.get(
|
||||||
|
logger.log.remote(
|
||||||
|
f"Launching propagation of a {params.get('t0', 0) * 1e15:.2f}fs pulse with {np.max(abs2(params['field_0'])):.0f}W peak power over {np.max(params['z_targets'])}m"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
jobs.append(
|
||||||
|
RK4IP_parallel.remote(
|
||||||
|
params,
|
||||||
|
save_data=True,
|
||||||
|
job_id=i,
|
||||||
|
param_id=k,
|
||||||
|
task_id=task_id,
|
||||||
|
pt=pt,
|
||||||
|
indexer=indexer,
|
||||||
|
logger=logger,
|
||||||
|
n_percent=1,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
ray.get(logger.log.remote("number of running jobs : {}".format(len(jobs))))
|
||||||
|
ray.get(logger.log.remote(ray.get(pt.get_eta.remote())))
|
||||||
|
|
||||||
|
# wait for the last jobs to finish
|
||||||
|
ray.get(jobs)
|
||||||
|
|
||||||
|
# merge the data properly
|
||||||
|
folder_0 = ray.get(indexer.convert_sim_data.remote())
|
||||||
|
|
||||||
|
print(f"{config_name} successfully finished ! data saved in {folder_0}")
|
||||||
|
|
||||||
|
return folder_0
|
||||||
|
|
||||||
|
|
||||||
|
def simulate(config_file, task_id=0, n_percent=1):
|
||||||
|
"""runs simulations one after another
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
config_file : str
|
||||||
|
name of the config file
|
||||||
|
should be a json containing all necessary parameters for the simulation. Varying parameters should be placed in a subdictionary
|
||||||
|
called "varying" (see scgenerator.utilities.dictionary_iterator for details)
|
||||||
|
task_id : any formatable (int, string, float, ...)
|
||||||
|
give an id for book keeping purposes (must be set if multiple ray instances run at once so their files do not overlap)
|
||||||
|
n_percent : int or float
|
||||||
|
each individual simulation reports its progress every n_percent percent.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
name of the folder where the data is stored
|
||||||
|
"""
|
||||||
|
logger = io.Logger()
|
||||||
|
state.CurrentLogger.focus_logger(logger)
|
||||||
|
|
||||||
|
config_name, config_dict, store_num, n, m = _sim_preps(config_file)
|
||||||
|
|
||||||
|
# Initiate helper workers (a logger, a progress tracker to give estimates of
|
||||||
|
# completion time and an indexer to keep track of the individual files
|
||||||
|
# created after each simulation. The indexer can then automatically merge them)
|
||||||
|
pt = ProgressTracker(max=n * m * store_num, auto_print=True, percent_incr=1)
|
||||||
|
indexer = io.tmp_index_manager(
|
||||||
|
config_name=config_name, task_id=task_id, varying_keys=config_dict.get("varying", None)
|
||||||
|
)
|
||||||
|
logger.log(f"CRITICAL FILE at {indexer.get_path()}, do not touch it")
|
||||||
|
|
||||||
|
# we treat loops over different parameters differently
|
||||||
|
for k, dico in enumerate(utilities.dictionary_iterator(config_dict, varying_dict="varying")):
|
||||||
|
# loop over same parameter set
|
||||||
|
for i in range(n):
|
||||||
|
# because of random processes, initial conditions are recalculated every time
|
||||||
|
params = initialize.compute_init_parameters(dictionary=config_dict, replace=dico)
|
||||||
|
|
||||||
|
# make sure initial conditions are saved
|
||||||
|
params["init_P0"] = dico.get("P0", config_dict.get("P0", 0))
|
||||||
|
params["init_T0_FWHM"] = dico.get("T0_FWHM", config_dict.get("T0_FWHM", 0))
|
||||||
|
params["param_id"] = k
|
||||||
|
params_file_name = io.generate_file_path("param", i, k, task_id, "")
|
||||||
|
io.save_parameters(params, params_file_name)
|
||||||
|
indexer.append_to_index(k, params_file_name=params_file_name)
|
||||||
|
|
||||||
|
# start a new simulation
|
||||||
|
logger.log(
|
||||||
|
f"Launching propagation of a {params.get('t0', 0) * 1e15:.2f}fs pulse with {np.max(abs2(params['field_0'])):.0f}W peak power over {np.max(params['z_targets'])}m"
|
||||||
|
)
|
||||||
|
RK4IP(
|
||||||
|
params,
|
||||||
|
save_data=True,
|
||||||
|
job_id=i,
|
||||||
|
param_id=k,
|
||||||
|
task_id=task_id,
|
||||||
|
pt=pt,
|
||||||
|
indexer=indexer,
|
||||||
|
logger=logger,
|
||||||
|
n_percent=n_percent,
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.log(pt.get_eta())
|
||||||
|
|
||||||
|
# merge the data properly
|
||||||
|
folder_0 = indexer.convert_sim_data()
|
||||||
|
|
||||||
|
print(f"{config_name} successfully finished ! data saved in {folder_0}")
|
||||||
|
|
||||||
|
return folder_0
|
||||||
|
|
||||||
|
|
||||||
|
def _sim_preps(config_file):
|
||||||
|
# Load the config file
|
||||||
|
try:
|
||||||
|
with open(config_file, "r") as file:
|
||||||
|
config_dict = json.loads(file.read())
|
||||||
|
except FileNotFoundError:
|
||||||
|
print("No config file named {} found".format(config_file))
|
||||||
|
raise
|
||||||
|
|
||||||
|
# Store a master dictionary of parameters to generate file names and such
|
||||||
|
config_name = config_dict.pop("name", os.path.split(config_file)[-1][:-5])
|
||||||
|
|
||||||
|
# make sure we store spectra every time at the exact same place
|
||||||
|
if "z_targets" not in config_dict:
|
||||||
|
config_dict["z_targets"] = np.linspace(0, 1, 128)
|
||||||
|
config_dict["z_targets"] = initialize.sanitize_z_targets(config_dict["z_targets"])
|
||||||
|
config_dict = units.standardize_dictionary(config_dict)
|
||||||
|
store_num = len(config_dict["z_targets"])
|
||||||
|
|
||||||
|
# How many total simulations
|
||||||
|
n = int(config_dict.pop("n", 1))
|
||||||
|
m = np.prod([len(np.atleast_1d(ls)) for _, ls in config_dict.get("varying", {1: 1}).items()])
|
||||||
|
|
||||||
|
return config_name, config_dict, store_num, n, m
|
||||||
323
src/scgenerator/physics/units.py
Normal file
323
src/scgenerator/physics/units.py
Normal file
@@ -0,0 +1,323 @@
|
|||||||
|
# series of functions to convert different values to angular frequencies
|
||||||
|
# For example, nm(X) means "I give the number X in nm, figure out the ang. freq."
|
||||||
|
# to be used especially when giving plotting ranges : (400, 1400, nm), (-4, 8, ps), ...
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
from numpy import pi
|
||||||
|
|
||||||
|
c = 299792458.0
|
||||||
|
hbar = 1.05457148e-34
|
||||||
|
NA = 6.02214076e23
|
||||||
|
R = 8.31446261815324
|
||||||
|
kB = 1.380649e-23
|
||||||
|
epsilon0 = 8.85418781e-12
|
||||||
|
|
||||||
|
prefix = dict(P=1e12, G=1e9, M=1e6, k=1e3, d=1e-1, c=1e-2, m=1e-3, u=1e-6, n=1e-9, p=1e-12, f=1e-15)
|
||||||
|
|
||||||
|
"""
|
||||||
|
Below are common units. You can define your own unit function
|
||||||
|
this function must have a few porperties:
|
||||||
|
inv : function
|
||||||
|
inverse of the function. example :
|
||||||
|
um(1) -> 883651567308853.2
|
||||||
|
um.inv(883651567308853.2) -> 1.0
|
||||||
|
label : str
|
||||||
|
label to be displayed on plot
|
||||||
|
type : ("WL", "FREQ", "AFREQ", "TIME", "OTHER")
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def m(l):
|
||||||
|
return 2 * pi * c / l
|
||||||
|
|
||||||
|
|
||||||
|
m.inv = m
|
||||||
|
m.label = r"Wavelength $\lambda$ (m)"
|
||||||
|
m.type = "WL"
|
||||||
|
|
||||||
|
|
||||||
|
def nm(l):
|
||||||
|
return 2 * pi * c / (l * 1e-9)
|
||||||
|
|
||||||
|
|
||||||
|
nm.inv = nm
|
||||||
|
nm.label = r"Wavelength $\lambda$ (nm)"
|
||||||
|
nm.type = "WL"
|
||||||
|
|
||||||
|
|
||||||
|
def um(l):
|
||||||
|
return 2 * pi * c / (l * 1e-6)
|
||||||
|
|
||||||
|
|
||||||
|
um.inv = um
|
||||||
|
um.label = r"Wavelength $\lambda$ ($\mathrm{\mu}$m)"
|
||||||
|
um.type = "WL"
|
||||||
|
|
||||||
|
|
||||||
|
def THz(f):
|
||||||
|
return 1e12 * 2 * pi * f
|
||||||
|
|
||||||
|
|
||||||
|
THz.inv = lambda w: w / (1e12 * 2 * pi)
|
||||||
|
THz.label = r"Frequency $f$ (THz)"
|
||||||
|
THz.type = "FREQ"
|
||||||
|
|
||||||
|
|
||||||
|
def PHz(f):
|
||||||
|
return 1e15 * 2 * pi * f
|
||||||
|
|
||||||
|
|
||||||
|
PHz.inv = lambda w: w / (1e15 * 2 * pi)
|
||||||
|
PHz.label = r"Frequency $f$ (PHz)"
|
||||||
|
PHz.type = "FREQ"
|
||||||
|
|
||||||
|
|
||||||
|
def rad_s(w):
|
||||||
|
return w
|
||||||
|
|
||||||
|
|
||||||
|
rad_s.inv = rad_s
|
||||||
|
rad_s.label = r"Angular frequency $\omega$ ($\frac{\mathrm{rad}}{\mathrm{s}}$)"
|
||||||
|
rad_s.type = "AFREQ"
|
||||||
|
|
||||||
|
|
||||||
|
def Prad_s(w):
|
||||||
|
return w * 1e15
|
||||||
|
|
||||||
|
|
||||||
|
Prad_s.inv = lambda w: 1e-15 * w
|
||||||
|
Prad_s.label = r"Angular frequency $\omega$ ($\frac{\mathrm{Prad}}{\mathrm{s}}$)"
|
||||||
|
Prad_s.type = "AFREQ"
|
||||||
|
|
||||||
|
|
||||||
|
def rel_time(t):
|
||||||
|
return t
|
||||||
|
|
||||||
|
|
||||||
|
rel_time.inv = rel_time
|
||||||
|
rel_time.label = r"relative time ${\tau}/{\tau_\mathrm{0, FWHM}}$"
|
||||||
|
rel_time.type = "TIME"
|
||||||
|
|
||||||
|
|
||||||
|
def rel_freq(f):
|
||||||
|
return f
|
||||||
|
|
||||||
|
|
||||||
|
rel_freq.inv = rel_freq
|
||||||
|
rel_freq.label = r"relative angular freq. $(\omega - \omega_0)/\Delta\omega_0$"
|
||||||
|
rel_freq.type = "FREQ"
|
||||||
|
|
||||||
|
|
||||||
|
def s(t):
|
||||||
|
return t
|
||||||
|
|
||||||
|
|
||||||
|
s.inv = s
|
||||||
|
s.label = r"Time $t$ (s)"
|
||||||
|
s.type = "TIME"
|
||||||
|
|
||||||
|
|
||||||
|
def us(t):
|
||||||
|
return t * 1e-6
|
||||||
|
|
||||||
|
|
||||||
|
us.inv = lambda t: t * 1e6
|
||||||
|
us.label = r"Time $t$ (us)"
|
||||||
|
us.type = "TIME"
|
||||||
|
|
||||||
|
|
||||||
|
def ns(t):
|
||||||
|
return t * 1e-9
|
||||||
|
|
||||||
|
|
||||||
|
ns.inv = lambda t: t * 1e9
|
||||||
|
ns.label = r"Time $t$ (ns)"
|
||||||
|
ns.type = "TIME"
|
||||||
|
|
||||||
|
|
||||||
|
def ps(t):
|
||||||
|
return t * 1e-12
|
||||||
|
|
||||||
|
|
||||||
|
ps.inv = lambda t: t * 1e12
|
||||||
|
ps.label = r"Time $t$ (ps)"
|
||||||
|
ps.type = "TIME"
|
||||||
|
|
||||||
|
|
||||||
|
def fs(t):
|
||||||
|
return t * 1e-15
|
||||||
|
|
||||||
|
|
||||||
|
fs.inv = lambda t: t * 1e15
|
||||||
|
fs.label = r"Time $t$ (fs)"
|
||||||
|
fs.type = "TIME"
|
||||||
|
|
||||||
|
|
||||||
|
def inv(x):
|
||||||
|
return 1 / x
|
||||||
|
|
||||||
|
|
||||||
|
inv.inv = inv
|
||||||
|
inv.label = "inverse"
|
||||||
|
inv.type = "WL"
|
||||||
|
|
||||||
|
|
||||||
|
def bar(p):
|
||||||
|
return 1e5 * p
|
||||||
|
|
||||||
|
|
||||||
|
bar.inv = lambda p: 1e-5 * p
|
||||||
|
bar.label = "Pressure (bar)"
|
||||||
|
bar.type = "PRESSURE"
|
||||||
|
|
||||||
|
|
||||||
|
def beta2_fs_cm(b2):
|
||||||
|
return 1e-28 * b2
|
||||||
|
|
||||||
|
|
||||||
|
beta2_fs_cm.inv = lambda b2: 1e28 * b2
|
||||||
|
beta2_fs_cm.label = r"$\beta_2$ (fs$^2$/cm)"
|
||||||
|
beta2_fs_cm.type = "OTHER"
|
||||||
|
|
||||||
|
|
||||||
|
def beta2_ps_km(b2):
|
||||||
|
return 1e-27 * b2
|
||||||
|
|
||||||
|
|
||||||
|
beta2_ps_km.inv = lambda b2: 1e27 * b2
|
||||||
|
beta2_ps_km.label = r"$\beta_2$ (ps$^2$/km)"
|
||||||
|
beta2_ps_km.type = "OTHER"
|
||||||
|
|
||||||
|
|
||||||
|
def D_ps_nm_km(D):
|
||||||
|
return 1e-6 * D
|
||||||
|
|
||||||
|
|
||||||
|
D_ps_nm_km.inv = lambda D: 1e6 * D
|
||||||
|
D_ps_nm_km.label = r"$D$ (ps/(nm km))"
|
||||||
|
D_ps_nm_km.type = "OTHER"
|
||||||
|
|
||||||
|
|
||||||
|
def beta2_coef(beta):
|
||||||
|
fac = 1e27
|
||||||
|
out = np.zeros_like(beta)
|
||||||
|
for i, b in enumerate(beta):
|
||||||
|
out[i] = fac * b
|
||||||
|
fac *= 1e12
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def standardize_dictionary(dico):
|
||||||
|
"""convert lists of number and units into a float with SI units inside a dictionary
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
dico : a dictionary
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
same dictionary with units converted
|
||||||
|
Example
|
||||||
|
----------
|
||||||
|
standardize_dictionary({"power": [23, "kW"], "points": [1, 2, 3]})
|
||||||
|
{"power": 23000, "points": [1, 2, 3]})
|
||||||
|
"""
|
||||||
|
for key, item in dico.items():
|
||||||
|
if isinstance(item, list) and len(item) == 2 and isinstance(item[0], (int, float)) and isinstance(item[1], str):
|
||||||
|
num, unit = item
|
||||||
|
fac = 1
|
||||||
|
if len(unit) == 2:
|
||||||
|
fac = prefix[unit[0]]
|
||||||
|
elif unit == "bar":
|
||||||
|
fac = 1e5
|
||||||
|
dico[key] = num * fac
|
||||||
|
return dico
|
||||||
|
|
||||||
|
|
||||||
|
def sort_axis(axis, plt_range):
|
||||||
|
"""
|
||||||
|
given an axis, returns this axis cropped according to the given range, converted and sorted
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
axis : 1D array containing the original axis (usual the w or t array)
|
||||||
|
plt_range : tupple (min, max, conversion_function) used to crop the axis
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
cropped : the axis cropped, converted and sorted
|
||||||
|
indices : indices to use to slice and sort other array in the same fashion
|
||||||
|
extent : tupple with min and max of cropped
|
||||||
|
Example
|
||||||
|
----------
|
||||||
|
w = np.append(np.linspace(0, -10, 20), np.linspace(0, 10, 20))
|
||||||
|
t = np.linspace(-10, 10, 400)
|
||||||
|
W, T = np.meshgrid(w, t)
|
||||||
|
y = np.exp(-W**2 - T**2)
|
||||||
|
|
||||||
|
# Define ranges
|
||||||
|
rw = (-4, 4, s)
|
||||||
|
rt = (-2, 6, s)
|
||||||
|
|
||||||
|
w, cw = sort_axis(w, rw)
|
||||||
|
t, ct = sort_axis(t, rt)
|
||||||
|
|
||||||
|
# slice y according to the given ranges
|
||||||
|
y = y[ct][:, cw]
|
||||||
|
"""
|
||||||
|
|
||||||
|
r = np.array(plt_range[:2], dtype="float")
|
||||||
|
func = plt_range[2]
|
||||||
|
|
||||||
|
indices = np.arange(len(axis))[(axis <= np.max(func(r))) & (axis >= np.min(func(r)))]
|
||||||
|
cropped = axis[indices]
|
||||||
|
order = np.argsort(func.inv(cropped))
|
||||||
|
indices = indices[order]
|
||||||
|
cropped = cropped[order]
|
||||||
|
out_ax = func.inv(cropped)
|
||||||
|
|
||||||
|
return out_ax, indices, (out_ax[0], out_ax[-1])
|
||||||
|
|
||||||
|
|
||||||
|
def to_WL(spectrum, frep, lambda_):
|
||||||
|
"""
|
||||||
|
When a spectrogram is displayed as function of wl instead of frequency, we
|
||||||
|
need to adjust the amplitude of each bin for the integral over the whole frequency
|
||||||
|
range to match.
|
||||||
|
"""
|
||||||
|
m = 2 * pi * c / (lambda_ ** 2) * frep * spectrum
|
||||||
|
return m
|
||||||
|
|
||||||
|
|
||||||
|
def to_log(arr, ref=None):
|
||||||
|
"""takes the log of each 1D array relative to the max of said array. Useful
|
||||||
|
to plot spectrum evolution, but use to_log2D for spectrograms
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
arr : 1D array of real numbers. >1D array : operation is applied on axis=0
|
||||||
|
ref : reference value corresponding to 0dB (default : max(arr))
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
arr array in dB
|
||||||
|
"""
|
||||||
|
if arr.ndim > 1:
|
||||||
|
return np.apply_along_axis(to_log, -1, arr, ref)
|
||||||
|
else:
|
||||||
|
if ref is None:
|
||||||
|
ref = np.max(arr)
|
||||||
|
m = arr / ref
|
||||||
|
m = 10 * np.log10(m, out=np.zeros_like(m) - 100, where=m > 0)
|
||||||
|
return m
|
||||||
|
|
||||||
|
|
||||||
|
def to_log2D(arr, ref=None):
|
||||||
|
"""computes the log of a 2D array
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
arr : 2D array of real numbers
|
||||||
|
ref : reference value corresponding to 0dB
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
arr array in dB
|
||||||
|
"""
|
||||||
|
if ref is None:
|
||||||
|
ref = np.max(arr)
|
||||||
|
m = arr / ref
|
||||||
|
m = 10 * np.log10(m, out=np.zeros_like(m) - 100, where=m > 0)
|
||||||
|
return m
|
||||||
927
src/scgenerator/plotting.py
Normal file
927
src/scgenerator/plotting.py
Normal file
@@ -0,0 +1,927 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
import matplotlib.gridspec as gs
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
from matplotlib.colors import ListedColormap
|
||||||
|
from scipy.interpolate import UnivariateSpline
|
||||||
|
|
||||||
|
from . import io, math, state
|
||||||
|
from .math import abs2, make_uniform_1D, span
|
||||||
|
from .physics import pulse, units
|
||||||
|
|
||||||
|
|
||||||
|
def draw_across(ax1, xy1, ax2, xy2, clip_on=False, **kwargs):
|
||||||
|
"""draws a line across 2 axes
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
ax1, ax2 : axis objects
|
||||||
|
xy1, xy2 : tupple (float, float)
|
||||||
|
The end positions in data coordinates (from their respective axis)
|
||||||
|
**kwargs : arrowprops kwargs
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
None
|
||||||
|
"""
|
||||||
|
ax1.annotate(
|
||||||
|
"",
|
||||||
|
xy=xy1,
|
||||||
|
xytext=xy2,
|
||||||
|
xycoords=ax1.transData,
|
||||||
|
textcoords=ax2.transData,
|
||||||
|
arrowprops=dict(arrowstyle="-", clip_on=clip_on, **kwargs),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def zoom(ax, zoom_ax, clip_on=False, **kwargs):
|
||||||
|
l, r = zoom_ax.get_xlim()
|
||||||
|
b, t = zoom_ax.get_ylim()
|
||||||
|
draw_across(ax, (l, b), zoom_ax, (l, b), clip_on=clip_on, **kwargs)
|
||||||
|
draw_across(ax, (l, t), zoom_ax, (l, t), clip_on=clip_on, **kwargs)
|
||||||
|
draw_across(ax, (r, l), zoom_ax, (r, l), clip_on=clip_on, **kwargs)
|
||||||
|
draw_across(ax, (r, t), zoom_ax, (r, t), clip_on=clip_on, **kwargs)
|
||||||
|
ax.plot([l, l, r, r], [b, t, t, b], **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def create_zoom_axis(
|
||||||
|
axis, xlim, ylim=None, width_ratios=[1, 1, 1], height_ratios=[1, 1, 1], frame_style=dict(c="k", lw=0.5), plot=True
|
||||||
|
):
|
||||||
|
"""creates a zoomed in plot inside a plot. Should be called as a last step as parent axis limits will be locked
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
axis : parent axis object
|
||||||
|
xlim : tupple
|
||||||
|
limits in parent axis data coordinates
|
||||||
|
ylim : tupple, optional
|
||||||
|
width_ratios, height_ration : lists of len 3
|
||||||
|
cut the parent axis in 3x3 cells with these ratios, the center one will be the new axis
|
||||||
|
frame_style : dict, optional
|
||||||
|
plot : bool, optional
|
||||||
|
whether to copy the lines or return an empty axis
|
||||||
|
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
the new axis
|
||||||
|
"""
|
||||||
|
axis.set_xlim(axis.get_xlim())
|
||||||
|
axis.set_ylim(axis.get_ylim())
|
||||||
|
|
||||||
|
# set up the axis
|
||||||
|
grid = gs.GridSpecFromSubplotSpec(
|
||||||
|
3, 3, subplot_spec=axis, width_ratios=width_ratios, height_ratios=height_ratios, hspace=0, wspace=0
|
||||||
|
)
|
||||||
|
inset = axis.get_figure().add_subplot(grid[1, 1])
|
||||||
|
width_ratios = np.cumsum(np.array(width_ratios) / np.sum(width_ratios))
|
||||||
|
height_ratios = np.cumsum(np.array(height_ratios) / np.sum(height_ratios))
|
||||||
|
|
||||||
|
# copy the plot content
|
||||||
|
if plot:
|
||||||
|
lines = axis.get_lines()
|
||||||
|
ymin, ymax = 0, 0
|
||||||
|
for line in lines:
|
||||||
|
xdata = line.get_xdata()
|
||||||
|
xdata, ind, _ = units.sort_axis(xdata, (*xlim, units.s))
|
||||||
|
ydata = line.get_ydata()[ind]
|
||||||
|
inset.plot(xdata, ydata, c=line.get_color(), ls=line.get_linestyle(), lw=line.get_linewidth())
|
||||||
|
inset.set_xlim(xlim)
|
||||||
|
if ylim is not None:
|
||||||
|
inset.set_ylim(ylim)
|
||||||
|
ylim = inset.get_ylim()
|
||||||
|
elif ylim is None:
|
||||||
|
raise ValueError("ylim is mandatory when not plotting")
|
||||||
|
|
||||||
|
# draw the box in parent axis
|
||||||
|
dx = math.length(axis.get_xlim())
|
||||||
|
dy = math.length(axis.get_ylim())
|
||||||
|
l, r = xlim
|
||||||
|
b, t = ylim
|
||||||
|
axis.plot([l, l, r, r, l], [b, t, t, b, b], **frame_style)
|
||||||
|
|
||||||
|
# draw lines connecting the box to the new axis
|
||||||
|
ll = axis.get_xlim()[0] + width_ratios[0] * dx
|
||||||
|
rr = axis.get_xlim()[0] + width_ratios[1] * dx
|
||||||
|
bb = axis.get_ylim()[1] - height_ratios[1] * dy
|
||||||
|
tt = axis.get_ylim()[1] - height_ratios[0] * dy
|
||||||
|
|
||||||
|
axis.plot([l, ll], [t, tt], **frame_style)
|
||||||
|
axis.plot([l, ll], [b, bb], **frame_style)
|
||||||
|
axis.plot([r, rr], [t, tt], **frame_style)
|
||||||
|
axis.plot([r, rr], [b, bb], **frame_style)
|
||||||
|
|
||||||
|
return inset
|
||||||
|
|
||||||
|
|
||||||
|
def corner_annotation(text, ax, position="tl", rel_x_offset=0.05, rel_y_offset=0.05, **text_kwargs):
|
||||||
|
"""puts an annotatin in a corner of an ax
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
text : str
|
||||||
|
text to put in the corner
|
||||||
|
ax : matplotlib axis object
|
||||||
|
position : str {"tl", "tr", "bl", "br"}
|
||||||
|
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
nothing
|
||||||
|
"""
|
||||||
|
# xlim = ax.get_xlim()
|
||||||
|
# ylim = ax.get_ylim()
|
||||||
|
|
||||||
|
# xoff = length(xlim) * rel_x_offset
|
||||||
|
# yoff = length(ylim) * rel_y_offset
|
||||||
|
|
||||||
|
if position[0] == "t":
|
||||||
|
y = 1 - rel_y_offset
|
||||||
|
va = "top"
|
||||||
|
else:
|
||||||
|
y = 0 + rel_y_offset
|
||||||
|
va = "bottom"
|
||||||
|
if position[1] == "l":
|
||||||
|
x = 0 + rel_x_offset
|
||||||
|
ha = "left"
|
||||||
|
else:
|
||||||
|
x = 1 - rel_x_offset
|
||||||
|
ha = "right"
|
||||||
|
|
||||||
|
ax.annotate(
|
||||||
|
text,
|
||||||
|
(x, y),
|
||||||
|
(x, y),
|
||||||
|
xycoords="axes fraction",
|
||||||
|
textcoords="axes fraction",
|
||||||
|
verticalalignment=va,
|
||||||
|
horizontalalignment=ha,
|
||||||
|
**text_kwargs,
|
||||||
|
)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _finish_plot_2D(
|
||||||
|
values,
|
||||||
|
x_axis,
|
||||||
|
x_label,
|
||||||
|
y_axis,
|
||||||
|
y_label,
|
||||||
|
log,
|
||||||
|
vmin,
|
||||||
|
vmax,
|
||||||
|
transpose,
|
||||||
|
cmap,
|
||||||
|
cbar_label,
|
||||||
|
ax,
|
||||||
|
file_name,
|
||||||
|
file_type,
|
||||||
|
params,
|
||||||
|
):
|
||||||
|
|
||||||
|
# apply log transform if required
|
||||||
|
if log != False:
|
||||||
|
vmax = state.plot_default_vmax if vmax is None else vmax
|
||||||
|
vmin = state.plot_default_vmin if vmin is None else vmin
|
||||||
|
if isinstance(log, (float, int)) and log != True:
|
||||||
|
values = units.to_log(values, ref=log)
|
||||||
|
|
||||||
|
elif log == "2D":
|
||||||
|
values = units.to_log2D(values)
|
||||||
|
|
||||||
|
elif log == "1D":
|
||||||
|
values = np.apply_along_axis(units.to_log, 1, values)
|
||||||
|
|
||||||
|
elif log == "smooth 1D":
|
||||||
|
ref = np.max(values, axis=1)
|
||||||
|
ind = np.argmax((ref[:-1] - ref[1:]) < 0)
|
||||||
|
values = units.to_log(values, ref=np.max(ref[ind:]))
|
||||||
|
|
||||||
|
elif log == "unique 1D":
|
||||||
|
try:
|
||||||
|
ref = _finish_plot_2D.ref
|
||||||
|
print(f"recovered reference value {ref} for log plot")
|
||||||
|
except AttributeError:
|
||||||
|
ref = np.max(values, axis=1)
|
||||||
|
ind = np.argmax((ref[:-1] - ref[1:]) < 0)
|
||||||
|
ref = np.max(ref[ind:])
|
||||||
|
_finish_plot_2D.ref = ref
|
||||||
|
|
||||||
|
values = units.to_log(values, ref=ref)
|
||||||
|
cmap = state.plot_default_cmap if cmap is None else cmap
|
||||||
|
|
||||||
|
is_new_plot = ax is None
|
||||||
|
cbar_ax = None
|
||||||
|
if isinstance(ax, tuple) and len(ax) > 1:
|
||||||
|
ax, cbar_ax = ax[0], ax[1]
|
||||||
|
|
||||||
|
folder_name = ""
|
||||||
|
if is_new_plot:
|
||||||
|
folder_name, file_name, fig, ax = io.plot_setup(file_name=file_name, file_type=file_type, params=params)
|
||||||
|
else:
|
||||||
|
fig = ax.get_figure()
|
||||||
|
|
||||||
|
# Determine grid extent and spacing to be able to center
|
||||||
|
# each pixel since by default imshow draws values at the lower-left corner
|
||||||
|
if transpose:
|
||||||
|
dy = x_axis[1] - x_axis[0]
|
||||||
|
ext_y = span(x_axis)
|
||||||
|
dx = y_axis[1] - y_axis[0]
|
||||||
|
ext_x = span(y_axis)
|
||||||
|
values = values.T
|
||||||
|
ax.set_xlabel(y_label)
|
||||||
|
ax.set_ylabel(x_label)
|
||||||
|
else:
|
||||||
|
dx = x_axis[1] - x_axis[0]
|
||||||
|
ext_x = span(x_axis)
|
||||||
|
dy = y_axis[1] - y_axis[0]
|
||||||
|
ext_y = span(y_axis)
|
||||||
|
ax.set_ylabel(y_label)
|
||||||
|
ax.set_xlabel(x_label)
|
||||||
|
|
||||||
|
ax.set_xlim(*ext_x)
|
||||||
|
ax.set_ylim(*ext_y)
|
||||||
|
|
||||||
|
interpolation = params.get("plot.interpolation", state.plot_default_2D_interpolation)
|
||||||
|
im = ax.imshow(
|
||||||
|
values,
|
||||||
|
extent=[ext_x[0] - dx / 2, ext_x[1] + dx / 2, ext_y[0] - dy / 2, ext_y[1] + dy / 2],
|
||||||
|
cmap=cmap,
|
||||||
|
vmin=vmin,
|
||||||
|
vmax=vmax,
|
||||||
|
origin="lower",
|
||||||
|
interpolation=interpolation,
|
||||||
|
aspect="auto",
|
||||||
|
)
|
||||||
|
|
||||||
|
cbar = None
|
||||||
|
if cbar_label is not None:
|
||||||
|
if cbar_ax is None:
|
||||||
|
cbar = fig.colorbar(im, ax=ax, orientation="vertical")
|
||||||
|
else:
|
||||||
|
cbar = fig.colorbar(im, cax=cbar_ax, orientation="vertical")
|
||||||
|
cbar.ax.set_ylabel(cbar_label)
|
||||||
|
|
||||||
|
if is_new_plot:
|
||||||
|
fig.savefig(os.path.join(folder_name, file_name), bbox_inches="tight", dpi=200)
|
||||||
|
print(f"plot saved in {os.path.join(folder_name, file_name)}")
|
||||||
|
if cbar_label is not None:
|
||||||
|
return fig, ax, cbar.ax
|
||||||
|
else:
|
||||||
|
return fig, ax
|
||||||
|
|
||||||
|
|
||||||
|
def plot_spectrogram(
|
||||||
|
values,
|
||||||
|
x_range,
|
||||||
|
y_range,
|
||||||
|
params,
|
||||||
|
t_res=None,
|
||||||
|
gate_width=None,
|
||||||
|
log=True,
|
||||||
|
vmin=None,
|
||||||
|
vmax=None,
|
||||||
|
cbar_label="normalized intensity (dB)",
|
||||||
|
file_type="png",
|
||||||
|
file_name=None,
|
||||||
|
cmap=None,
|
||||||
|
ax=None,
|
||||||
|
):
|
||||||
|
"""Plots a spectrogram given a complex field in the time domain
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
values : 2D array
|
||||||
|
axis 0 defines the position in the fiber and axis 1 the position in time, frequency or wl
|
||||||
|
example : [[1, 2, 3], [0, 1, 0]] describes a quantity at 3 different freq/time and at two locations in the fiber
|
||||||
|
x_range, y_range : tupple (min, max, units)
|
||||||
|
one of them must be time, the other one must be wl/freq
|
||||||
|
min, max : int or float
|
||||||
|
minimum and maximum values given in the desired units
|
||||||
|
units : function to convert from the desired units to rad/s or to time.
|
||||||
|
common functions are already defined in scgenerator.physics.units
|
||||||
|
look there for more details
|
||||||
|
params : dict
|
||||||
|
parameters of the simulations
|
||||||
|
log : bool, optional
|
||||||
|
whether to compute the logarithm of the spectrogram
|
||||||
|
vmin : float, optional
|
||||||
|
min value of the colorbar
|
||||||
|
vmax : float, optional
|
||||||
|
max value of the colorbar
|
||||||
|
cbar_label : str or None
|
||||||
|
label of the colorbar. Will not draw colorbar if None
|
||||||
|
file_type : str, optional
|
||||||
|
usually pdf or png
|
||||||
|
plt_name : str, optional
|
||||||
|
special name to give to the plot. A name is automatically assigned anyway
|
||||||
|
cmap : str, optional
|
||||||
|
colormap to be used in matplotlib.pyplot.imshow
|
||||||
|
ax : matplotlib.axes._subplots.AxesSubplot object or tupple of 2 axis objects, optional
|
||||||
|
axis on which to draw the plot
|
||||||
|
if only one is given, a new one will be created to draw the colorbar
|
||||||
|
|
||||||
|
"""
|
||||||
|
if values.ndim != 1:
|
||||||
|
print("plot_spectrogram can only plot 1D arrays")
|
||||||
|
return
|
||||||
|
|
||||||
|
if (x_range[2].type == "TIME") == (y_range[2].type == "TIME"):
|
||||||
|
print("exactly one range must be a time range")
|
||||||
|
return
|
||||||
|
|
||||||
|
log = "2D" if log in ["2D", True] else False
|
||||||
|
|
||||||
|
# 0 axis means x-axis -> determine final orientation of spectrogram
|
||||||
|
time_axis = 0 if x_range[2].type not in ["WL", "FREQ", "AFREQ"] else 1
|
||||||
|
if time_axis == 0:
|
||||||
|
t_range, f_range = x_range, y_range
|
||||||
|
else:
|
||||||
|
t_range, f_range = y_range, x_range
|
||||||
|
|
||||||
|
# Actually compute the spectrogram
|
||||||
|
t_win = 2 * np.max(t_range[2](np.abs(t_range[:2])))
|
||||||
|
spec_kwargs = dict(t_res=t_res, t_win=t_win, gate_width=gate_width, shift=False)
|
||||||
|
spec, new_t = pulse.spectrogram(
|
||||||
|
params["t"].copy(), values, **{k: v for k, v in spec_kwargs.items() if v is not None}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Crop and reoder axis
|
||||||
|
new_t, ind_t, _ = units.sort_axis(new_t, t_range)
|
||||||
|
new_f, ind_f, _ = units.sort_axis(params["w"], f_range)
|
||||||
|
values = spec[ind_t][:, ind_f]
|
||||||
|
if f_range[2].type == "WL":
|
||||||
|
values = np.apply_along_axis(units.to_WL, 1, values, params["frep"], units.m(f_range[2].inv(new_f)))
|
||||||
|
values = np.apply_along_axis(make_uniform_1D, 1, values, new_f)
|
||||||
|
|
||||||
|
if time_axis == 0:
|
||||||
|
x_axis, y_axis = new_t, new_f
|
||||||
|
values = values.T
|
||||||
|
else:
|
||||||
|
x_axis, y_axis = new_f, new_t
|
||||||
|
|
||||||
|
return _finish_plot_2D(
|
||||||
|
values,
|
||||||
|
x_axis,
|
||||||
|
x_range[2].label,
|
||||||
|
y_axis,
|
||||||
|
y_range[2].label,
|
||||||
|
log,
|
||||||
|
vmin,
|
||||||
|
vmax,
|
||||||
|
False,
|
||||||
|
cmap,
|
||||||
|
cbar_label,
|
||||||
|
ax,
|
||||||
|
file_name,
|
||||||
|
file_type,
|
||||||
|
params,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def plot_results_2D(
|
||||||
|
values,
|
||||||
|
plt_range,
|
||||||
|
params,
|
||||||
|
log="1D",
|
||||||
|
skip=16,
|
||||||
|
vmin=None,
|
||||||
|
vmax=None,
|
||||||
|
transpose=False,
|
||||||
|
cbar_label="normalized intensity (dB)",
|
||||||
|
file_type="png",
|
||||||
|
file_name=None,
|
||||||
|
cmap=None,
|
||||||
|
ax=None,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
plots 2D arrays and automatically saves the plots, as well as returns it
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
values : 2D array
|
||||||
|
axis 0 defines the position in the fiber and axis 1 the position in time, frequency or wl
|
||||||
|
example : [[1, 2, 3], [0, 1, 0]] describes a quantity at 3 different freq/time and at two locations in the fiber
|
||||||
|
plt_range : tupple (min, max, units)
|
||||||
|
min, max : int or float
|
||||||
|
minimum and maximum values given in the desired units
|
||||||
|
units : function to convert from the desired units to rad/s or to time.
|
||||||
|
common functions are already defined in scgenerator.physics.units
|
||||||
|
look there for more details
|
||||||
|
params : dict
|
||||||
|
parameters of the simulations
|
||||||
|
log : str {"1D", "2D", "smooth 1D"} or int, float or bool, optional
|
||||||
|
str : plot in dB
|
||||||
|
1D : takes the log for every slice
|
||||||
|
2D : takes the log for the whole 2D array
|
||||||
|
smooth 1D : figures out a smart reference value for the whole 2D array
|
||||||
|
int, float : plot in dB
|
||||||
|
reference value
|
||||||
|
bool : whether to use 1D variant or nothing
|
||||||
|
skip : int, optional
|
||||||
|
take 1 every skip values along the -1 axis
|
||||||
|
vmin : float, optional
|
||||||
|
min value of the colorbar
|
||||||
|
vmax : float, optional
|
||||||
|
max value of the colorbar
|
||||||
|
cbar_label : str or None
|
||||||
|
label of the colorbar. Will not draw colorbar if None
|
||||||
|
file_type : str, optional
|
||||||
|
usually pdf or png
|
||||||
|
plt_name : str, optional
|
||||||
|
special name to give to the plot. A name is automatically assigned anyway
|
||||||
|
cmap : str, optional
|
||||||
|
colormap to be used in matplotlib.pyplot.imshow
|
||||||
|
ax : matplotlib.axes._subplots.AxesSubplot object or tupple of 2 axis objects, optional
|
||||||
|
axis on which to draw the plot
|
||||||
|
if only one is given, a new one will be created to draw the colorbar
|
||||||
|
returns
|
||||||
|
fig, ax : matplotlib objects containing the plots
|
||||||
|
example:
|
||||||
|
if spectra is a (m, n, nt) array, one can plot a spectrum evolution as such:
|
||||||
|
>>> fig, ax = plot_results_2D(spectra[:, -1], (600, 1600, nm), log=True, "Heidt2017")
|
||||||
|
"""
|
||||||
|
|
||||||
|
if values.ndim != 2:
|
||||||
|
print(f"Shape was {values.shape}. plot_results_2D can only plot 2D arrays")
|
||||||
|
return
|
||||||
|
|
||||||
|
is_spectrum = values.dtype == "complex"
|
||||||
|
|
||||||
|
if plt_range[2].type in ["WL", "FREQ", "AFREQ"]:
|
||||||
|
x_axis = params["w"].copy()
|
||||||
|
else:
|
||||||
|
x_axis = params["t"].copy()
|
||||||
|
|
||||||
|
# crop and convert
|
||||||
|
x_axis, ind, ext = units.sort_axis(x_axis[::skip], plt_range)
|
||||||
|
values = values[:, ::skip][:, ind]
|
||||||
|
if is_spectrum:
|
||||||
|
values = abs2(values)
|
||||||
|
|
||||||
|
# make uniform if converting to wavelength
|
||||||
|
if plt_range[2].type == "WL":
|
||||||
|
if is_spectrum:
|
||||||
|
values = np.apply_along_axis(units.to_WL, 1, values, params.get("frep", 1), x_axis)
|
||||||
|
values = np.array([make_uniform_1D(v, x_axis, n=len(x_axis), method="linear") for v in values])
|
||||||
|
|
||||||
|
return _finish_plot_2D(
|
||||||
|
values,
|
||||||
|
x_axis,
|
||||||
|
plt_range[2].label,
|
||||||
|
params["z_targets"],
|
||||||
|
"propagation distance (m)",
|
||||||
|
log,
|
||||||
|
vmin,
|
||||||
|
vmax,
|
||||||
|
transpose,
|
||||||
|
cmap,
|
||||||
|
cbar_label,
|
||||||
|
ax,
|
||||||
|
file_name,
|
||||||
|
file_type,
|
||||||
|
params,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def plot_results_1D(
|
||||||
|
values,
|
||||||
|
plt_range,
|
||||||
|
params,
|
||||||
|
log=False,
|
||||||
|
spacing=1,
|
||||||
|
vmin=None,
|
||||||
|
vmax=None,
|
||||||
|
ylabel=None,
|
||||||
|
yscaling=1,
|
||||||
|
file_type="pdf",
|
||||||
|
file_name=None,
|
||||||
|
ax=None,
|
||||||
|
line_label=None,
|
||||||
|
transpose=False,
|
||||||
|
**line_kwargs,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
values : 1D array
|
||||||
|
if values are complex, the abs^2 is computed before plotting
|
||||||
|
plt_range : tupple (min, max, units)
|
||||||
|
min, max : int or float
|
||||||
|
minimum and maximum values given in the desired units
|
||||||
|
units : function to convert from the desired units to rad/s or to time.
|
||||||
|
common functions are already defined in scgenerator.physics.units
|
||||||
|
look there for more details
|
||||||
|
params : dict
|
||||||
|
parameters of the simulations
|
||||||
|
log : str {"1D"} or int, float or bool, optional
|
||||||
|
str : plot in dB
|
||||||
|
1D : takes the log for every slice
|
||||||
|
int, float : plot in dB
|
||||||
|
reference value
|
||||||
|
bool : whether to use 1D variant or nothing
|
||||||
|
spacing : int, float, optional
|
||||||
|
tells the function to take one value every `spacing` one available. If a float is given, it will interpolate with a spline.
|
||||||
|
vmin : float, optional
|
||||||
|
min value of the colorbar
|
||||||
|
vmax : float, optional
|
||||||
|
max value of the colorbar
|
||||||
|
ylabel : str, optional
|
||||||
|
label of the y axis (x axis in transposed mode). Default is "normalized intensity (dB)" for log plots
|
||||||
|
yscaling : float, optional
|
||||||
|
scale the y values by this amount
|
||||||
|
file_type : str, optional
|
||||||
|
usually pdf or png
|
||||||
|
plt_name : str, optional
|
||||||
|
special name to give to the plot. A name is automatically assigned anyway
|
||||||
|
ax : matplotlib.axes._subplots.AxesSubplot object, optional
|
||||||
|
axis on which to draw the plot
|
||||||
|
line_label : str, optional
|
||||||
|
label of the line
|
||||||
|
transpose : bool, optional
|
||||||
|
transpose the plot
|
||||||
|
line_kwargs : to be passed to plt.plot
|
||||||
|
returns
|
||||||
|
fig, ax : matplotlib objects containing the plots
|
||||||
|
example:
|
||||||
|
if spectra is a (m, n, nt) array, one can plot a spectrum evolution as such:
|
||||||
|
>>> fig, ax = plot_results_2D(spectra[:, -1], (600, 1600, nm), log=True, "Heidt2017")
|
||||||
|
"""
|
||||||
|
|
||||||
|
if len(values.shape) != 1:
|
||||||
|
print(f"Shape was {values.shape}. plot_results_1D can only plot 1D arrays")
|
||||||
|
return
|
||||||
|
|
||||||
|
is_spectrum = values.dtype == "complex"
|
||||||
|
|
||||||
|
if plt_range[2].type in ["WL", "FREQ", "AFREQ"]:
|
||||||
|
x_axis = params["w"].copy()
|
||||||
|
else:
|
||||||
|
x_axis = params["t"].copy()
|
||||||
|
|
||||||
|
# crop and convert
|
||||||
|
x_axis, ind, ext = units.sort_axis(x_axis, plt_range)
|
||||||
|
values = values[ind]
|
||||||
|
if is_spectrum:
|
||||||
|
values = abs2(values)
|
||||||
|
values *= yscaling
|
||||||
|
|
||||||
|
# make uniform if converting to wavelength
|
||||||
|
if plt_range[2].type == "WL":
|
||||||
|
if is_spectrum:
|
||||||
|
values = units.to_WL(values, params["frep"], units.m.inv(params["w"][ind]))
|
||||||
|
|
||||||
|
# change the resolution
|
||||||
|
if isinstance(spacing, float):
|
||||||
|
new_x_axis = np.linspace(*span(x_axis), int(len(x_axis) / spacing))
|
||||||
|
values = UnivariateSpline(x_axis, values, k=4, s=0)(new_x_axis)
|
||||||
|
x_axis = new_x_axis
|
||||||
|
elif isinstance(spacing, int) and spacing > 1:
|
||||||
|
values = values[::spacing]
|
||||||
|
x_axis = x_axis[::spacing]
|
||||||
|
|
||||||
|
# apply log transform if required
|
||||||
|
if log == False:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
ylabel = "normalized intensity (dB)" if ylabel is None else ylabel
|
||||||
|
vmax = state.plot_default_vmax_with_headroom if vmax is None else vmax
|
||||||
|
vmin = state.plot_default_vmin if vmin is None else vmin
|
||||||
|
if isinstance(log, (float, int)) and log != True:
|
||||||
|
values = units.to_log(values, ref=log)
|
||||||
|
else:
|
||||||
|
values = units.to_log(values)
|
||||||
|
|
||||||
|
is_new_plot = ax is None
|
||||||
|
|
||||||
|
folder_name = ""
|
||||||
|
if is_new_plot:
|
||||||
|
folder_name, file_name, fig, ax = io.plot_setup(file_name=file_name, file_type=file_type, params=params)
|
||||||
|
else:
|
||||||
|
fig = ax.get_figure()
|
||||||
|
if transpose:
|
||||||
|
ax.plot(values, x_axis, label=line_label, **line_kwargs)
|
||||||
|
ax.yaxis.tick_right()
|
||||||
|
ax.yaxis.set_label_position("right")
|
||||||
|
ax.set_xlim(vmax, vmin)
|
||||||
|
ax.set_xlabel(ylabel)
|
||||||
|
ax.set_ylabel(plt_range[2].label)
|
||||||
|
else:
|
||||||
|
ax.plot(x_axis, values, label=line_label, **line_kwargs)
|
||||||
|
ax.set_ylim(vmin, vmax)
|
||||||
|
ax.set_ylabel(ylabel)
|
||||||
|
ax.set_xlabel(plt_range[2].label)
|
||||||
|
|
||||||
|
if is_new_plot:
|
||||||
|
fig.savefig(os.path.join(folder_name, file_name), bbox_inches="tight", dpi=200)
|
||||||
|
print(f"plot saved in {os.path.join(folder_name, file_name)}")
|
||||||
|
return fig, ax
|
||||||
|
|
||||||
|
|
||||||
|
def plot_avg(
|
||||||
|
values,
|
||||||
|
plt_range,
|
||||||
|
params,
|
||||||
|
log=False,
|
||||||
|
spacing=1,
|
||||||
|
vmin=None,
|
||||||
|
vmax=None,
|
||||||
|
ylabel=None,
|
||||||
|
yscaling=1,
|
||||||
|
renormalize=True,
|
||||||
|
add_coherence=False,
|
||||||
|
file_type="png",
|
||||||
|
file_name=None,
|
||||||
|
ax=None,
|
||||||
|
line_labels=None,
|
||||||
|
legend=True,
|
||||||
|
legend_kwargs={},
|
||||||
|
transpose=False,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
plots 1D arrays and there mean and automatically saves the plots, as well as returns it
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
values : 2D array
|
||||||
|
axis 0 defines the position in the fiber and axis 1 the position in time, frequency or wl
|
||||||
|
example : [[1, 2, 3], [0, 1, 0]] describes a quantity at 3 different freq/time and at two locations in the fiber
|
||||||
|
plt_range : tupple (min, max, units)
|
||||||
|
min, max : int or float
|
||||||
|
minimum and maximum values given in the desired units
|
||||||
|
units : function to convert from the desired units to rad/s or to time.
|
||||||
|
common functions are already defined in scgenerator.physics.units
|
||||||
|
look there for more details
|
||||||
|
params : dict
|
||||||
|
parameters of the simulations
|
||||||
|
log : str {"1D"} or int, float or bool, optional
|
||||||
|
str : plot in dB
|
||||||
|
1D : takes the log for every slice
|
||||||
|
int, float : plot in dB
|
||||||
|
reference value
|
||||||
|
bool : whether to use 1D variant or nothing
|
||||||
|
spacing : int, float, optional
|
||||||
|
tells the function to take one value every `spacing` one available. If a float is given, it will interpolate with a spline.
|
||||||
|
vmin : float, optional
|
||||||
|
min value of the colorbar
|
||||||
|
vmax : float, optional
|
||||||
|
max value of the colorbar
|
||||||
|
ylabel : str, optional
|
||||||
|
label of the y axis (x axis in transposed mode). Default is 'normalized intensity (dB)' for log plots
|
||||||
|
yscaling : float, optional
|
||||||
|
scale the y values by this amount
|
||||||
|
renormalize : bool, optional
|
||||||
|
if converting to wl scale, renormalize with to_WL function to ensure energy is conserved
|
||||||
|
add_coherence : bool, optional
|
||||||
|
whether to add a subplot with coherence
|
||||||
|
file_type : str, optional
|
||||||
|
usually pdf or png
|
||||||
|
plt_name : str, optional
|
||||||
|
special name to give to the plot. A name is automatically assigned anyway
|
||||||
|
ax : matplotlib.axes._subplots.AxesSubplot object, optional
|
||||||
|
axis on which to draw the plot
|
||||||
|
line_labels : tupple(str), optional
|
||||||
|
label of the lines. line_labels[0] is the label of the mean and line_labels[1] is the label of the indiv. values
|
||||||
|
legend : bool, optional
|
||||||
|
whether to draw the legend
|
||||||
|
transpose : bool, optional
|
||||||
|
transpose the plot
|
||||||
|
returns
|
||||||
|
fig, ax : matplotlib objects containing the plots
|
||||||
|
example:
|
||||||
|
if spectra is a (m, n, nt) array, one can plot a spectrum evolution as such:
|
||||||
|
>>> fig, ax = plot_results_2D(spectra[:, -1], (600, 1600, nm), log=True, "Heidt2017")
|
||||||
|
"""
|
||||||
|
|
||||||
|
if len(values.shape) != 2:
|
||||||
|
print(f"Shape was {values.shape}. plot_avg can only plot 2D arrays")
|
||||||
|
return
|
||||||
|
|
||||||
|
is_spectrum = values.dtype == "complex"
|
||||||
|
|
||||||
|
if plt_range[2].type in ["WL", "FREQ", "AFREQ"]:
|
||||||
|
x_axis = params["w"].copy()
|
||||||
|
else:
|
||||||
|
x_axis = params["t"].copy()
|
||||||
|
|
||||||
|
# crop and convert
|
||||||
|
x_axis, ind, ext = units.sort_axis(x_axis, plt_range)
|
||||||
|
if add_coherence:
|
||||||
|
coherence = pulse.g12(values)
|
||||||
|
coherence = coherence[ind]
|
||||||
|
else:
|
||||||
|
coherence = None
|
||||||
|
values = values[:, ind]
|
||||||
|
|
||||||
|
is_new_plot = ax is None
|
||||||
|
folder_name = ""
|
||||||
|
original_lines = []
|
||||||
|
|
||||||
|
# compute the mean spectrum
|
||||||
|
if is_spectrum:
|
||||||
|
values = abs2(values)
|
||||||
|
values *= yscaling
|
||||||
|
mean_values = np.mean(values, axis=0)
|
||||||
|
if plt_range[2].type == "WL" and renormalize:
|
||||||
|
values = np.apply_along_axis(units.to_WL, 1, values, params["frep"], x_axis)
|
||||||
|
mean_values = units.to_WL(mean_values, params["frep"], x_axis)
|
||||||
|
|
||||||
|
# change the resolution
|
||||||
|
if isinstance(spacing, float):
|
||||||
|
new_x_axis = np.linspace(*span(x_axis), int(len(x_axis) / spacing))
|
||||||
|
values = np.array([UnivariateSpline(x_axis, value, k=4, s=0)(new_x_axis) for value in values])
|
||||||
|
if add_coherence:
|
||||||
|
coherence = UnivariateSpline(x_axis, coherence, k=4, s=0)(new_x_axis)
|
||||||
|
mean_values = np.mean(values, axis=0)
|
||||||
|
x_axis = new_x_axis
|
||||||
|
elif isinstance(spacing, int) and spacing > 1:
|
||||||
|
values = values[:, ::spacing]
|
||||||
|
mean_values = mean_values[::spacing]
|
||||||
|
x_axis = x_axis[::spacing]
|
||||||
|
if add_coherence:
|
||||||
|
coherence = coherence[::spacing]
|
||||||
|
|
||||||
|
# apply log transform if required
|
||||||
|
if log != False:
|
||||||
|
ylabel = "normalized intensity (dB)" if ylabel is None else ylabel
|
||||||
|
vmax = state.plot_default_vmax_with_headroom if vmax is None else vmax
|
||||||
|
vmin = state.plot_default_vmin if vmin is None else vmin
|
||||||
|
if isinstance(log, (float, int)) and log != True:
|
||||||
|
ref = log
|
||||||
|
else:
|
||||||
|
ref = np.max(mean_values)
|
||||||
|
values = units.to_log(values, ref=ref)
|
||||||
|
mean_values = units.to_log(mean_values, ref=ref)
|
||||||
|
|
||||||
|
if is_new_plot:
|
||||||
|
if add_coherence:
|
||||||
|
mode = "coherence_T" if transpose else "coherence"
|
||||||
|
folder_name, file_name, fig, (top, bot) = io.plot_setup(
|
||||||
|
file_name=file_name, file_type=file_type, params=params, mode=mode
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
folder_name, file_name, fig, top = io.plot_setup(file_name=file_name, file_type=file_type, params=params)
|
||||||
|
bot = top
|
||||||
|
else:
|
||||||
|
if isinstance(ax, (tuple, list)):
|
||||||
|
top, bot = ax
|
||||||
|
if transpose:
|
||||||
|
bot.set_xlim(1.1, -0.1)
|
||||||
|
bot.set_xlabel(r"|$g_{12}$|")
|
||||||
|
else:
|
||||||
|
bot.set_ylim(-0.1, 1.1)
|
||||||
|
bot.set_ylabel(r"|$g_{12}$|")
|
||||||
|
else:
|
||||||
|
bot, top = ax, ax
|
||||||
|
|
||||||
|
fig = top.get_figure()
|
||||||
|
original_lines = top.get_lines()
|
||||||
|
|
||||||
|
# Actual Plotting
|
||||||
|
|
||||||
|
gray_style = state.plot_muted_style
|
||||||
|
highlighted_style = state.plot_highlighted_style
|
||||||
|
|
||||||
|
if transpose:
|
||||||
|
for value in values:
|
||||||
|
top.plot(value, x_axis, **gray_style)
|
||||||
|
top.plot(mean_values, x_axis, **highlighted_style)
|
||||||
|
if add_coherence:
|
||||||
|
bot.plot(coherence, x_axis, c=state.plot_default_color_cycle[0])
|
||||||
|
|
||||||
|
top.set_xlim(left=vmax, right=vmin)
|
||||||
|
top.yaxis.tick_right()
|
||||||
|
top.set_xlabel(ylabel)
|
||||||
|
top.set_ylim(*ext)
|
||||||
|
bot.yaxis.tick_right()
|
||||||
|
bot.yaxis.set_label_position("right")
|
||||||
|
bot.set_ylabel(plt_range[2].label)
|
||||||
|
bot.set_ylim(*ext)
|
||||||
|
else:
|
||||||
|
for value in values:
|
||||||
|
top.plot(x_axis, value, **gray_style)
|
||||||
|
top.plot(x_axis, mean_values, **highlighted_style)
|
||||||
|
if add_coherence:
|
||||||
|
bot.plot(x_axis, coherence, c=state.plot_default_color_cycle[0])
|
||||||
|
|
||||||
|
top.set_ylim(bottom=vmin, top=vmax)
|
||||||
|
top.set_ylabel(ylabel)
|
||||||
|
top.set_xlim(*ext)
|
||||||
|
bot.set_xlabel(plt_range[2].label)
|
||||||
|
bot.set_xlim(*ext)
|
||||||
|
|
||||||
|
custom_lines = [plt.Line2D([0], [0], lw=2, c=gray_style["c"]), plt.Line2D([0], [0], lw=2, c=highlighted_style["c"])]
|
||||||
|
line_labels = state.plot_avg_default_line_labels if line_labels is None else line_labels
|
||||||
|
line_labels = list(line_labels)
|
||||||
|
|
||||||
|
if not is_new_plot:
|
||||||
|
custom_lines += original_lines
|
||||||
|
line_labels += [l.get_label() for l in original_lines]
|
||||||
|
|
||||||
|
if legend:
|
||||||
|
top.legend(custom_lines, line_labels, **legend_kwargs)
|
||||||
|
|
||||||
|
if is_new_plot:
|
||||||
|
fig.savefig(os.path.join(folder_name, file_name), bbox_inches="tight", dpi=200)
|
||||||
|
print(f"plot saved in {os.path.join(folder_name, file_name)}")
|
||||||
|
|
||||||
|
if top is bot:
|
||||||
|
return fig, top
|
||||||
|
else:
|
||||||
|
return fig, (top, bot)
|
||||||
|
|
||||||
|
|
||||||
|
def prepare_plot_1D(values, plt_range, x_axis, yscaling=1, spacing=1, frep=80e6):
|
||||||
|
"""prepares the values for plotting
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
values : array
|
||||||
|
the values to plot.
|
||||||
|
if complex, will take the abs^2
|
||||||
|
if 2D, will consider it a as a list of values, each corresponding to the same x_axis
|
||||||
|
plt_range : tupple (float, float, fct)
|
||||||
|
fct as defined in scgenerator.physics.units
|
||||||
|
x_axis : 1D array
|
||||||
|
the corresponding x_axis
|
||||||
|
yscaling : float, optional
|
||||||
|
scale the y values by this amount
|
||||||
|
spacing : int, float, optional
|
||||||
|
tells the function to take one value every `spacing` one available. If a float is given, it will interpolate with a spline.
|
||||||
|
frep : float
|
||||||
|
used for conversion between frequency and wavelength if necessary
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
new_x_axis : array
|
||||||
|
new_values : array
|
||||||
|
"""
|
||||||
|
is_spectrum = values.dtype == "complex"
|
||||||
|
|
||||||
|
unique = len(values.shape) == 1
|
||||||
|
values = np.atleast_2d(values)
|
||||||
|
|
||||||
|
x_axis, ind, ext = units.sort_axis(x_axis, plt_range)
|
||||||
|
|
||||||
|
if is_spectrum:
|
||||||
|
values = abs2(values)
|
||||||
|
values *= yscaling
|
||||||
|
|
||||||
|
values = values[:, ind]
|
||||||
|
|
||||||
|
if plt_range[2].type == "WL":
|
||||||
|
values = np.apply_along_axis(units.to_WL, -1, values, frep, x_axis)
|
||||||
|
|
||||||
|
if isinstance(spacing, float):
|
||||||
|
new_x_axis = np.linspace(*span(x_axis), int(len(x_axis) / spacing))
|
||||||
|
values = np.array([UnivariateSpline(x_axis, value, k=4, s=0)(new_x_axis) for value in values])
|
||||||
|
x_axis = new_x_axis
|
||||||
|
elif isinstance(spacing, int) and spacing > 1:
|
||||||
|
values = values[:, ::spacing]
|
||||||
|
x_axis = x_axis[::spacing]
|
||||||
|
|
||||||
|
return x_axis, np.squeeze(values)
|
||||||
|
|
||||||
|
|
||||||
|
def plot_dispersion_parameter(params, plt_range):
|
||||||
|
"""
|
||||||
|
Plots the dispersion parameter D as well as the beta2 parameter over the given range
|
||||||
|
"""
|
||||||
|
# TODO allow several curves, with legends, to be plotted
|
||||||
|
|
||||||
|
x_axis = np.linspace(*plt_range[:2], 1000)
|
||||||
|
w_axis = plt_range[2](x_axis)
|
||||||
|
|
||||||
|
if "disp_obj" in params:
|
||||||
|
D = params["disp_obj"].D_w(w_axis)
|
||||||
|
beta2 = params["disp_obj"].beta2_w(w_axis)
|
||||||
|
else:
|
||||||
|
print("no dispersion information given")
|
||||||
|
return
|
||||||
|
|
||||||
|
fig, (ax_D, ax_beta2) = plt.subplots(1, 2)
|
||||||
|
|
||||||
|
ax_D.plot(x_axis, 1e6 * D)
|
||||||
|
ax_D.plot(
|
||||||
|
x_axis,
|
||||||
|
0 * x_axis,
|
||||||
|
":",
|
||||||
|
c="k",
|
||||||
|
)
|
||||||
|
ax_D.set_xlabel(plt_range[2].label)
|
||||||
|
ax_D.set_ylabel(r"Dispersion parameter $D$ ($\frac{\mathrm{ps}}{\mathrm{nm\ km}}$)")
|
||||||
|
|
||||||
|
ax_beta2.plot(x_axis, 1e27 * beta2)
|
||||||
|
ax_beta2.plot(
|
||||||
|
x_axis,
|
||||||
|
0 * x_axis,
|
||||||
|
":",
|
||||||
|
c="k",
|
||||||
|
)
|
||||||
|
ax_beta2.set_xlabel(plt_range[2].label)
|
||||||
|
ax_beta2.set_ylabel(r"$\beta_2$ parameter ($\frac{\mathrm{ps}^2}{\mathrm{km}}$)")
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
def white_bottom_cmap(name, start=0, end=1, new_name="white_background", c_back=(1, 1, 1, 1)):
|
||||||
|
"""returns a new colormap based on "name" but that has a solid bacground (default=white)"""
|
||||||
|
top = plt.get_cmap(name, 1024)
|
||||||
|
n_bottom = 80
|
||||||
|
bottom = np.ones((n_bottom, 4))
|
||||||
|
for i in range(4):
|
||||||
|
bottom[:, i] = np.linspace(c_back[i], top(start)[i], n_bottom)
|
||||||
|
return ListedColormap(np.vstack((bottom, top(np.linspace(start, end, 1024)))), name=new_name)
|
||||||
103
src/scgenerator/state.py
Normal file
103
src/scgenerator/state.py
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
from . import utilities as util
|
||||||
|
|
||||||
|
"""
|
||||||
|
This File is used as a public global variable storage solutions. Main functions are having a centralised
|
||||||
|
parameters index
|
||||||
|
plotting parameters
|
||||||
|
logger
|
||||||
|
This is not a solution when functions are accessing this module in parallel threads, as
|
||||||
|
changes made by a thread are not reflected in other threads, which is why another solution should be used when dealing
|
||||||
|
with parameters or paths (if those paths are not stored in paths.json)
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class CurrentLogger:
|
||||||
|
_current_logger = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def focus_logger(cls, logger):
|
||||||
|
cls._current_logger = logger
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def log(cls, *args, **kwargs):
|
||||||
|
if cls._current_logger is not None:
|
||||||
|
util.ray_safe(cls._current_logger.log, *args, **kwargs)
|
||||||
|
else:
|
||||||
|
print(*args)
|
||||||
|
|
||||||
|
|
||||||
|
# WILL BREAK SIMULATION SAVING AND MERGING IF CHANGED
|
||||||
|
recorded_types = ["spectra", "params"] # nickname of the objects saved and tracked when doing automatic simulations
|
||||||
|
|
||||||
|
|
||||||
|
# --------SIMULATION VARIABLES--------#
|
||||||
|
default_z_target_size = 128
|
||||||
|
|
||||||
|
|
||||||
|
# ---------PLOTTING VARIABLES---------#
|
||||||
|
|
||||||
|
|
||||||
|
def plot_arrowstyle(direction=1, color="white"):
|
||||||
|
return dict(
|
||||||
|
arrowprops=dict(arrowstyle="->", connectionstyle=f"arc3,rad={direction*0.3}", color=color),
|
||||||
|
color=color,
|
||||||
|
backgroundcolor=(0.5, 0.5, 0.5, 0.5),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
plot_default_figsize = (10, 7)
|
||||||
|
plot_default_2D_interpolation = "bicubic"
|
||||||
|
plot_default_vmin = -40
|
||||||
|
plot_default_vmax = 0
|
||||||
|
plot_default_vmax_with_headroom = 2
|
||||||
|
plot_default_name = "plot"
|
||||||
|
|
||||||
|
plot_avg_default_main_to_coherence_ratio = 4
|
||||||
|
plot_avg_default_line_labels = ["individual values", "mean"]
|
||||||
|
|
||||||
|
plot_muted_style = dict(linewidth=0.5, c=(0.8, 0.8, 0.8, 0.4))
|
||||||
|
plot_highlighted_style = dict(c="red")
|
||||||
|
plot_default_color_cycle = plt.rcParams["axes.prop_cycle"].by_key()["color"]
|
||||||
|
plot_default_light_color = (1, 1, 1, 0.7)
|
||||||
|
plot_default_markers = ["*", "+", ".", "D", "x", "d", "v", "s", "1", "^"]
|
||||||
|
|
||||||
|
plot_default_cmap = "viridis"
|
||||||
|
|
||||||
|
plot_label_quality_factor = r"$F_\mathrm{Q}$"
|
||||||
|
plot_label_mean_g12 = r"$\langle | g_{12} |\rangle$"
|
||||||
|
plot_label_g12 = r"|$g_{12}$|"
|
||||||
|
plot_label_z = "propagation distance z (m)"
|
||||||
|
plot_label_fwhm = r"$T_\mathrm{FWHM}$ (fs)"
|
||||||
|
plot_label_wb_distance = r"$L_\mathrm{WB}$"
|
||||||
|
plot_label_t_jitter = "timing jitter (fs)"
|
||||||
|
plot_label_fwhm_noise = "FWHM noise (%)"
|
||||||
|
plot_label_int_noise = "RIN (%)"
|
||||||
|
|
||||||
|
plot_text_topright_style = dict(verticalalignment="top", horizontalalignment="right")
|
||||||
|
plot_text_topleft_style = dict(verticalalignment="top", horizontalalignment="left")
|
||||||
|
|
||||||
|
# ------------------------------------#
|
||||||
|
|
||||||
|
# plotting choices
|
||||||
|
dist = 1.5
|
||||||
|
|
||||||
|
# plotting variables
|
||||||
|
|
||||||
|
|
||||||
|
def style(k):
|
||||||
|
return dict(
|
||||||
|
marker=plot_default_markers[k], markerfacecolor="none", linestyle=":", lw=1, c=plot_default_color_cycle[k]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
default_width = 10
|
||||||
|
|
||||||
|
|
||||||
|
def fs(ratio):
|
||||||
|
return (default_width, default_width * ratio)
|
||||||
|
|
||||||
|
|
||||||
|
# store global variables for debug purposes
|
||||||
|
_DEBUG = {}
|
||||||
235
src/scgenerator/utilities.py
Normal file
235
src/scgenerator/utilities.py
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
"""
|
||||||
|
This files includes utility functions designed more or less to be used specifically with the
|
||||||
|
scgenerator module but some function may be used in any python program
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import datetime as dt
|
||||||
|
import itertools
|
||||||
|
from typing import Callable, List, Tuple, Union, Any
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import ray
|
||||||
|
|
||||||
|
from .math import *
|
||||||
|
from .const import valid_varying
|
||||||
|
|
||||||
|
# XXX ############################################
|
||||||
|
# XXX ############### Pure Python ################
|
||||||
|
# XXX ############################################
|
||||||
|
|
||||||
|
|
||||||
|
class ProgressTracker:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
max: Union[int, float],
|
||||||
|
auto_print: bool = False,
|
||||||
|
percent_incr: Union[int, float] = 5,
|
||||||
|
default_update: Union[int, float] = 1,
|
||||||
|
callback: Callable[[str, Any], None] = None,
|
||||||
|
):
|
||||||
|
self.max = max
|
||||||
|
self.current = 0
|
||||||
|
self.start_time = dt.datetime.now()
|
||||||
|
self.auto_print = auto_print
|
||||||
|
self.next_percent = percent_incr
|
||||||
|
self.percent_incr = percent_incr
|
||||||
|
self.default_update = default_update
|
||||||
|
self.callback = callback
|
||||||
|
|
||||||
|
def _update(self, callback_args):
|
||||||
|
if self.auto_print and self.current / self.max >= self.next_percent / 100:
|
||||||
|
self.next_percent += self.percent_incr
|
||||||
|
if self.callback is None:
|
||||||
|
print(self.ETA)
|
||||||
|
else:
|
||||||
|
self.callback(self.ETA, *callback_args)
|
||||||
|
|
||||||
|
def update(self, num=None, callback_args=[]):
|
||||||
|
if num is None:
|
||||||
|
num = self.default_update
|
||||||
|
self.current += num
|
||||||
|
self._update(callback_args)
|
||||||
|
|
||||||
|
def set(self, value, callback_args=[]):
|
||||||
|
self.current = value
|
||||||
|
self._update(callback_args)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ETA(self):
|
||||||
|
if self.current <= 0:
|
||||||
|
return "\033[31mETA : unknown\033[0m"
|
||||||
|
eta = (
|
||||||
|
(dt.datetime.now() - self.start_time).seconds / self.current * (self.max - self.current)
|
||||||
|
)
|
||||||
|
H = eta // 3600
|
||||||
|
M = (eta - H * 3600) // 60
|
||||||
|
S = eta % 60
|
||||||
|
percent = int(100 * self.current / self.max)
|
||||||
|
return "\033[34mremaining : {:.0f}h {:.0f}min {:.0f}s ({:.0f}% in total). \033[31mETA : {:%Y-%m-%d %H:%M:%S}\033[0m".format(
|
||||||
|
H, M, S, percent, dt.datetime.now() + dt.timedelta(seconds=eta)
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_eta(self):
|
||||||
|
return self.ETA
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "{}/{}".format(self.current, self.max)
|
||||||
|
|
||||||
|
|
||||||
|
# def ray_safe(func, *args, **kwargs):
|
||||||
|
# """evaluates functions that return None whether they are Ray workers or normal functions
|
||||||
|
# Parameters
|
||||||
|
# ----------
|
||||||
|
# func : the function or Worker id
|
||||||
|
# args : arguments to give to the functions
|
||||||
|
# Returns
|
||||||
|
# ----------
|
||||||
|
# nothing
|
||||||
|
# """
|
||||||
|
# if hasattr(func, "remote"):
|
||||||
|
# ray.get(func.remote(*args, **kwargs))
|
||||||
|
# else:
|
||||||
|
# func(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def count_variations(config: dict) -> Tuple[int, int]:
|
||||||
|
"""returns True if the config specified by the config dict requires only on simulation run"""
|
||||||
|
num = 1
|
||||||
|
varying_params = 0
|
||||||
|
|
||||||
|
for section_name in valid_varying:
|
||||||
|
for array in config.get(section_name, {}).get("varying", {}).values():
|
||||||
|
num *= len(array)
|
||||||
|
varying_params += 1
|
||||||
|
|
||||||
|
num *= config["simulation"].get("repeat", 1)
|
||||||
|
return num, varying_params
|
||||||
|
|
||||||
|
|
||||||
|
def format_varying_list(l: List[tuple], joints: List[str] = ""):
|
||||||
|
while len(joints) < 2:
|
||||||
|
joints += "_"
|
||||||
|
str_list = []
|
||||||
|
for p_name, p_value in l:
|
||||||
|
ps = p_name.replace("/", "").replace(joints[0], "").replace(joints[1], "")
|
||||||
|
vs = format_value(p_value).replace("/", "").replace(joints[0], "").replace(joints[1], "")
|
||||||
|
str_list.append(ps + joints[1] + vs)
|
||||||
|
return joints[0].join(str_list)
|
||||||
|
|
||||||
|
|
||||||
|
def varying_list_from_path(s: str) -> List[tuple]:
|
||||||
|
s = s.replace("/", "")
|
||||||
|
str_list = s.split("_")
|
||||||
|
out = []
|
||||||
|
for i in range(0, len(str_list) // 2 * 2, 2):
|
||||||
|
out.append((str_list[i], get_value(str_list[i + 1])))
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def format_value(value):
|
||||||
|
if type(value) == type(False):
|
||||||
|
return str(value)
|
||||||
|
elif isinstance(value, (float, int)):
|
||||||
|
return format(value, ".5g")
|
||||||
|
elif isinstance(value, (list, tuple, np.ndarray)):
|
||||||
|
return "-".join([format_value(v) for v in value])
|
||||||
|
else:
|
||||||
|
return str(value)
|
||||||
|
|
||||||
|
|
||||||
|
def get_value(s: str):
|
||||||
|
if s.lower() == "true":
|
||||||
|
return True
|
||||||
|
if s.lower() == "false":
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
return int(s)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
return float(s)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def varying_iterator(config):
|
||||||
|
varying_dict = {
|
||||||
|
section_name: config.get(section_name, {}).pop("varying", {})
|
||||||
|
for section_name in valid_varying
|
||||||
|
}
|
||||||
|
|
||||||
|
possible_keys = []
|
||||||
|
possible_ranges = []
|
||||||
|
|
||||||
|
for section_name, section in varying_dict.items():
|
||||||
|
for key in section:
|
||||||
|
arr = np.atleast_1d(varying_dict[section_name][key])
|
||||||
|
varying_dict[section_name][key] = arr
|
||||||
|
possible_keys.append((section_name, key))
|
||||||
|
possible_ranges.append(range(len(arr)))
|
||||||
|
|
||||||
|
combinations = itertools.product(*possible_ranges)
|
||||||
|
|
||||||
|
for combination in combinations:
|
||||||
|
out = config.copy()
|
||||||
|
only_varying = []
|
||||||
|
for i, key in enumerate(possible_keys):
|
||||||
|
parameter_value = varying_dict[key[0]][key[1]][combination[i]]
|
||||||
|
out[key[0]][key[1]] = parameter_value
|
||||||
|
only_varying.append((key[1], parameter_value))
|
||||||
|
yield only_varying, out
|
||||||
|
|
||||||
|
|
||||||
|
def parallelize(func, arg_iter, sim_jobs=4, progress_tracker_kwargs=None, const_kwarg={}):
|
||||||
|
"""given a function and an iterator of arguments, runs the function in parallel
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
func : a function
|
||||||
|
arg_iter : an iterator that yields a tuple to be unpacked to the function as argument(s)
|
||||||
|
sim_jobs : number of simultaneous runs
|
||||||
|
progress_tracker_kwargs : key word arguments to be passed to the ProgressTracker
|
||||||
|
const_kwarg : keyword arguments to be passed to the function on every run
|
||||||
|
|
||||||
|
Returns
|
||||||
|
----------
|
||||||
|
a list of the result ordered like arg_iter
|
||||||
|
"""
|
||||||
|
pt = None
|
||||||
|
if progress_tracker_kwargs is not None:
|
||||||
|
progress_tracker_kwargs["auto_print"] = True
|
||||||
|
pt = ray.remote(ProgressTracker).remote(**progress_tracker_kwargs)
|
||||||
|
|
||||||
|
# Initial setup
|
||||||
|
func = ray.remote(func)
|
||||||
|
jobs = []
|
||||||
|
results = []
|
||||||
|
dico = {} # to keep track of the order, as tasks may no finish in order
|
||||||
|
for k, args in enumerate(arg_iter):
|
||||||
|
if not isinstance(args, tuple):
|
||||||
|
print("iterator must return a tuple")
|
||||||
|
quit()
|
||||||
|
# as we got through the iterator, wait for first one to finish before
|
||||||
|
# adding a new job
|
||||||
|
if len(jobs) >= sim_jobs:
|
||||||
|
res, jobs = ray.wait(jobs)
|
||||||
|
results[dico[res[0].task_id()]] = ray.get(res[0])
|
||||||
|
if pt is not None:
|
||||||
|
ray.get(pt.update.remote())
|
||||||
|
newJob = func.remote(*args, **const_kwarg)
|
||||||
|
jobs.append(newJob)
|
||||||
|
dico[newJob.task_id()] = k
|
||||||
|
results.append(None)
|
||||||
|
|
||||||
|
# still have to wait for the last few jobs when there is no more new jobs
|
||||||
|
for j in jobs:
|
||||||
|
results[dico[j.task_id()]] = ray.get(j)
|
||||||
|
if pt is not None:
|
||||||
|
ray.get(pt.update.remote())
|
||||||
|
|
||||||
|
return np.array(results)
|
||||||
BIN
test_config.npz
Normal file
BIN
test_config.npz
Normal file
Binary file not shown.
26
testing/configs/compute_init_parameters/good.toml
Normal file
26
testing/configs/compute_init_parameters/good.toml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
name = "test config"
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
# gamma = 0.018
|
||||||
|
length = 1
|
||||||
|
model = "pcf"
|
||||||
|
pitch = 1.5e-6
|
||||||
|
pitch_ratio = 0.37
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
intensity_noise = 0.05e-2
|
||||||
|
power = 100e3
|
||||||
|
quantum_noise = true
|
||||||
|
shape = "gaussian"
|
||||||
|
wavelength = 1050e-9
|
||||||
|
width = 50e-15
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
parallel = 2
|
||||||
|
raman_type = "agrawal"
|
||||||
|
repeat = 4
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
29
testing/configs/ensure_consistency/bad1.toml
Normal file
29
testing/configs/ensure_consistency/bad1.toml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#t0 or width missing
|
||||||
|
|
||||||
|
name = "test config"
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
gamma = 0.018
|
||||||
|
length = 1
|
||||||
|
model = "pcf"
|
||||||
|
pitch = 1.5e-6
|
||||||
|
pitch_ratio = 0.37
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
power = 100e3
|
||||||
|
quantum_noise = true
|
||||||
|
shape = "gaussian"
|
||||||
|
wavelength = 1050e-9
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
intensity_noise = [0.05e-2, 0.1e-2]
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
parallel = 2
|
||||||
|
raman_type = "agrawal"
|
||||||
|
repeat = 4
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
29
testing/configs/ensure_consistency/bad2.toml
Normal file
29
testing/configs/ensure_consistency/bad2.toml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#t0, width, power or energy missing
|
||||||
|
|
||||||
|
name = "test config"
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
gamma = 0.018
|
||||||
|
length = 1
|
||||||
|
model = "pcf"
|
||||||
|
pitch = 1.5e-6
|
||||||
|
pitch_ratio = 0.37
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
quantum_noise = true
|
||||||
|
shape = "gaussian"
|
||||||
|
wavelength = 1050e-9
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
intensity_noise = [0.05e-2, 0.1e-2]
|
||||||
|
soliton_num = [1, 2, 3, 4]
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
parallel = 2
|
||||||
|
raman_type = "agrawal"
|
||||||
|
repeat = 4
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
29
testing/configs/ensure_consistency/bad3.toml
Normal file
29
testing/configs/ensure_consistency/bad3.toml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# window size or dt missing
|
||||||
|
|
||||||
|
name = "test config"
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
gamma = 0.018
|
||||||
|
length = 1
|
||||||
|
model = "pcf"
|
||||||
|
pitch = 1.5e-6
|
||||||
|
pitch_ratio = 0.37
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
power = 100e3
|
||||||
|
quantum_noise = true
|
||||||
|
shape = "gaussian"
|
||||||
|
wavelength = 1050e-9
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
intensity_noise = [0.05e-2, 0.1e-2]
|
||||||
|
width = [50e-15, 100e-15, 200e-15]
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
parallel = 2
|
||||||
|
raman_type = "agrawal"
|
||||||
|
repeat = 4
|
||||||
|
t_num = 16384
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
31
testing/configs/ensure_consistency/bad4.toml
Normal file
31
testing/configs/ensure_consistency/bad4.toml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#multiple width parameters
|
||||||
|
|
||||||
|
name = "test config"
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
gamma = 0.018
|
||||||
|
length = 1
|
||||||
|
model = "pcf"
|
||||||
|
pitch = 1.5e-6
|
||||||
|
pitch_ratio = 0.37
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
power = 100e3
|
||||||
|
quantum_noise = true
|
||||||
|
shape = "gaussian"
|
||||||
|
wavelength = 1050e-9
|
||||||
|
width = 120e-15
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
intensity_noise = [0.05e-2, 0.1e-2]
|
||||||
|
width = [50e-15, 100e-15, 200e-15]
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
parallel = 2
|
||||||
|
raman_type = "agrawal"
|
||||||
|
repeat = 4
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
32
testing/configs/ensure_consistency/bad5.toml
Normal file
32
testing/configs/ensure_consistency/bad5.toml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# missing capillary_thickness
|
||||||
|
|
||||||
|
name = "test config"
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
capillary_num = 6
|
||||||
|
capillary_outer_d = 2e-6
|
||||||
|
capillary_spacing = 4e-6
|
||||||
|
core_radius = 50e-6
|
||||||
|
gamma = 0.018
|
||||||
|
length = 1
|
||||||
|
model = "hasan"
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
power = 100e3
|
||||||
|
quantum_noise = true
|
||||||
|
shape = "gaussian"
|
||||||
|
wavelength = 1050e-9
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
intensity_noise = [0.05e-2, 0.1e-2]
|
||||||
|
width = [50e-15, 100e-15, 200e-15]
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
parallel = 2
|
||||||
|
raman_type = "agrawal"
|
||||||
|
repeat = 4
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
31
testing/configs/ensure_consistency/bad6.toml
Normal file
31
testing/configs/ensure_consistency/bad6.toml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# missing capillary_outer_d and capillary_spacing
|
||||||
|
|
||||||
|
name = "test config"
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
capillary_num = 6
|
||||||
|
capillary_thickness = 4e-6
|
||||||
|
core_radius = 50e-6
|
||||||
|
gamma = 0.018
|
||||||
|
length = 1
|
||||||
|
model = "hasan"
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
power = 100e3
|
||||||
|
quantum_noise = true
|
||||||
|
shape = "gaussian"
|
||||||
|
wavelength = 1050e-9
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
intensity_noise = [0.05e-2, 0.1e-2]
|
||||||
|
width = [50e-15, 100e-15, 200e-15]
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
parallel = 2
|
||||||
|
raman_type = "agrawal"
|
||||||
|
repeat = 4
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
29
testing/configs/ensure_consistency/good1.toml
Normal file
29
testing/configs/ensure_consistency/good1.toml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# model 'pcf' should be added and no gas dico
|
||||||
|
|
||||||
|
name = "test config"
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
gamma = 0.018
|
||||||
|
length = 1
|
||||||
|
pitch = 1.5e-6
|
||||||
|
pitch_ratio = 0.37
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
power = 100e3
|
||||||
|
quantum_noise = true
|
||||||
|
shape = "gaussian"
|
||||||
|
wavelength = 1050e-9
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
intensity_noise = [0.05e-2, 0.1e-2]
|
||||||
|
width = [50e-15, 100e-15, 200e-15]
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
parallel = 2
|
||||||
|
raman_type = "agrawal"
|
||||||
|
repeat = 4
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
29
testing/configs/ensure_consistency/good2.toml
Normal file
29
testing/configs/ensure_consistency/good2.toml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# raman_type should be added
|
||||||
|
|
||||||
|
name = "test config"
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
gamma = 0.018
|
||||||
|
length = 1
|
||||||
|
model = "pcf"
|
||||||
|
pitch = 1.5e-6
|
||||||
|
pitch_ratio = 0.37
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
power = 100e3
|
||||||
|
quantum_noise = true
|
||||||
|
shape = "gaussian"
|
||||||
|
wavelength = 1050e-9
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
intensity_noise = [0.05e-2, 0.1e-2]
|
||||||
|
width = [50e-15, 100e-15, 200e-15]
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
parallel = 2
|
||||||
|
repeat = 4
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
28
testing/configs/ensure_consistency/good3.toml
Normal file
28
testing/configs/ensure_consistency/good3.toml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# name should be added
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
gamma = 0.018
|
||||||
|
length = 1
|
||||||
|
model = "pcf"
|
||||||
|
pitch = 1.5e-6
|
||||||
|
pitch_ratio = 0.37
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
power = 100e3
|
||||||
|
quantum_noise = true
|
||||||
|
shape = "gaussian"
|
||||||
|
wavelength = 1050e-9
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
intensity_noise = [0.05e-2, 0.1e-2]
|
||||||
|
width = [50e-15, 100e-15, 200e-15]
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
parallel = 2
|
||||||
|
raman_type = "agrawal"
|
||||||
|
repeat = 4
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
38
testing/configs/ensure_consistency/good4.toml
Normal file
38
testing/configs/ensure_consistency/good4.toml
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# should add capillary_nested and capillary_resonance_strengths
|
||||||
|
|
||||||
|
name = "test config"
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
capillary_num = 6
|
||||||
|
capillary_outer_d = 2e-6
|
||||||
|
capillary_spacing = 4e-6
|
||||||
|
capillary_thickness = 1e-7
|
||||||
|
core_radius = 50e-6
|
||||||
|
length = 1
|
||||||
|
model = "hasan"
|
||||||
|
|
||||||
|
[gas]
|
||||||
|
gas_name = "helium"
|
||||||
|
|
||||||
|
[gas.varying]
|
||||||
|
temperature = [300, 350, 400]
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
power = 100e3
|
||||||
|
quantum_noise = true
|
||||||
|
shape = "gaussian"
|
||||||
|
wavelength = 1050e-9
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
intensity_noise = [0.05e-2, 0.1e-2]
|
||||||
|
width = [50e-15, 100e-15, 200e-15]
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
parallel = 2
|
||||||
|
raman_type = "agrawal"
|
||||||
|
repeat = 4
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
29
testing/configs/ensure_consistency/good5.toml
Normal file
29
testing/configs/ensure_consistency/good5.toml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# should add he_mode and gas
|
||||||
|
|
||||||
|
name = "test config"
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
core_radius = 50e-6
|
||||||
|
gamma = 0.018
|
||||||
|
length = 1
|
||||||
|
model = "marcatili"
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
power = 100e3
|
||||||
|
quantum_noise = true
|
||||||
|
shape = "gaussian"
|
||||||
|
wavelength = 1050e-9
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
intensity_noise = [0.05e-2, 0.1e-2]
|
||||||
|
width = [50e-15, 100e-15, 200e-15]
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
parallel = 2
|
||||||
|
raman_type = "agrawal"
|
||||||
|
repeat = 4
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
31
testing/configs/ensure_consistency/good6.toml
Normal file
31
testing/configs/ensure_consistency/good6.toml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# should not touch simulation parameters
|
||||||
|
# should add wavelength ranges
|
||||||
|
|
||||||
|
name = "test config"
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
gamma = 0.018
|
||||||
|
length = 1
|
||||||
|
model = "pcf"
|
||||||
|
pitch = 1.5e-6
|
||||||
|
pitch_ratio = 0.37
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
power = 100e3
|
||||||
|
quantum_noise = true
|
||||||
|
shape = "gaussian"
|
||||||
|
wavelength = 1050e-9
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
intensity_noise = [0.05e-2, 0.1e-2]
|
||||||
|
width = [50e-15, 100e-15, 200e-15]
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
parallel = 2
|
||||||
|
raman_type = "agrawal"
|
||||||
|
repeat = 4
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
32
testing/configs/run_simulations/full_anomalous.toml
Normal file
32
testing/configs/run_simulations/full_anomalous.toml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
name = "full anomalous"
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
beta = [
|
||||||
|
-1.183e-26,
|
||||||
|
8.1038e-41,
|
||||||
|
-9.5205e-56,
|
||||||
|
2.0737e-70,
|
||||||
|
-5.3943e-85,
|
||||||
|
1.3486e-99,
|
||||||
|
-2.5495e-114,
|
||||||
|
3.0524e-129,
|
||||||
|
-1.714e-144,
|
||||||
|
]
|
||||||
|
gamma = 0.11
|
||||||
|
length = 0.02
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
power = 10000
|
||||||
|
t0 = 2.84e-14
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
wavelength = [835e-9, 830e-9]
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
dt = 1e-15
|
||||||
|
parallel = 3
|
||||||
|
raman_type = "measured"
|
||||||
|
repeat = 4
|
||||||
|
t_num = 16384
|
||||||
|
tolerated_error = 1e-10
|
||||||
|
z_num = 64
|
||||||
20
testing/configs/single_sim/false1.toml
Normal file
20
testing/configs/single_sim/false1.toml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
[fiber]
|
||||||
|
core_radius = 50e-6
|
||||||
|
length = 50e-2
|
||||||
|
model = "marcatili"
|
||||||
|
|
||||||
|
[gas]
|
||||||
|
gas_name = "air"
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
wavelength = 800e-9
|
||||||
|
width = 250e-15
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
parallel = 2
|
||||||
|
repeat = 2
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
23
testing/configs/single_sim/false2.toml
Normal file
23
testing/configs/single_sim/false2.toml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
[fiber]
|
||||||
|
core_radius = 50e-6
|
||||||
|
length = 50e-2
|
||||||
|
model = "marcatili"
|
||||||
|
|
||||||
|
[gas]
|
||||||
|
gas_name = "air"
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
wavelength = 800e-9
|
||||||
|
width = 250e-15
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
shape = ["gaussian", "sech"]
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
parallel = 2
|
||||||
|
repeat = 1
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
20
testing/configs/single_sim/true1.toml
Normal file
20
testing/configs/single_sim/true1.toml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
[fiber]
|
||||||
|
core_radius = 50e-6
|
||||||
|
length = 50e-2
|
||||||
|
model = "marcatili"
|
||||||
|
|
||||||
|
[gas]
|
||||||
|
gas_name = "air"
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
wavelength = 800e-9
|
||||||
|
width = 250e-15
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
parallel = 2
|
||||||
|
repeat = 1
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
30
testing/configs/validate_types/bad1.toml
Normal file
30
testing/configs/validate_types/bad1.toml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# pitch in wrong section
|
||||||
|
|
||||||
|
name = "test config"
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
gamma = 0.018
|
||||||
|
length = 1
|
||||||
|
model = "pcf"
|
||||||
|
pitch_ratio = 0.37
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
pitch = 1.5e-6
|
||||||
|
power = 100e3
|
||||||
|
quantum_noise = true
|
||||||
|
shape = "gaussian"
|
||||||
|
wavelength = 1050e-9
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
intensity_noise = [0.05e-2, 0.1e-2]
|
||||||
|
width = [50e-15, 100e-15, 200e-15]
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
parallel = 2
|
||||||
|
raman_type = "agrawal"
|
||||||
|
repeat = 4
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
30
testing/configs/validate_types/bad2.toml
Normal file
30
testing/configs/validate_types/bad2.toml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# wrong value in behaviors
|
||||||
|
|
||||||
|
name = "test config"
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
gamma = 0.018
|
||||||
|
length = 1
|
||||||
|
model = "pcf"
|
||||||
|
pitch = 1.5e-6
|
||||||
|
pitch_ratio = 0.37
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
power = 100e3
|
||||||
|
quantum_noise = true
|
||||||
|
shape = "gaussian"
|
||||||
|
wavelength = 1050e-9
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
intensity_noise = [0.05e-2, 0.1e-2]
|
||||||
|
width = [50e-15, 100e-15, 200e-15]
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss", "q_noise"]
|
||||||
|
parallel = 2
|
||||||
|
raman_type = "agrawal"
|
||||||
|
repeat = 4
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
30
testing/configs/validate_types/bad3.toml
Normal file
30
testing/configs/validate_types/bad3.toml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# wrong type in width
|
||||||
|
|
||||||
|
name = "test config"
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
gamma = 0.018
|
||||||
|
length = 1
|
||||||
|
model = "pcf"
|
||||||
|
pitch = 1.5e-6
|
||||||
|
pitch_ratio = 0.37
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
power = 100e3
|
||||||
|
quantum_noise = true
|
||||||
|
shape = "gaussian"
|
||||||
|
wavelength = 1050e-9
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
intensity_noise = [0.05e-2, 0.1e-2]
|
||||||
|
width = ["gaussian", "sech"]
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
parallel = 2
|
||||||
|
raman_type = "agrawal"
|
||||||
|
repeat = 4
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
32
testing/configs/validate_types/bad4.toml
Normal file
32
testing/configs/validate_types/bad4.toml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# parallel should not be varying
|
||||||
|
|
||||||
|
name = "test config"
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
gamma = 0.018
|
||||||
|
length = 1
|
||||||
|
model = "pcf"
|
||||||
|
pitch = 1.5e-6
|
||||||
|
pitch_ratio = 0.37
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
power = 100e3
|
||||||
|
quantum_noise = true
|
||||||
|
shape = "gaussian"
|
||||||
|
wavelength = 1050e-9
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
intensity_noise = [0.05e-2, 0.1e-2]
|
||||||
|
width = [50e-15, 100e-15, 200e-15]
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
raman_type = "agrawal"
|
||||||
|
repeat = 4
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 1
|
||||||
|
|
||||||
|
[simulation.varying]
|
||||||
|
parallel = [2, 4]
|
||||||
30
testing/configs/validate_types/bad5.toml
Normal file
30
testing/configs/validate_types/bad5.toml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#varying parameters should be lists
|
||||||
|
|
||||||
|
name = "test config"
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
gamma = 0.018
|
||||||
|
length = 1
|
||||||
|
model = "pcf"
|
||||||
|
pitch = 1.5e-6
|
||||||
|
pitch_ratio = 0.37
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
power = 100e3
|
||||||
|
quantum_noise = true
|
||||||
|
shape = "gaussian"
|
||||||
|
wavelength = 1050e-9
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
intensity_noise = 0.05e-2
|
||||||
|
width = [50e-15, 100e-15, 200e-15]
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
parallel = 2
|
||||||
|
raman_type = "agrawal"
|
||||||
|
repeat = 4
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
30
testing/configs/validate_types/bad6.toml
Normal file
30
testing/configs/validate_types/bad6.toml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#repeat should not be 0
|
||||||
|
|
||||||
|
name = "test config"
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
gamma = 0.018
|
||||||
|
length = 1
|
||||||
|
model = "pcf"
|
||||||
|
pitch = 1.5e-6
|
||||||
|
pitch_ratio = 0.37
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
intensity_noise = 0.05e-2
|
||||||
|
power = 100e3
|
||||||
|
quantum_noise = true
|
||||||
|
shape = "gaussian"
|
||||||
|
wavelength = 1050e-9
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
width = [50e-15, 100e-15, 200e-15]
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
parallel = 2
|
||||||
|
raman_type = "agrawal"
|
||||||
|
repeat = 0
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
28
testing/configs/validate_types/bad7.toml
Normal file
28
testing/configs/validate_types/bad7.toml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# gamma missing
|
||||||
|
|
||||||
|
name = "test config"
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
beta = [1, 2, 3]
|
||||||
|
gamma = 0.018
|
||||||
|
length = 1
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
power = 100e3
|
||||||
|
quantum_noise = true
|
||||||
|
shape = "gaussian"
|
||||||
|
wavelength = 1050e-9
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
intensity_noise = []
|
||||||
|
width = [50e-15, 100e-15, 200e-15]
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
parallel = 2
|
||||||
|
raman_type = "agrawal"
|
||||||
|
repeat = 4
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
28
testing/configs/validate_types/good.toml
Normal file
28
testing/configs/validate_types/good.toml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
name = "test config"
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
gamma = 0.018
|
||||||
|
length = 1
|
||||||
|
model = "pcf"
|
||||||
|
pitch = 1.5e-6
|
||||||
|
pitch_ratio = 0.37
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
power = 100e3
|
||||||
|
quantum_noise = true
|
||||||
|
shape = "gaussian"
|
||||||
|
wavelength = 1050e-9
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
intensity_noise = [0.05e-2, 0.1e-2]
|
||||||
|
width = [50e-15, 100e-15, 200e-15]
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
parallel = 2
|
||||||
|
raman_type = "agrawal"
|
||||||
|
repeat = 4
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
155
testing/test_initialize.py
Normal file
155
testing/test_initialize.py
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
import unittest
|
||||||
|
import toml
|
||||||
|
import scgenerator.initialize as init
|
||||||
|
from scgenerator.errors import *
|
||||||
|
from prettyprinter import pprint
|
||||||
|
|
||||||
|
|
||||||
|
def load_conf(name):
|
||||||
|
with open("testing/configs/" + name + ".toml") as file:
|
||||||
|
conf = toml.load(file)
|
||||||
|
return conf
|
||||||
|
|
||||||
|
|
||||||
|
def conf_maker(folder):
|
||||||
|
def conf(name):
|
||||||
|
return load_conf(folder + "/" + name)
|
||||||
|
|
||||||
|
return conf
|
||||||
|
|
||||||
|
|
||||||
|
class TestInitializeMethods(unittest.TestCase):
|
||||||
|
def test_validate_types(self):
|
||||||
|
conf = lambda s: load_conf("validate_types/" + s)
|
||||||
|
with self.assertRaisesRegex(TypeError, "belong"):
|
||||||
|
init.validate_types(conf("bad1"))
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(TypeError, "valid list of behaviors"):
|
||||||
|
init.validate_types(conf("bad2"))
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(TypeError, "single, real, non-negative number"):
|
||||||
|
init.validate_types(conf("bad3"))
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(TypeError, "'parallel' is not a valid variable parameter"):
|
||||||
|
init.validate_types(conf("bad4"))
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(TypeError, "Varying parameters should be specified in a list"):
|
||||||
|
init.validate_types(conf("bad5"))
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
TypeError,
|
||||||
|
"value '0' of type <class 'int'> for key 'repeat' is not valid, must be a strictly positive integer",
|
||||||
|
):
|
||||||
|
init.validate_types(conf("bad6"))
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
ValueError,
|
||||||
|
r"Varying parameters lists should contain at least 1 element",
|
||||||
|
):
|
||||||
|
init.ensure_consistency(conf("bad7"))
|
||||||
|
|
||||||
|
self.assertIsNone(init.validate_types(conf("good")))
|
||||||
|
|
||||||
|
def test_ensure_consistency(self):
|
||||||
|
conf = lambda s: load_conf("ensure_consistency/" + s)
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
MissingParameterError,
|
||||||
|
r"1 of '\['t0', 'width'\]' is required and no defaults have been set",
|
||||||
|
):
|
||||||
|
init.ensure_consistency(conf("bad1"))
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
MissingParameterError,
|
||||||
|
r"1 of '\['power', 'energy', 'width', 't0'\]' is required when 'soliton_num' is specified and no defaults have been set",
|
||||||
|
):
|
||||||
|
init.ensure_consistency(conf("bad2"))
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
MissingParameterError,
|
||||||
|
r"2 of '\['dt', 't_num', 'time_window'\]' are required and no defaults have been set",
|
||||||
|
):
|
||||||
|
init.ensure_consistency(conf("bad3"))
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
DuplicateParameterError,
|
||||||
|
r"got multiple values for parameter 'width'",
|
||||||
|
):
|
||||||
|
init.ensure_consistency(conf("bad4"))
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
MissingParameterError,
|
||||||
|
r"'capillary_thickness' is a required parameter for fiber model 'hasan' and no defaults have been set",
|
||||||
|
):
|
||||||
|
init.ensure_consistency(conf("bad5"))
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
MissingParameterError,
|
||||||
|
r"1 of '\['capillary_spacing', 'capillary_outer_d'\]' is required for fiber model 'hasan' and no defaults have been set",
|
||||||
|
):
|
||||||
|
init.ensure_consistency(conf("bad6"))
|
||||||
|
|
||||||
|
self.assertLessEqual(
|
||||||
|
{"model": "pcf"}.items(), init.ensure_consistency(conf("good1"))["fiber"].items()
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertNotIn("gas", init.ensure_consistency(conf("good1")))
|
||||||
|
|
||||||
|
self.assertNotIn("gamma", init.ensure_consistency(conf("good4"))["fiber"])
|
||||||
|
|
||||||
|
self.assertLessEqual(
|
||||||
|
{"raman_type": "agrawal"}.items(),
|
||||||
|
init.ensure_consistency(conf("good2"))["simulation"].items(),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertLessEqual(
|
||||||
|
{"name": "no name"}.items(), init.ensure_consistency(conf("good3")).items()
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertLessEqual(
|
||||||
|
{"capillary_nested": 0, "capillary_resonance_strengths": []}.items(),
|
||||||
|
init.ensure_consistency(conf("good4"))["fiber"].items(),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertLessEqual(
|
||||||
|
dict(he_mode=(1, 1)).items(),
|
||||||
|
init.ensure_consistency(conf("good5"))["fiber"].items(),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertLessEqual(
|
||||||
|
dict(temperature=300, pressure=1e5, gas_name="vacuum", plasma_density=0).items(),
|
||||||
|
init.ensure_consistency(conf("good5"))["gas"].items(),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertLessEqual(
|
||||||
|
dict(
|
||||||
|
t_num=16384,
|
||||||
|
time_window=37e-12,
|
||||||
|
lower_wavelength_interp_limit=0,
|
||||||
|
upper_wavelength_interp_limit=1900e-9,
|
||||||
|
).items(),
|
||||||
|
init.ensure_consistency(conf("good6"))["simulation"].items(),
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_single_sim(self):
|
||||||
|
conf = conf_maker("single_sim")
|
||||||
|
|
||||||
|
self.assertTrue(init.single_sim(conf("true1")))
|
||||||
|
|
||||||
|
self.assertFalse(init.single_sim(conf("false1")))
|
||||||
|
|
||||||
|
self.assertFalse(init.single_sim(conf("false2")))
|
||||||
|
|
||||||
|
# def test_compute_init_parameters(self):
|
||||||
|
# conf = lambda s: load_conf("compute_init_parameters/" + s)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
conf = conf_maker("validate_types")
|
||||||
|
config = conf("good")
|
||||||
|
pprint(config)
|
||||||
|
config = init.ensure_consistency(config)
|
||||||
|
pprint(config)
|
||||||
|
params = init.compute_init_parameters(config)
|
||||||
|
pprint(params)
|
||||||
|
|
||||||
|
unittest.main()
|
||||||
41
testing/test_pulse.py
Normal file
41
testing/test_pulse.py
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import unittest
|
||||||
|
from scgenerator.physics.pulse import conform_pulse_params
|
||||||
|
|
||||||
|
|
||||||
|
class TestPulseMethods(unittest.TestCase):
|
||||||
|
def test_conform_pulse_params(self):
|
||||||
|
self.assertNotIn(None, conform_pulse_params("gaussian", t0=5, energy=6))
|
||||||
|
self.assertNotIn(None, conform_pulse_params("gaussian", width=5, energy=6))
|
||||||
|
self.assertNotIn(None, conform_pulse_params("gaussian", t0=5, power=6))
|
||||||
|
self.assertNotIn(None, conform_pulse_params("gaussian", width=5, power=6))
|
||||||
|
|
||||||
|
self.assertEqual(4, len(conform_pulse_params("gaussian", t0=5, energy=6)))
|
||||||
|
self.assertEqual(4, len(conform_pulse_params("gaussian", width=5, energy=6)))
|
||||||
|
self.assertEqual(4, len(conform_pulse_params("gaussian", t0=5, power=6)))
|
||||||
|
self.assertEqual(4, len(conform_pulse_params("gaussian", width=5, power=6)))
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
TypeError, "when soliton number is desired, both gamma and beta2 must be specified"
|
||||||
|
):
|
||||||
|
conform_pulse_params("gaussian", t0=5, energy=6, gamma=0.01)
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
TypeError, "when soliton number is desired, both gamma and beta2 must be specified"
|
||||||
|
):
|
||||||
|
conform_pulse_params("gaussian", t0=5, energy=6, beta2=0.01)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
5, len(conform_pulse_params("gaussian", t0=5, energy=6, gamma=0.01, beta2=2e-6))
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
5, len(conform_pulse_params("gaussian", width=5, energy=6, gamma=0.01, beta2=2e-6))
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
5, len(conform_pulse_params("gaussian", t0=5, power=6, gamma=0.01, beta2=2e-6))
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
5, len(conform_pulse_params("gaussian", width=5, power=6, gamma=0.01, beta2=2e-6))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
84
tests.py
Normal file
84
tests.py
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
import numpy as np
|
||||||
|
import scgenerator as sc
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
|
||||||
|
def convert(l, beta2):
|
||||||
|
return l[2:-2] * 1e9, sc.units.beta2_fs_cm.inv(beta2[2:-2])
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_marcatili():
|
||||||
|
l = np.linspace(250, 1200, 500) * 1e-9
|
||||||
|
beta2 = sc.fiber.HCPCF_dispersion(l, 15e-6)
|
||||||
|
plt.plot(*convert(l, beta2))
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_hasan_no_resonance():
|
||||||
|
l = np.linspace(250, 1200, 500) * 1e-9
|
||||||
|
beta2 = sc.fiber.HCPCF_dispersion(
|
||||||
|
l, 12e-6, model="hasan", model_params=dict(t=0.2e-6, g=1e-6, n=6)
|
||||||
|
)
|
||||||
|
plt.plot(*convert(l, beta2))
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_hasan():
|
||||||
|
l = np.linspace(250, 1200, 500) * 1e-9
|
||||||
|
fig, (ax, ax2) = plt.subplots(2, 1, figsize=(6, 7), gridspec_kw=dict(height_ratios=[3, 1]))
|
||||||
|
ax.set_ylim(-40, 20)
|
||||||
|
ax2.set_ylim(-100, 0)
|
||||||
|
beta2 = sc.fiber.HCPCF_dispersion(
|
||||||
|
l,
|
||||||
|
12e-6,
|
||||||
|
model="hasan",
|
||||||
|
model_params=dict(t=0.2e-6, g=1e-6, n=6, resonance_strength=(2e-6,)),
|
||||||
|
)
|
||||||
|
ax.plot(*convert(l, beta2))
|
||||||
|
beta2 = sc.fiber.HCPCF_dispersion(
|
||||||
|
l, 12e-6, model="hasan", model_params=dict(t=0.2e-6, g=1e-6, n=6)
|
||||||
|
)
|
||||||
|
ax.plot(*convert(l, beta2))
|
||||||
|
|
||||||
|
l = np.linspace(500, 1500, 500) * 1e-9
|
||||||
|
beta2 = sc.fiber.HCPCF_dispersion(
|
||||||
|
l, 12e-6, model="hasan", model_params=dict(t=0.2e-6, g=1e-6, n=10)
|
||||||
|
)
|
||||||
|
ax2.plot(*convert(l, beta2))
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
def test_custom_initial_field():
|
||||||
|
param = {
|
||||||
|
"name": "test",
|
||||||
|
"lambda0": [1030, "nm"],
|
||||||
|
"E0": [6, "uJ"],
|
||||||
|
"T0_FWHM": [27, "fs"],
|
||||||
|
"frep": 151e3,
|
||||||
|
"z_targets": [0, 0.07, 128],
|
||||||
|
"gas": "argon",
|
||||||
|
"pressure": 4e5,
|
||||||
|
"temperature": 293,
|
||||||
|
"pulse_shape": "sech",
|
||||||
|
"behaviors": [],
|
||||||
|
"fiber_model": "marcatili",
|
||||||
|
"model_params": {"core_radius": 18e-6},
|
||||||
|
"field_0": "exp(-(t/t0)**2)*P0 + P0/10 * cos(t/t0)*2*exp(-(0.05*t/t0)**2)",
|
||||||
|
"nt": 16384,
|
||||||
|
"T": 2e-12,
|
||||||
|
"adapt_step_size": True,
|
||||||
|
"error_ok": 1e-10,
|
||||||
|
"interp_range": [120, 2000],
|
||||||
|
"n_percent": 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
p = sc.compute_init_parameters(dictionary=param)
|
||||||
|
fig, ax = plt.subplots()
|
||||||
|
ax.plot(p["t"], abs(p["field_0"]))
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# test_empty_marcatili()
|
||||||
|
# test_empty_hasan()
|
||||||
|
test_custom_initial_field()
|
||||||
6
tests/numpy.toml
Normal file
6
tests/numpy.toml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
a = [ 0, 1, 2, 3, 4,]
|
||||||
|
c = [ 0, 1, 2, 3, 4,]
|
||||||
|
b = "<built-in function print>"
|
||||||
|
aa = [ "0j", "(1+0j)", "(2+0j)", "(3+0j)", "(4+0j)",]
|
||||||
|
bb = [ 0.0, 1.0, 2.0, 3.0, 4.0,]
|
||||||
|
ddd = 2021-01-21T07:55:18.881790
|
||||||
49343
tests/param.json
Normal file
49343
tests/param.json
Normal file
File diff suppressed because it is too large
Load Diff
4
tests/param.toml
Normal file
4
tests/param.toml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
a = [ 0, 1, 2, 3, 4,]
|
||||||
|
c = [ 0, 1, 2, 3, 4,]
|
||||||
|
bb = [ 0.0, 1.0, 2.0, 3.0, 4.0,]
|
||||||
|
datetime = 2021-01-21T07:55:18.882279
|
||||||
15
tests/playground.py
Normal file
15
tests/playground.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
from scgenerator import io
|
||||||
|
from scgenerator.io import _get_data_subfolders
|
||||||
|
import numpy as np
|
||||||
|
from glob import glob
|
||||||
|
from scgenerator.math import abs2
|
||||||
|
from matplotlib import pyplot as plt
|
||||||
|
|
||||||
|
path = "scgenerator_full anomalous123/wavelength_8.35e-07"
|
||||||
|
|
||||||
|
|
||||||
|
for i in [0, 63]:
|
||||||
|
dat = np.load(f"{path}/spectra_{i}.npy")
|
||||||
|
for d in dat:
|
||||||
|
plt.plot(abs2(d))
|
||||||
|
plt.show()
|
||||||
15
tests/test_Config.py
Normal file
15
tests/test_Config.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
from scgenerator.initialize import ParamSequence
|
||||||
|
from logging import StreamHandler
|
||||||
|
from scgenerator import io
|
||||||
|
from scgenerator import utilities
|
||||||
|
|
||||||
|
# dispatcher = ParamSequence(io.load_toml("testing/configs/ensure_consistency/good4"))
|
||||||
|
dispatcher = ParamSequence(io.load_toml("testing/configs/compute_init_parameters/good"))
|
||||||
|
print(dispatcher)
|
||||||
|
|
||||||
|
for only, params in dispatcher:
|
||||||
|
print(only, params["width"])
|
||||||
|
print(len(dispatcher))
|
||||||
|
print(dispatcher["fiber", "length"])
|
||||||
|
|
||||||
|
print(utilities.varying_list_from_path("/a_5_b_asdf"))
|
||||||
13
tests/test_compute_init_parameters.py
Normal file
13
tests/test_compute_init_parameters.py
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
from prettyprinter import pprint
|
||||||
|
from scgenerator import initialize as init
|
||||||
|
from scgenerator.io import load_toml
|
||||||
|
|
||||||
|
debug = 56
|
||||||
|
|
||||||
|
config = load_toml("testing/configs/compute_init_parameters/good.toml")
|
||||||
|
config = init.ensure_consistency(config)
|
||||||
|
try:
|
||||||
|
params = init.compute_init_parameters(config)
|
||||||
|
except:
|
||||||
|
raise
|
||||||
|
pprint(params)
|
||||||
38
tests/test_config.json
Normal file
38
tests/test_config.json
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"name": "test config",
|
||||||
|
"fiber": {
|
||||||
|
"gamma": 0.018,
|
||||||
|
"pitch": 1.5e-06,
|
||||||
|
"pitch_ratio": 0.37,
|
||||||
|
"type": "pcf"
|
||||||
|
},
|
||||||
|
"pulse": {
|
||||||
|
"power": 100000.0,
|
||||||
|
"quantum_noise": true,
|
||||||
|
"shape": "gaussian",
|
||||||
|
"wavelength": 1.05e-06,
|
||||||
|
"varying": {
|
||||||
|
"intensity_noise": [
|
||||||
|
0.0005,
|
||||||
|
0.001
|
||||||
|
],
|
||||||
|
"pulse_width": [
|
||||||
|
5e-14,
|
||||||
|
1e-13,
|
||||||
|
2e-13
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"simulation": {
|
||||||
|
"behaviors": [
|
||||||
|
"spm",
|
||||||
|
"raman",
|
||||||
|
"ss"
|
||||||
|
],
|
||||||
|
"nt": 16384,
|
||||||
|
"raman_type": "agrawal",
|
||||||
|
"repeat": 4,
|
||||||
|
"time_window": 3.7e-11,
|
||||||
|
"tolerated_error": 1e-11
|
||||||
|
}
|
||||||
|
}
|
||||||
28
tests/test_config.toml
Normal file
28
tests/test_config.toml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
name = "test config"
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
gamma = 0.018
|
||||||
|
length = 1
|
||||||
|
model = "pcf"
|
||||||
|
pitch = 1.5e-6
|
||||||
|
pitch_ratio = 0.37
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
power = 100e3
|
||||||
|
quantum_noise = true
|
||||||
|
shape = "gaussian"
|
||||||
|
wavelength = 1050e-9
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
intensity_noise = [0.05e-2, 0.1e-2]
|
||||||
|
pulse_width = [50e-15, 100e-15, 200e-15]
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = ["spm", "raman", "ss"]
|
||||||
|
parallel = 2
|
||||||
|
raman_type = "agrawal"
|
||||||
|
repeat = 4
|
||||||
|
t_num = 16384
|
||||||
|
time_window = 37e-12
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
z_num = 128
|
||||||
11
tests/test_load_config.py
Normal file
11
tests/test_load_config.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import toml
|
||||||
|
from prettyprinter import pprint
|
||||||
|
import json
|
||||||
|
|
||||||
|
config = toml.load("tests/test_config.toml")
|
||||||
|
pprint(config)
|
||||||
|
with open("tests/test_config.toml") as file:
|
||||||
|
config = toml.load(file)
|
||||||
|
|
||||||
|
# with open("tests/test_config.json", "w") as file:
|
||||||
|
# json.dump(config, file)
|
||||||
29
tests/test_merge_data.py
Normal file
29
tests/test_merge_data.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
from scgenerator.io import merge_same_simulations
|
||||||
|
from prettyprinter import pprint
|
||||||
|
|
||||||
|
# a, b = [
|
||||||
|
# "scgenerator_full anomalous123_1/wavelength_8.35e-07_num_3",
|
||||||
|
# "scgenerator_full anomalous123_1/wavelength_8.35e-07_num_2",
|
||||||
|
# "scgenerator_full anomalous123_1/wavelength_8.3e-07_num_1",
|
||||||
|
# "scgenerator_full anomalous123_1/wavelength_8.3e-07_num_0",
|
||||||
|
# "scgenerator_full anomalous123_1/wavelength_8.35e-07_num_0",
|
||||||
|
# "scgenerator_full anomalous123_1/wavelength_8.35e-07_num_1",
|
||||||
|
# "scgenerator_full anomalous123_1/wavelength_8.3e-07_num_2",
|
||||||
|
# "scgenerator_full anomalous123_1/wavelength_8.3e-07_num_3",
|
||||||
|
# ], [
|
||||||
|
# [("wavelength", 8.3e-07), ("num", 0)],
|
||||||
|
# [("wavelength", 8.35e-07), ("num", 0)],
|
||||||
|
# [("wavelength", 8.3e-07), ("num", 1)],
|
||||||
|
# [("wavelength", 8.35e-07), ("num", 1)],
|
||||||
|
# [("wavelength", 8.3e-07), ("num", 2)],
|
||||||
|
# [("wavelength", 8.35e-07), ("num", 2)],
|
||||||
|
# [("wavelength", 8.3e-07), ("num", 3)],
|
||||||
|
# [("wavelength", 8.35e-07), ("num", 3)],
|
||||||
|
# ]
|
||||||
|
|
||||||
|
# pprint(list(zip(a, b)))
|
||||||
|
|
||||||
|
|
||||||
|
all = merge_same_simulations("scgenerator_full anomalous123")
|
||||||
|
|
||||||
|
pprint(all)
|
||||||
8
tests/test_run_simulations.py
Normal file
8
tests/test_run_simulations.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
from scgenerator.physics.simulate import new_simulations
|
||||||
|
from scgenerator import io
|
||||||
|
import ray
|
||||||
|
|
||||||
|
ray.init()
|
||||||
|
|
||||||
|
sim = new_simulations("testing/configs/run_simulations/full_anomalous.toml", 123)
|
||||||
|
sim.run()
|
||||||
17
tests/test_save_config.py
Normal file
17
tests/test_save_config.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
from json import encoder
|
||||||
|
import toml
|
||||||
|
import numpy as np
|
||||||
|
from datetime import datetime
|
||||||
|
from scgenerator.io import save_parameters
|
||||||
|
|
||||||
|
x = np.arange(5)
|
||||||
|
y = np.arange(5, dtype="complex")
|
||||||
|
z = np.arange(5, dtype="float")
|
||||||
|
|
||||||
|
dico = dict(a=x, c=list(x), b=print, aa=y, bb=z, ddd=datetime.now())
|
||||||
|
|
||||||
|
with open("tests/numpy.toml", "w") as file:
|
||||||
|
toml.dump(dico, file, encoder=toml.TomlNumpyEncoder())
|
||||||
|
|
||||||
|
save_parameters(dico, "tests/param")
|
||||||
|
save_parameters(toml.load("tests/test_config.toml"), "tests/test_save_config")
|
||||||
26
tests/test_save_config.toml
Normal file
26
tests/test_save_config.toml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
name = "test config"
|
||||||
|
datetime = 2021-01-21T07:55:18.883204
|
||||||
|
|
||||||
|
[fiber]
|
||||||
|
gamma = 0.018
|
||||||
|
pitch = 1.5e-6
|
||||||
|
pitch_ratio = 0.37
|
||||||
|
type = "pcf"
|
||||||
|
|
||||||
|
[pulse]
|
||||||
|
power = 100000.0
|
||||||
|
quantum_noise = true
|
||||||
|
shape = "gaussian"
|
||||||
|
wavelength = 1.05e-6
|
||||||
|
|
||||||
|
[simulation]
|
||||||
|
behaviors = [ "spm", "raman", "ss",]
|
||||||
|
nt = 16384
|
||||||
|
raman_type = "agrawal"
|
||||||
|
repeat = 4
|
||||||
|
time_window = 3.7e-11
|
||||||
|
tolerated_error = 1e-11
|
||||||
|
|
||||||
|
[pulse.varying]
|
||||||
|
intensity_noise = [ 0.0005, 0.001,]
|
||||||
|
pulse_width = [ 5e-14, 1e-13, 2e-13,]
|
||||||
6
tests/test_validate_types.py
Normal file
6
tests/test_validate_types.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from scgenerator.initialize import validate_types
|
||||||
|
from scgenerator.io import load_toml
|
||||||
|
|
||||||
|
config = load_toml("tests/test_config.toml")
|
||||||
|
|
||||||
|
validate_types(config)
|
||||||
Reference in New Issue
Block a user