Skip to content

Commit a0ff457

Browse files
committed
Support ionic dipole couplings and tabulated electric fields
1 parent 25a918b commit a0ff457

File tree

2 files changed

+67
-27
lines changed

2 files changed

+67
-27
lines changed

src/channels.jl

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ dipole(F::Number, d::Number) = F*d
3636
dipole(F::SVector{3}, d::SVector{3}) = dot(F, d)
3737
dipole(F::Number, d::SVector{3}) = F*d[3]
3838

39-
source_term(d::DipoleSourceTerm{<:Any,<:ElectricFields.AbstractField}, t, p) =
40-
dipole(field_amplitude(d.F, t), d.d(p))
39+
_field_amplitude(F::ElectricFields.AbstractField, t) =
40+
field_amplitude(F, t)
41+
_field_amplitude(F::AbstractVector, i::Integer) = F[i]
4142

42-
source_term(d::DipoleSourceTerm{<:Any,<:AbstractVector}, i::Integer, p) =
43-
dipole(d.F[i], d.d(p))
43+
source_term(d::DipoleSourceTerm, t, p) = dipole(_field_amplitude(d.F, t), d.d(p))
4444

4545
# * Ionizations channels
4646

@@ -54,6 +54,8 @@ Represents an ionization channel with energy `E` above the neutral
5454
struct IonizationChannel{T,SourceTerm<:AbstractSourceTerm}
5555
E::T
5656
st::SourceTerm
57+
IonizationChannel(E::T, st::SourceTerm) where {T,SourceTerm} =
58+
new{T,SourceTerm}(E, st)
5759
end
5860

5961
source_term(ic::IonizationChannel, args...) =
@@ -85,6 +87,7 @@ canonical_momentum_conservation(::Type{<:AbstractCoupling}) = NoCanonicalMomentu
8587
struct NoCoupling <: AbstractCoupling end
8688
Base.iszero(::NoCoupling) = true
8789
Base.zero(::AbstractCoupling) = NoCoupling()
90+
Base.zero(::Type{<:AbstractCoupling}) = NoCoupling()
8891

8992
Base.show(io::IO, ::NoCoupling) = write(io, "0")
9093

src/dyson_expansions.jl

Lines changed: 60 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ the external field, and the interactions possible, the actual process
1111
is described by a [`Diagram`](@ref).
1212
"""
1313
struct System{T,IonizationChannels<:AbstractVector{<:IonizationChannel{T}},
14+
IonDipoleCouplings,
1415
Couplings<:AbstractVector{<:AbstractMatrix{<:AbstractCoupling}},
1516
VectorPotential,
1617
Times<:AbstractRange,
1718
Volkov<:VolkovPhases}
1819
ionization_channels::IonizationChannels
20+
𝐫ᵢₒₙ::IonDipoleCouplings
1921

2022
couplings::Couplings
2123

@@ -26,60 +28,79 @@ struct System{T,IonizationChannels<:AbstractVector{<:IonizationChannel{T}},
2628
volkov::Volkov
2729
end
2830

31+
IonDipoleCouplingsType = Union{AbstractMatrix{<:Number},UniformScaling,SVector{3},Nothing}
32+
NoCouplings = Matrix{AbstractCoupling}[]
33+
2934
"""
30-
System(ionization_channels, couplings, F, ndt)
35+
System(ionization_channels, 𝐫ᵢₒₙ, couplings, F, ndt)
3136
3237
Set up a [`System`](@ref) consisting of multiple
33-
[`IonizationChannel`](@ref)s with possible `couplings` between them,
34-
driven by an external field `F`, sampled at a frequency of `fs`.
38+
[`IonizationChannel`](@ref)s with ionic dipole moments `𝐫ᵢₒₙ` and
39+
possible `couplings` between them, driven by an external field `F`,
40+
sampled at a frequency of `fs`.
3541
"""
3642
function System(ionization_channels::AbstractVector{<:IonizationChannel},
43+
𝐫ᵢₒₙ::IonDipoleCouplingsType,
3744
couplings::AbstractVector,
3845
F::ElectricFields.AbstractField, fs::Number)
3946
t = timeaxis(F, fs)
4047
volkov = VolkovPhases(F, t)
4148

4249
𝐀 = vector_potential.(F, t)
43-
System(ionization_channels, couplings, 𝐀, t, step(t), volkov)
50+
System(ionization_channels, 𝐫ᵢₒₙ, couplings, 𝐀, t, step(t), volkov)
4451
end
4552

4653
@doc raw"""
47-
System(ionization_channels, couplings, Fv, Av, t)
54+
System(ionization_channels, 𝐫ᵢₒₙ, couplings, Fv, Av, t)
4855
4956
Set up a [`System`](@ref) consisting of multiple
50-
[`IonizationChannel`](@ref)s with possible `couplings` between them,
51-
driven by an external field `Fv` with corresponding vector potential
52-
`Av`, both resolved on the times given by `t`; it is up to the user to
53-
ensure that ``\vec{F} = -\partial_t\vec{A}`` holds.
57+
[`IonizationChannel`](@ref)s with with ionic dipole moments `𝐫ᵢₒₙ` and
58+
possible `couplings` between them, driven by an external field `Fv`
59+
with corresponding vector potential `Av`, both resolved on the times
60+
given by `t`; it is up to the user to ensure that ``\vec{F} =
61+
-\partial_t\vec{A}`` holds.
5462
"""
5563
function System(ionization_channels::AbstractVector{<:IonizationChannel},
56-
couplings::AbstractVector,
64+
𝐫ᵢₒₙ::IonDipoleCouplingsType, couplings::AbstractVector,
5765
Fv::AbstractVector, Av::AbstractVector, t::AbstractRange)
5866
volkov = VolkovPhases(Av, t)
5967

60-
System(ionization_channels, couplings, Av, t, step(t), volkov)
68+
System(ionization_channels, 𝐫ᵢₒₙ, couplings, Av, t, step(t), volkov)
6169
end
6270

63-
System(ionization_channels::AbstractVector{<:IonizationChannel}, args...;
64-
couplings=Matrix{AbstractCoupling}[], kwargs...) =
65-
System(ionization_channels, couplings, args...)
66-
67-
System(ionization_channel::IonizationChannel, args...; kwargs...) =
68-
System([ionization_channel], args...; kwargs...)
71+
System(ionization_channels::AbstractVector{<:IonizationChannel},
72+
F::ElectricFields.AbstractField, fs::Number) =
73+
System(ionization_channels, nothing, NoCouplings,
74+
F, fs)
6975

7076
System(Iₚ::Number, args...; kwargs...) =
71-
System(IonizationChannel(Iₚ, args...), args...; kwargs...)
77+
System([IonizationChannel(Iₚ, args...)], args...; kwargs...)
7278

73-
function Base.show(io::IO, system::System)
74-
n = length(system.ionization_channels)
75-
write(io, "$(n)-channel System")
76-
end
79+
num_channels(system::System) = length(system.ionization_channels)
80+
81+
Base.show(io::IO, system::System) =
82+
write(io, "$(num_channels(system))-channel SFA System")
7783

7884
function Base.show(io::IO, mime::MIME"text/plain", system::System)
7985
println(io, system, ":")
8086
for (i,c) in enumerate(system.ionization_channels)
8187
println(io, " ", i, ". ", c)
8288
end
89+
if !isnothing(system.𝐫ᵢₒₙ)
90+
nz(A) = count(!iszero, A)
91+
nz(A,i) = count(e -> !iszero(e[i]), A)
92+
nz(I::UniformScaling) = iszero(I) ? 0 : 1
93+
println(io, "Channel dipole couplings:")
94+
if system.𝐫ᵢₒₙ isa SVector{3}
95+
for (i,d) in enumerate(("x","y","z"))
96+
nzd = nz(system.𝐫ᵢₒₙ[i])
97+
println(io, " - $d: $(nzd) non-zero couplings")
98+
end
99+
else
100+
nzz = nz(system.𝐫ᵢₒₙ)
101+
println(io, " - z: $(nzz) non-zero couplings")
102+
end
103+
end
83104
end
84105

85106
canonical_momentum_conservation(system::System, which::Integer) =
@@ -185,6 +206,14 @@ struct Diagram{Couplings}
185206
which == 0 ||
186207
throw(ArgumentError("Non-empty diagrams must have photoionization as the first interaction"))
187208
end
209+
ncoup = length(couplings)
210+
vcoup = 0:ncoup
211+
invalid_couplings = findall((vcoup), last.(path))
212+
if !isempty(invalid_couplings)
213+
length(invalid_couplings) == 1 &&
214+
throw(ArgumentError("Coupling at vertex $(first(invalid_couplings)) not in valid range $(vcoup)"))
215+
throw(ArgumentError("Couplings at vertices $(invalid_couplings) not in valid range $(vcoup)"))
216+
end
188217
for i = 2:length(path)-1
189218
path[i][2] == 0 &&
190219
throw(ArgumentError("Only the first and last interaction in a diagram may have which = 0 (corresponding to ionization/recombination)"))
@@ -209,11 +238,19 @@ diagram corresponding to photoionization into the first ionization of
209238
channel of `system` will automatically be generated.
210239
"""
211240
function Diagram(path::AbstractVector, system::System)
241+
nc = length(system.ionization_channels)
212242
if isempty(path)
213-
length(system.ionization_channels) > 1 &&
243+
nc > 1 &&
214244
@warn "More than one ionization channel present in system, choosing the first"
215245
path = [(1,0)]
216246
end
247+
vc = 1:nc
248+
invalid_channels = findall((vc), first.(path))
249+
if !isempty(invalid_channels)
250+
length(invalid_channels) == 1 &&
251+
throw(ArgumentError("Invalid channel at vertex $(first(invalid_channels))"))
252+
throw(ArgumentError("Invalid channels at vertices $(invalid_channels)"))
253+
end
217254
Diagram(path, [typeof(first(c)) for c in system.couplings])
218255
end
219256

0 commit comments

Comments
 (0)