@@ -11,11 +11,13 @@ the external field, and the interactions possible, the actual process
11
11
is described by a [`Diagram`](@ref).
12
12
"""
13
13
struct System{T,IonizationChannels<: AbstractVector{<:IonizationChannel{T}} ,
14
+ IonDipoleCouplings,
14
15
Couplings<: AbstractVector{<:AbstractMatrix{<:AbstractCoupling}} ,
15
16
VectorPotential,
16
17
Times<: AbstractRange ,
17
18
Volkov<: VolkovPhases }
18
19
ionization_channels:: IonizationChannels
20
+ 𝐫ᵢₒₙ:: IonDipoleCouplings
19
21
20
22
couplings:: Couplings
21
23
@@ -26,60 +28,79 @@ struct System{T,IonizationChannels<:AbstractVector{<:IonizationChannel{T}},
26
28
volkov:: Volkov
27
29
end
28
30
31
+ IonDipoleCouplingsType = Union{AbstractMatrix{<: Number },UniformScaling,SVector{3 },Nothing}
32
+ NoCouplings = Matrix{AbstractCoupling}[]
33
+
29
34
"""
30
- System(ionization_channels, couplings, F, ndt)
35
+ System(ionization_channels, 𝐫ᵢₒₙ, couplings, F, ndt)
31
36
32
37
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`.
35
41
"""
36
42
function System (ionization_channels:: AbstractVector{<:IonizationChannel} ,
43
+ 𝐫ᵢₒₙ:: IonDipoleCouplingsType ,
37
44
couplings:: AbstractVector ,
38
45
F:: ElectricFields.AbstractField , fs:: Number )
39
46
t = timeaxis (F, fs)
40
47
volkov = VolkovPhases (F, t)
41
48
42
49
𝐀 = vector_potential .(F, t)
43
- System (ionization_channels, couplings, 𝐀, t, step (t), volkov)
50
+ System (ionization_channels, 𝐫ᵢₒₙ, couplings, 𝐀, t, step (t), volkov)
44
51
end
45
52
46
53
@doc raw """
47
- System(ionization_channels, couplings, Fv, Av, t)
54
+ System(ionization_channels, 𝐫ᵢₒₙ, couplings, Fv, Av, t)
48
55
49
56
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 ``\v ec{F} = -\p artial_t\v ec{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 ``\v ec{F} =
61
+ -\p artial_t\v ec{A}`` holds.
54
62
"""
55
63
function System (ionization_channels:: AbstractVector{<:IonizationChannel} ,
56
- couplings:: AbstractVector ,
64
+ 𝐫ᵢₒₙ :: IonDipoleCouplingsType , couplings:: AbstractVector ,
57
65
Fv:: AbstractVector , Av:: AbstractVector , t:: AbstractRange )
58
66
volkov = VolkovPhases (Av, t)
59
67
60
- System (ionization_channels, couplings, Av, t, step (t), volkov)
68
+ System (ionization_channels, 𝐫ᵢₒₙ, couplings, Av, t, step (t), volkov)
61
69
end
62
70
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)
69
75
70
76
System (Iₚ:: Number , args... ; kwargs... ) =
71
- System (IonizationChannel (Iₚ, args... ), args... ; kwargs... )
77
+ System ([ IonizationChannel (Iₚ, args... )] , args... ; kwargs... )
72
78
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 " )
77
83
78
84
function Base. show (io:: IO , mime:: MIME"text/plain" , system:: System )
79
85
println (io, system, " :" )
80
86
for (i,c) in enumerate (system. ionization_channels)
81
87
println (io, " " , i, " . " , c)
82
88
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
83
104
end
84
105
85
106
canonical_momentum_conservation (system:: System , which:: Integer ) =
@@ -185,6 +206,14 @@ struct Diagram{Couplings}
185
206
which == 0 ||
186
207
throw (ArgumentError (" Non-empty diagrams must have photoionization as the first interaction" ))
187
208
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
188
217
for i = 2 : length (path)- 1
189
218
path[i][2 ] == 0 &&
190
219
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
209
238
channel of `system` will automatically be generated.
210
239
"""
211
240
function Diagram (path:: AbstractVector , system:: System )
241
+ nc = length (system. ionization_channels)
212
242
if isempty (path)
213
- length (system . ionization_channels) > 1 &&
243
+ nc > 1 &&
214
244
@warn " More than one ionization channel present in system, choosing the first"
215
245
path = [(1 ,0 )]
216
246
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
217
254
Diagram (path, [typeof (first (c)) for c in system. couplings])
218
255
end
219
256
0 commit comments