started working on plasma

This commit is contained in:
Benoît Sierro
2021-06-30 09:37:49 +02:00
parent 2bd5c3d055
commit 9d036ae608
8 changed files with 149 additions and 29 deletions

View File

@@ -118,13 +118,13 @@ capillary_nested : int, optional
gamma: float, optional unless beta is directly provided
nonlinear parameter in m^2 / W. Will overwrite any computed gamma parameter.
nonlinear parameter in m^-1*W^-1. Will overwrite any computed gamma parameter.
effective_mode_diameter : float, optional
effective mode field diameter in m
n2 : float, optional
non linear refractive index
non linear refractive index in m^2/W
A_eff : float, optional
effective mode field area

View File

@@ -10,6 +10,6 @@ from .math import abs2, argclosest, span
from .physics import fiber, materials, pulse, simulate, units
from .physics.simulate import RK4IP, new_simulation, resume_simulations
from .plotting import plot_avg, plot_results_1D, plot_results_2D, plot_spectrogram
from .spectra import Pulse
from .spectra import Pulse, Spectrum
from .utils.parameter import BareParams, BareConfig
from . import utils, io, initialize, math

View File

@@ -26,7 +26,8 @@ def material_dispersion(
material: str,
pressure=None,
temperature=None,
ideal=False,
ideal=True,
safe=True,
):
"""returns the dispersion profile (beta_2) of a bulk material.
@@ -41,7 +42,7 @@ def material_dispersion(
pressure : float, optional
constant pressure
ideal : bool, optional
whether to use the ideal gas law instead of the van der Waals equation, by default False
whether to use the ideal gas law instead of the van der Waals equation, by default True
Returns
-------
@@ -50,6 +51,9 @@ def material_dispersion(
"""
w = units.m(wavelengths)
order = np.argsort(w)
material_dico = load_material_dico(material)
if ideal:
n_gas_2 = materials.sellmeier(wavelengths, material_dico, pressure, temperature) + 1
@@ -59,12 +63,19 @@ def material_dispersion(
)
N_0 = materials.number_density_van_der_waals(material_dico=material_dico)
n_gas_2 = materials.sellmeier(wavelengths, material_dico) * N_1 / N_0 + 1
return fiber.beta2(w, np.sqrt(n_gas_2))
if safe:
disp = np.zeros(len(w))
ind = w > 0
disp[ind] = material_dispersion(
units.To.m(w[ind]), material, pressure, temperature, ideal, False
)
return disp
else:
return fiber.beta2(w[order], np.sqrt(n_gas_2[order]))[order]
def find_optimal_depth(
spectrum: T, w_c: np.ndarray, w0: float, material: str = "silica", max_z: float = 1.0
spectrum: T, w_c: np.ndarray, w0: float, material: str, max_z: float = 1.0
) -> tuple[T, pulse.OptimizeResult]:
"""finds the optimal silica depth to compress a pulse
@@ -86,12 +97,26 @@ def find_optimal_depth(
float
distance in m
"""
silica_disp = material_dispersion(units.To.m(w_c + w0), material)
w = w_c + w0
disp = np.zeros(len(w))
ind = w > (w0 / 10)
disp[ind] = material_dispersion(units.To.m(w[ind]), material)
propagate = lambda z: spectrum * np.exp(-0.5j * silica_disp * w_c ** 2 * z)
propagate = lambda z: spectrum * np.exp(-0.5j * disp * w_c ** 2 * z)
integrate = lambda z: math.abs2(np.fft.ifft(propagate(z)))
def score(z):
return 1 / np.max(math.abs2(np.fft.ifft(propagate(z))))
return -np.nansum(integrate(z) ** 6)
opti = minimize_scalar(score, bracket=(0, max_z))
return opti.x
# import matplotlib.pyplot as plt
# to_test = np.linspace(0, max_z, 200)
# scores = [score(z) for z in to_test]
# fig, ax = plt.subplots()
# ax.plot(to_test, scores / np.min(scores))
# plt.show()
# plt.close(fig)
# ama = np.argmin(scores)
opti = minimize_scalar(score, method="bounded", bounds=(0, max_z))
return propagate(opti.x), opti

View File

@@ -647,7 +647,7 @@ def PCF_dispersion(lambda_, pitch, ratio_d, w0=None, n2=None, A_eff=None):
if A_eff is None:
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)) ** pipi
A_eff = interp1d(lambda_, w_eff, kind="linear")(units.m.inv(w0)) ** 2 * pi
if n2 is None:
n2 = 2.6e-20

View File

@@ -1,8 +1,13 @@
from typing import Any, Callable
import numpy as np
import scipy.special
from scipy.integrate import cumulative_trapezoid
from scgenerator import math
from ..logger import get_logger
from . import units
from .units import NA, c, kB, me, e
from .units import NA, c, kB, me, e, hbar
def pressure_from_gradient(ratio, p0, p1):
@@ -174,3 +179,57 @@ def non_linear_refractive_index(material_dico, pressure=None, temperature=None):
def adiabadicity(w: np.ndarray, I: float, field: np.ndarray) -> np.ndarray:
return w * np.sqrt(2 * me * I) / (e * np.abs(field))
def free_electron_density(
t: np.ndarray, field: np.ndarray, N0: float, rate_func: Callable[[np.ndarray], np.ndarray]
) -> np.ndarray:
return N0 * (1 - np.exp(-cumulative_trapezoid(rate_func(field), t, initial=0)))
def ionization_rate_ADK(
ionization_energy: float, atomic_number
) -> Callable[[np.ndarray], np.ndarray]:
Z = -(atomic_number - 1) * e
omega_p = ionization_energy / hbar
nstar = Z * np.sqrt(2.1787e-18 / ionization_energy)
omega_t = lambda field: e * np.abs(field) / np.sqrt(2 * me * ionization_energy)
Cnstar = 2 ** (2 * nstar) / (scipy.special.gamma(nstar + 1) ** 2)
omega_C = omega_p / 4 * math.abs2(Cnstar)
def rate(field: np.ndarray) -> np.ndarray:
opt4 = 4 * omega_t(field) / om
return omega_C * (4 * omega_p / ot) ** (2 * nstar - 1) * np.exp(-4 * omega_p / (3 * ot))
return rate
class Plasma:
def __init__(self, t: np.ndarray, ionization_energy: float, atomic_number: int):
self.t = t
self.Ip = ionization_energy
self.atomic_number = atomic_number
self.rate = ionization_rate_ADK(self.Ip, self.atomic_number)
def __call__(self, field: np.ndarray, N0: float) -> np.ndarray:
"""returns the number density of free electrons as function of time
Parameters
----------
field : np.ndarray
electric field in V/m
N0 : float
total number density of matter
Returns
-------
np.ndarray
number density of free electrons as function of time
"""
Ne = free_electron_density(self.t, field, N0, self.rate)
return cumulative_trapezoid(
np.gradient(Ne, self.t) * self.Ip / field, self.t, initial=0
) + e ** 2 / me * cumulative_trapezoid(
cumulative_trapezoid(Ne * field, self.t, initial=0), self.t, initial=0
)

View File

@@ -572,7 +572,7 @@ def peak_ind(values, mam=None):
) + 3
except IndexError:
right_ind = len(values) - 1
return left_ind, right_ind
return max(0, left_ind), min(len(values) - 1, right_ind)
def setup_splines(x_axis, values, mam=None):
@@ -685,8 +685,7 @@ def find_lobe_limits(x_axis, values, debug="", already_sorted=True):
dd_roots,
fwhm_pos,
peak_pos,
folder_name,
file_name,
out_path,
fig,
ax,
color,
@@ -716,7 +715,7 @@ def find_lobe_limits(x_axis, values, debug="", already_sorted=True):
c=color[5],
)
ax.legend()
fig.savefig(os.path.join(folder_name, file_name), bbox_inches="tight")
fig.savefig(out_path, bbox_inches="tight")
plt.close(fig)
else:
@@ -818,9 +817,7 @@ def _detailed_find_lobe_limits(
# 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"
)
out_path, fig, ax = plot_setup(out_path=f"measurement_errors_plots/it_{iterations}_{debug}")
new_fwhm_pos = np.array([np.max(left_pos), np.min(right_pos)])
@@ -842,8 +839,7 @@ def _detailed_find_lobe_limits(
dd_roots,
fwhm_pos,
peak_pos,
folder_name,
file_name,
out_path,
fig,
ax,
color,
@@ -946,7 +942,7 @@ def measure_field(t: np.ndarray, field: np.ndarray) -> Tuple[float, float, float
def remove_2nd_order_dispersion(
spectrum: T, w_c: np.ndarray, beta2: float, max_z: float = -1.0
spectrum: T, w_c: np.ndarray, beta2: float, max_z: float = -100.0
) -> tuple[T, OptimizeResult]:
"""attempts to remove 2nd order dispersion from a complex spectrum
@@ -964,11 +960,49 @@ def remove_2nd_order_dispersion(
np.ndarray, shape (n, )
spectrum with 2nd order dispersion removed
"""
# makeshift_t = np.linspace(0, 1, len(w_c))
propagate = lambda z: spectrum * np.exp(-0.5j * beta2 * w_c ** 2 * z)
def score(z):
return 1 / np.max(abs2(np.fft.ifft(propagate(z))))
return -np.max(abs2(np.fft.ifft(propagate(z))))
opti = minimize_scalar(score, bracket=(max_z, 0))
return propagate(opti.x), opti
def remove_2nd_order_dispersion2(
spectrum: T, w_c: np.ndarray, max_gdd: float = 1000e-30
) -> tuple[T, OptimizeResult]:
"""attempts to remove 2nd order dispersion from a complex spectrum
Parameters
----------
spectrum : np.ndarray or Spectrum, shape (n, )
spectrum from which to remove 2nd order dispersion
w_c : np.ndarray, shape (n, )
corresponding centered angular frequencies (w-w0)
Returns
-------
np.ndarray, shape (n, )
spectrum with 2nd order dispersion removed
"""
propagate = lambda gdd: spectrum * np.exp(-0.5j * w_c ** 2 * 1e-30 * gdd)
integrate = lambda gdd: abs2(np.fft.ifft(propagate(gdd)))
def score(gdd):
return -np.sum(integrate(gdd) ** 6)
# def score(gdd):
# return -np.max(integrate(gdd))
# to_test = np.linspace(-max_gdd, max_gdd, 200)
# scores = [score(g) for g in to_test]
# fig, ax = plt.subplots()
# ax.plot(to_test, scores / np.min(scores))
# plt.show()
# plt.close(fig)
# ama = np.argmin(scores)
opti = minimize_scalar(score, bounds=(-max_gdd * 1e30, max_gdd * 1e30))
opti["x"] *= 1e-30
return propagate(opti.x * 1e30), opti

View File

@@ -1,5 +1,6 @@
import multiprocessing
import os
import random
from datetime import datetime
from pathlib import Path
from typing import Dict, List, Tuple, Type
@@ -704,7 +705,7 @@ def new_simulation(
if prev_sim_dir is not None:
config_dict["prev_sim_dir"] = str(prev_sim_dir)
task_id = np.random.randint(1e9, 1e12)
task_id = random.randint(1e9, 1e12)
if prev_sim_dir is None:
param_seq = initialize.ParamSequence(config_dict)
@@ -718,7 +719,7 @@ def new_simulation(
def resume_simulations(sim_dir: Path, method: Type[Simulations] = None) -> Simulations:
task_id = np.random.randint(1e9, 1e12)
task_id = random.randint(1e9, 1e12)
config = io.load_toml(sim_dir / "initial_config.toml")
io.set_data_folder(task_id, sim_dir)
param_seq = initialize.RecoveryParamSequence(config, task_id)

View File

@@ -30,6 +30,7 @@ def plot_setup(
- an axis
"""
out_path = defaults["name"] if out_path is None else out_path
out_path = Path(out_path)
plot_name = out_path.name.replace(f".{file_type}", "")
out_dir = out_path.resolve().parent