removed phase term from photoionization

This commit is contained in:
Benoît Sierro
2021-12-20 11:45:03 +01:00
parent c36ece6697
commit b8f18bc104
4 changed files with 42 additions and 30 deletions

View File

@@ -386,7 +386,6 @@ default_rules: list[Rule] = [
Rule("n_op", operators.MarcatiliAdjustedRefractiveIndex), Rule("n_op", operators.MarcatiliAdjustedRefractiveIndex),
Rule("n_op", operators.HasanRefractiveIndex), Rule("n_op", operators.HasanRefractiveIndex),
Rule("gas_op", operators.ConstantGas), Rule("gas_op", operators.ConstantGas),
Rule("raman_op", operators.NoRaman, priorities=-1),
Rule("loss_op", operators.NoLoss, priorities=-1), Rule("loss_op", operators.NoLoss, priorities=-1),
Rule("conserved_quantity", operators.NoConservedQuantity, priorities=-1), Rule("conserved_quantity", operators.NoConservedQuantity, priorities=-1),
] ]
@@ -422,6 +421,7 @@ envelope_rules = default_rules + [
Rule("spm_op", operators.NoEnvelopeSPM, priorities=-1), Rule("spm_op", operators.NoEnvelopeSPM, priorities=-1),
Rule("spm_op", operators.EnvelopeSPM), Rule("spm_op", operators.EnvelopeSPM),
Rule("raman_op", operators.EnvelopeRaman), Rule("raman_op", operators.EnvelopeRaman),
Rule("raman_op", operators.NoEnvelopeRaman, priorities=-1),
Rule("nonlinear_operator", operators.EnvelopeNonLinearOperator), Rule("nonlinear_operator", operators.EnvelopeNonLinearOperator),
Rule("loss_op", operators.CustomLoss, priorities=3), Rule("loss_op", operators.CustomLoss, priorities=3),
Rule("loss_op", operators.CapillaryLoss, priorities=2, conditions=dict(loss="capillary")), Rule("loss_op", operators.CapillaryLoss, priorities=2, conditions=dict(loss="capillary")),
@@ -454,5 +454,6 @@ full_field_rules = default_rules + [
), ),
Rule("plasma_op", operators.Plasma, conditions=dict(photoionization=True)), Rule("plasma_op", operators.Plasma, conditions=dict(photoionization=True)),
Rule("plasma_op", operators.NoPlasma, priorities=-1), Rule("plasma_op", operators.NoPlasma, priorities=-1),
Rule("raman_op", operators.NoFullFieldRaman, priorities=-1),
Rule("nonlinear_operator", operators.FullFieldNonLinearOperator), Rule("nonlinear_operator", operators.FullFieldNonLinearOperator),
] ]

View File

@@ -630,7 +630,7 @@ class CustomLoss(ConstantLoss):
class AbstractRaman(Operator): class AbstractRaman(Operator):
f_r: float = 0.0 fraction: float = 0.0
@abstractmethod @abstractmethod
def __call__(self, state: CurrentState) -> np.ndarray: def __call__(self, state: CurrentState) -> np.ndarray:
@@ -647,27 +647,34 @@ class AbstractRaman(Operator):
""" """
class NoRaman(NoOpTime, AbstractRaman): class NoEnvelopeRaman(NoOpTime, AbstractRaman):
pass
class NoFullFieldRaman(NoOpFreq, AbstractRaman):
pass pass
class EnvelopeRaman(AbstractRaman): class EnvelopeRaman(AbstractRaman):
def __init__(self, raman_type: str, t: np.ndarray): def __init__(self, raman_type: str, t: np.ndarray):
self.hr_w = fiber.delayed_raman_w(t, raman_type) self.hr_w = fiber.delayed_raman_w(t, raman_type)
self.f_r = 0.245 if raman_type == "agrawal" else 0.18 self.fraction = 0.245 if raman_type == "agrawal" else 0.18
def __call__(self, state: CurrentState) -> np.ndarray: def __call__(self, state: CurrentState) -> np.ndarray:
return self.f_r * np.fft.ifft(self.hr_w * np.fft.fft(state.field2)) return self.fraction * np.fft.ifft(self.hr_w * np.fft.fft(state.field2))
class FullFieldRaman(AbstractRaman): class FullFieldRaman(AbstractRaman):
def __init__(self, raman_type: str, t: np.ndarray, chi3: float): def __init__(self, raman_type: str, t: np.ndarray, w: np.ndarray, chi3: float):
self.hr_w = fiber.delayed_raman_w(t, raman_type) self.hr_w = fiber.delayed_raman_w(t, raman_type)
self.f_r = 0.245 if raman_type == "agrawal" else 0.18 self.fraction = 0.245 if raman_type == "agrawal" else 0.18
self.multiplier = units.epsilon0 * chi3 * self.f_r self.factor_in = units.epsilon0 * chi3 * self.fraction
self.factor_out = 1j * w ** 2 / (2.0 * units.c ** 2 * units.epsilon0)
def __call__(self, state: CurrentState) -> np.ndarray: def __call__(self, state: CurrentState) -> np.ndarray:
return self.multiplier * np.fft.ifft(np.fft.fft(state.field2) * self.hr_w) return self.factor_out * np.fft.rfft(
self.factor_in * state.field * np.fft.irfft(self.hr_w * np.fft.rfft(state.field2))
)
################################################## ##################################################
@@ -703,19 +710,20 @@ class NoFullFieldSPM(NoOpTime, AbstractSPM):
class EnvelopeSPM(AbstractSPM): class EnvelopeSPM(AbstractSPM):
def __init__(self, raman_op: AbstractRaman): def __init__(self, raman_op: AbstractRaman):
self.fraction = 1 - raman_op.f_r self.fraction = 1 - raman_op.fraction
def __call__(self, state: CurrentState) -> np.ndarray: def __call__(self, state: CurrentState) -> np.ndarray:
return self.fraction * state.field2 return self.fraction * state.field2
class FullFieldSPM(AbstractSPM): class FullFieldSPM(AbstractSPM):
def __init__(self, raman_op: AbstractRaman, chi3: float): def __init__(self, raman_op: AbstractRaman, w: np.ndarray, chi3: float):
self.fraction = 1 - raman_op.f_r self.fraction = 1 - raman_op.fraction
self.factor = self.fraction * chi3 * units.epsilon0 self.factor_out = 1j * w ** 2 / (2.0 * units.c ** 2 * units.epsilon0)
self.factor_in = self.fraction * chi3 * units.epsilon0
def __call__(self, state: CurrentState) -> np.ndarray: def __call__(self, state: CurrentState) -> np.ndarray:
return self.factor * state.field2 * state.field return self.factor_out * np.fft.rfft(self.factor_in * state.field2 * state.field)
################################################## ##################################################
@@ -804,19 +812,20 @@ class Plasma(Operator):
gas_op: AbstractGas gas_op: AbstractGas
ionization_fraction = 0.0 ionization_fraction = 0.0
def __init__(self, dt: float, gas_op: AbstractGas): def __init__(self, dt: float, w: np.ndarray, gas_op: AbstractGas):
self.gas_op = gas_op self.gas_op = gas_op
self.mat_plasma = plasma.Plasma( self.mat_plasma = plasma.Plasma(
dt, dt,
self.gas_op.material_dico["ionization_energy"], self.gas_op.material_dico["ionization_energy"],
plasma.IonizationRateADK(self.gas_op.material_dico["ionization_energy"]), plasma.IonizationRateADK(self.gas_op.material_dico["ionization_energy"]),
) )
self.factor_out = -w / (2.0 * units.c ** 2 * units.epsilon0)
def __call__(self, state: CurrentState) -> np.ndarray: def __call__(self, state: CurrentState) -> np.ndarray:
N0 = self.gas_op.number_density(state) N0 = self.gas_op.number_density(state)
plasma_info = self.mat_plasma(state.field, N0) plasma_info = self.mat_plasma(state.field, N0)
self.ionization_fraction = plasma_info.electron_density[-1] / N0 self.ionization_fraction = plasma_info.electron_density[-1] / N0
return plasma_info.polarization return self.factor_out * np.fft.rfft(plasma_info.dp_dt)
def values(self) -> dict[str, float]: def values(self) -> dict[str, float]:
return dict(ionization_fraction=self.ionization_fraction) return dict(ionization_fraction=self.ionization_fraction)
@@ -902,7 +911,7 @@ def conserved_quantity(
if not adapt_step_size: if not adapt_step_size:
return NoConservedQuantity() return NoConservedQuantity()
logger = get_logger(__name__) logger = get_logger(__name__)
raman = not isinstance(raman_op, NoRaman) raman = not isinstance(raman_op, NoEnvelopeRaman)
loss = not isinstance(loss_op, NoLoss) loss = not isinstance(loss_op, NoLoss)
if raman and loss: if raman and loss:
logger.debug("Conserved quantity : photon number with loss") logger.debug("Conserved quantity : photon number with loss")
@@ -1023,4 +1032,4 @@ class FullFieldNonLinearOperator(NonLinearOperator):
def __call__(self, state: CurrentState) -> np.ndarray: def __call__(self, state: CurrentState) -> np.ndarray:
total_nonlinear = self.spm_op(state) + self.raman_op(state) + self.plasma_op(state) total_nonlinear = self.spm_op(state) + self.raman_op(state) + self.plasma_op(state)
return self.factor / self.beta_op(state) * np.fft.rfft(total_nonlinear) return total_nonlinear / self.beta_op(state)

View File

@@ -12,7 +12,7 @@ T_a = TypeVar("T_a", np.floating, np.ndarray)
@dataclass @dataclass
class PlasmaInfo: class PlasmaInfo:
electron_density: np.ndarray electron_density: np.ndarray
polarization: np.ndarray dp_dt: np.ndarray
rate: np.ndarray rate: np.ndarray
dn_dt: np.ndarray dn_dt: np.ndarray
debug: np.ndarray debug: np.ndarray
@@ -79,18 +79,15 @@ class Plasma:
rate = self.rate(field_abs) rate = self.rate(field_abs)
electron_density = free_electron_density(rate, self.dt, N0) electron_density = free_electron_density(rate, self.dt, N0)
dn_dt: np.ndarray = (N0 - electron_density) * rate dn_dt: np.ndarray = (N0 - electron_density) * rate
integrand = np.zeros_like(field)
integrand[nzi] = dn_dt[nzi] * self.ionization_energy / field[nzi]
energy_loss = self.dt * cumulative_simpson(integrand) loss_term = np.zeros_like(field)
added_phase = ( loss_term[nzi] = dn_dt[nzi] * self.ionization_energy / field[nzi]
self.dt ** 2
* e ** 2 phase_term = self.dt * e ** 2 / me * cumulative_simpson(electron_density * field)
/ me
* cumulative_simpson(cumulative_simpson(electron_density * field)) # polarization = -loss_integrated + phase_integrated
) dp_dt = loss_term
polarization = energy_loss + added_phase return PlasmaInfo(electron_density, dp_dt, rate, dn_dt, phase_term)
return PlasmaInfo(electron_density, polarization, rate, dn_dt, (energy_loss, added_phase))
def adiabadicity(w: np.ndarray, I: float, field: np.ndarray) -> np.ndarray: def adiabadicity(w: np.ndarray, I: float, field: np.ndarray) -> np.ndarray:

View File

@@ -19,6 +19,11 @@ from .operators import (
from .utils import get_arg_names from .utils import get_arg_names
import warnings import warnings
class IntegratorError(Exception):
pass
# warnings.filterwarnings("error") # warnings.filterwarnings("error")