Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement charge trapping models #414

Merged
merged 12 commits into from
Oct 7, 2024
5 changes: 3 additions & 2 deletions .github/workflows/Downgrade.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ on:
pull_request:
branches:
- main
- dev
paths-ignore:
- 'docs/**'
push:
branches:
- main
- dev
paths-ignore:
- 'docs/**'
jobs:
Expand All @@ -22,10 +24,9 @@ jobs:
with:
version: ${{ matrix.version }}
- name: Add LegendJuliaRegistry
run: julia -e 'using Pkg; Pkg.Registry.add(Pkg.RegistrySpec(url = "https://github.com/JuliaRegistries/General")); Pkg.Registry.add(Pkg.RegistrySpec(url = "https://github.com/legend-exp/LegendJuliaRegistry"))'
run: julia -e 'using Pkg; Pkg.Registry.add("General"); Pkg.Registry.add(Pkg.RegistrySpec(url = "https://github.com/legend-exp/LegendJuliaRegistry"))'
shell: bash
- uses: julia-actions/julia-downgrade-compat@v1
# if: ${{ matrix.version == '1.6' }}
with:
skip: Pkg,TOML
- uses: julia-actions/julia-buildpkg@v1
Expand Down
91 changes: 90 additions & 1 deletion docs/src/man/charge_drift.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@ The first step is to define a `struct` for the model which is a subtype of `Soli
```julia
using SolidStateDetectors
using SolidStateDetectors: SSDFloat, AbstractChargeDriftModel
using StaticArrays

struct CustomChargeDriftModel{T <: SSDFloat} <: AbstractChargeDriftModel{T}
# optional fields to parameterize the model
Expand All @@ -155,6 +154,7 @@ The second step is to define two methods (`getVe` for electrons and `getVh` for
Note, that the vectors are in cartesian coordinates, independent of the coordinate system (cartesian or cylindrical) of the simulation.

```julia
using StaticArrays
function SolidStateDetectors.getVe(fv::SVector{3, T}, cdm::CustomChargeDriftModel)::SVector{3, T} where {T <: SSDFloat}
# arbitrary transformation of fv
return -fv
Expand All @@ -173,6 +173,95 @@ charge_drift_model = CustomChargeDriftModel{T}()
sim.detector = SolidStateDetector(sim.detector, charge_drift_model)
```



## Charge Trapping Models

Electrons and holes can be trapped on their way to the contacts, resulting in a decrease in height of the observed charge pulse. SolidStateDetectors.jl allows for incorporating and testing different charge trapping models.

In order to implement a charge trapping model, the first step is to define a `struct` for the model which is a subtype of `SolidStateDetectors.AbstractChargeTrappingModel`:

```julia
using SolidStateDetectors
using SolidStateDetectors: SSDFloat, AbstractChargeTrappingModel

struct CustomChargeTrappingModel{T <: SSDFloat} <: AbstractChargeTrappingModel{T}
# optional fields to parameterize the model
end
```

The second step would be to define a method for `_calculate_signal`, which returns a charge signal based on a given charge drift `path` and its `pathtimestamps`, the `charge` value of the charge cloud, the interpolated weighting potential `wpot` and the coordinate system type `S` (`Cartesian` or `Cylindrical`):

```julia
using SolidStateDetectors: CoordinateSystemType, SSDFloat
using Interpolations
function SolidStateDetectors._calculate_signal(
ctm::CustomChargeTrappingModel{T},
path::AbstractVector{CartesianPoint{T}},
pathtimestamps::AbstractVector{T},
charge::T,
wpot::Interpolations.Extrapolation{T, 3},
S::CoordinateSystemType
)::Vector{T} where {T <: SSDFloat}

# Implement method here
end
```

!!! note
So far, the charge trapping models do not influence the charge drift path simulation, but just the signal calculation afterwards.

### `NoChargeTrappingModel`

If no charge trapping model is selected, the default is the `NoChargeTrappingModel`.
In this case, the signal is calculated using the Schockley-Ramo theorem, i.e. by evaluating the weighting potential `wpot` at every point `path[i]` of the charge drift path and multiplying it with the `charge` of the charge cloud.


### `BoggsChargeTrappingModel`

In SolidStateDetectors.jl, the only charge trapping model implemented so far is the one presented in [Boggs _et al._ (2023)](https://doi.org/10.1016/j.nima.2023.168756).
In this model, the charge cloud loses part of its charge at every point `path[i]` of the charge drift, depending on its drift and thermal velocity, as well as the trapping product $[n\sigma_{E/h}]^{-1}$ for electrons and holes.
The charge signal is then given by the charge-decreased charge cloud reaching the contacts and the charges trapped on the way.

The `BoggsChargeTrappingModel` can be applied in the configuration file by adding a field `charge_trapping_model` to the `semiconductor` with `model: Boggs` and `parameters` defining the (inverse) trapping products and (optionally) the `temperature`:
```yaml
detectors:
- semiconductor:
material: #...
geometry: #...
charge_trapping_model:
model: Boggs
parameters:
nσe-1: 1020cm
nσh-1: 2040cm
temperature: 78K

# ... or ...

detectors:
- semiconductor:
material: #...
geometry: #...
charge_trapping_model:
model: Boggs
parameters:
nσe: 0.001cm^-1
nσh: 0.0005cm^-1
temperature: 78K
```

It can also be applied to an already read-in `SolidStateDetector` using for example:
```julia
using SolidStateDetectors, Unitful
T = Float32
sim = Simulation{T}(SSD_examples[:InvertedCoax])

parameters = Dict("parameters" =>
Dict("nσe-1" => 1000u"cm", "nσh-1" => 500u"cm", "temperature" => 78u"K"))
sim.detector = SolidStateDetector(sim.detector, BoggsChargeTrappingModel{T}(parameters))
```


## Group Effects

The movement of electrons and holes is not only given by the forces resulting from external electric fields. In addition, diffusion and self-repulsion of the charge carriers can play a significant role when simulating drift paths. To simulate this, electron and holes cannot be described as single point-like charges anymore, but as charge clouds consisting of multiple point-like charges. SolidStateDetectors.jl offers different models for the [Initial Charge Cloud Distribution](@ref). Right now, [Diffusion](@ref) and [Self-Repulsion](@ref) are implemented as experimental features.
Expand Down
159 changes: 159 additions & 0 deletions examples/example_config_files/public_ivc_trapping_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
name: Public Inverted Coax
units:
length: mm
angle: deg
potential: V
temperature: K
grid:
coordinates: cylindrical
axes:
r:
to: 40
boundaries: inf
phi:
from: 0
to: 0
boundaries: periodic
z:
from: -10
to: 90
boundaries:
left: inf
right: inf
# grid:
# coordinates: cartesian
# axes:
# x:
# from: -40
# to: 40
# boundaries:
# left: inf
# right: inf
# y:
# from: -40
# to: 40
# boundaries:
# left: inf
# right: inf
# z:
# from: -10
# to: 90
# boundaries:
# left: inf
# right: inf
medium: vacuum
detectors:
- semiconductor:
material: HPGe
temperature: 78
impurity_density:
name: cylindrical
r:
init: 0
gradient: 0
z:
init: -1e7
gradient: -1e5
charge_drift_model:
include: ADLChargeDriftModel/drift_velocity_config.yaml
charge_trapping_model:
model: Boggs
parameters:
nσe-1: 1020cm
nσh-1: 2040cm
geometry:
difference:
- tube:
r: 35
h: 80
origin:
z: 40
- cone:
r:
bottom:
from: 35
to: 36
top:
from: 23.71
to: 36
h: 64
origin:
z: 52
- tube:
r: 5
h: 80
origin:
z: 65
contacts:
- material: HPGe
id: 1
potential: 0
geometry:
tube:
r: 3
h: 2
origin:
z: 1
- material: HPGe
id: 2
potential: 3500
geometry:
union:
- tube:
r:
from: 15
to: 35
h: 0
- tube:
r:
from: 35
to: 35
h: 20
origin:
z: 10
- cone:
r:
bottom:
from: 35
to: 35
top:
from: 24.42
to: 24.42
h: 60
origin:
z: 50
- tube:
r:
from: 5
to: 24.42
h: 0
origin:
z: 80
- tube:
r:
from: 5
to: 5
h: 55
origin:
z: 52.5
- tube:
r: 5
h: 0
origin:
z: 25
surroundings:
- material: HPGe
name: Passivation Layer
geometry:
tube:
r:
from: 4
to: 14
h: 0.1
origin:
- 0
- 0
- -0.05
charge_density:
name: constant
value: 0 # Reasonable density: +2e-11 # => 2*10⁻¹1 C/m⁻³
Loading
Loading