-
Notifications
You must be signed in to change notification settings - Fork 54
Expand file tree
/
Copy pathChargeTrapping.jl
More file actions
123 lines (96 loc) · 5.03 KB
/
ChargeTrapping.jl
File metadata and controls
123 lines (96 loc) · 5.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
abstract type AbstractChargeTrappingModel{T <: SSDFloat} end
function _calculate_signal(
::AbstractChargeTrappingModel{T},
path::AbstractVector{CartesianPoint{T}},
pathtimestamps::AbstractVector{T},
charge::T,
wpot::Interpolations.Extrapolation{T, 3},
S::CoordinateSystemType
) where {T <: SSDFloat}
throw("For the chosen charge trapping model, no method for `_calculate_signal` is implemented.")
end
"""
struct NoChargeTrappingModel{T <: SSDFloat} <: AbstractChargeTrappingModel{T}
Charge trapping model, in which no charges are trapped during the charge drift.
This model is the default when no charge trapping model is defined in the configuration file.
"""
struct NoChargeTrappingModel{T <: SSDFloat} <: AbstractChargeTrappingModel{T} end
function _calculate_signal(
::NoChargeTrappingModel{T},
path::AbstractVector{CartesianPoint{T}},
pathtimestamps::AbstractVector{T},
charge::T,
wpot::Interpolations.Extrapolation{T, 3},
S::CoordinateSystemType
)::Vector{T} where {T <: SSDFloat}
tmp_signal::Vector{T} = Vector{T}(undef, length(pathtimestamps))
@inbounds for i in eachindex(tmp_signal)
tmp_signal[i] = get_interpolation(wpot, path[i], S)::T * charge
end
tmp_signal
end
NoChargeTrappingModel(args...; T::Type{<:SSDFloat} = Float32, kwargs...) = NoChargeTrappingModel{T}(args...; kwargs...)
NoChargeTrappingModel{T}(config_dict::AbstractDict; kwargs...) where {T <: SSDFloat} = NoChargeTrappingModel{T}()
"""
struct BoggsChargeTrappingModel{T <: SSDFloat} <: AbstractChargeTrappingModel{T}
Charge trapping model presented in [Boggs _et al._ (2023)](https://doi.org/10.1016/j.nima.2023.168756).
## Fields
* `nσe::T`: Trapping product for electrons (default: `(nσe)^-1 = 1020cm`).
* `nσh::T`: Trapping product for holes (default: `(nσh)^-1 = 2040cm`).
* `temperature::T`: Temperature of the crystal (default: `78K`).
See also [Charge Trapping Models](@ref).
"""
struct BoggsChargeTrappingModel{T <: SSDFloat} <: AbstractChargeTrappingModel{T}
nσe::T # in m^-1
nσh::T # in m^-1
meffe::T # in units of me
meffh::T # in units of me
temperature::T # in K
end
function _calculate_signal(
ctm::BoggsChargeTrappingModel{T},
path::AbstractVector{CartesianPoint{T}},
pathtimestamps::AbstractVector{T},
charge::T,
wpot::Interpolations.Extrapolation{T, 3},
S::CoordinateSystemType
)::Vector{T} where {T <: SSDFloat}
vth::T = sqrt(3 * kB * ctm.temperature / (ifelse(charge > 0, ctm.meffh, ctm.meffe) * me)) # in m/s
nσ::T = ifelse(charge > 0, ctm.nσh, ctm.nσe)
tmp_signal::Vector{T} = Vector{T}(undef, length(pathtimestamps))
running_sum::T = zero(T)
q::T = charge
@inbounds for i in eachindex(tmp_signal)
Δldrift::T = (i > 1) ? norm(path[i] - path[i-1]) : zero(T)
Δl::T = Δldrift > 0 ? hypot(Δldrift, vth * (pathtimestamps[i] - pathtimestamps[i-1])) : zero(T)
Δq::T = q * nσ * Δl
q -= Δq
w::T = i > 1 ? get_interpolation(wpot, path[i], S) : zero(T)
running_sum += w * Δq
tmp_signal[i] = running_sum + w * q
end
tmp_signal
end
BoggsChargeTrappingModel(args...; T::Type{<:SSDFloat}, kwargs...) = BoggsChargeTrappingModel{T}(args...; kwargs...)
function BoggsChargeTrappingModel{T}(config_dict::AbstractDict = Dict(); temperature::RealQuantity = T(78)) where {T <: SSDFloat}
nσe::T = ustrip(u"m^-1", inv(1020u"cm"))
nσh::T = ustrip(u"m^-1", inv(2040u"cm"))
meffe::T = 0.12
meffh::T = 0.21
temperature::T = _parse_value(T, temperature, internal_temperature_unit)
if haskey(config_dict, "model") && !haskey(config_dict, "parameters")
throw(ConfigFileError("`BoggsChargeTrappingModel` does not have `parameters`"))
end
parameters = haskey(config_dict, "parameters") ? config_dict["parameters"] : config_dict
allowed_keys = ("nσe","nσe-1","nσh","nσh-1","meffe","meffh","temperature")
k = filter(k -> !(k in allowed_keys), keys(parameters))
!isempty(k) && @warn "The following keys will be ignored: $(k).\nAllowed keys are: $(allowed_keys)"
if haskey(parameters, "nσe") nσe = _parse_value(T, parameters["nσe"], internal_length_unit^-1) end
if haskey(parameters, "nσe-1") nσe = inv(_parse_value(T, parameters["nσe-1"], internal_length_unit)) end
if haskey(parameters, "nσh") nσh = _parse_value(T, parameters["nσh"], internal_length_unit^-1) end
if haskey(parameters, "nσh-1") nσh = inv(_parse_value(T, parameters["nσh-1"], internal_length_unit)) end
if haskey(parameters, "meffe") meffe = _parse_value(T, parameters["meffe"], Unitful.NoUnits) end
if haskey(parameters, "meffh") meffh = _parse_value(T, parameters["meffh"], Unitful.NoUnits) end
if haskey(parameters, "temperature") temperature = _parse_value(T, parameters["temperature"], internal_temperature_unit) end
BoggsChargeTrappingModel{T}(nσe, nσh, meffe, meffh, temperature)
end