Skip to content

Commit 020a266

Browse files
authored
Merge pull request #489 from JuliaPhysics/point-types
Change AbstractCoordinatePoint to not be a FieldVector
2 parents 314e52b + b6cdbf6 commit 020a266

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+682
-285
lines changed

.github/workflows/Downgrade.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
runs-on: ubuntu-latest
2020
strategy:
2121
matrix:
22-
version: ['1.10', '1']
22+
version: ['1.10', '1.12']
2323
steps:
2424
- uses: actions/checkout@v5
2525
- uses: julia-actions/setup-julia@v2

Project.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Format = "1fa38f19-a742-5d3f-a2b9-30dd87b9d5f8"
1414
GPUArrays = "0c68f7d7-f131-5f86-a1c3-88cf8149b2d7"
1515
Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"
1616
IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953"
17+
InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112"
1718
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
1819
KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c"
1920
LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
@@ -58,6 +59,7 @@ GPUArrays = "8, 9, 10, 11"
5859
Geant4 = "0.1.13, 0.2"
5960
Interpolations = "0.14, 0.15, 0.16"
6061
IntervalSets = "0.6, 0.7"
62+
InverseFunctions = "0.1"
6163
JSON = "0.21.2, 1.1"
6264
KernelAbstractions = "0.8, 0.9"
6365
LaTeXStrings = "1.1"
@@ -69,7 +71,7 @@ Parameters = "0.12"
6971
PolygonOps = "0.1.1"
7072
Polynomials = "2, 3, 4"
7173
ProgressMeter = "1.5"
72-
RadiationDetectorSignals = "0.3.5"
74+
RadiationDetectorSignals = "0.3.10"
7375
Random = "<0.0.1, 1"
7476
RecipesBase = "1"
7577
Requires = "1.1.3"

devenv/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
This directory contains the Julia project environments `cpu` and `cuda`
44
that can be used when developing SolidStateDetectors with Julia >= v1.11.
55
They contain all direct, test and doc-gen dependencies of SolidStateDetectors,
6-
plus BenchmarkTools and Cthulhu.
6+
plus BenchmarkTools, Cthulhu and JLD2 (for snapshots and regression tests
7+
during development).
78

89
Note: These environments can't be used with Julia versions <= v1.10, as they
910
use a `[sources]` section in the `Project.toml` to ensure SolidStateDetectors

devenv/cuda/Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
1818
Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"
1919
IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953"
2020
InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112"
21+
JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819"
2122
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
2223
KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c"
2324
LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"

docs/Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
[deps]
2+
ArraysOfArrays = "65a8f2f4-9b39-5baf-92e2-a9cc46fdf018"
23
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
34
Geant4 = "559df036-b7a0-42fd-85df-7d5dd9d70f44"
45
Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"

docs/src/tutorials/dead_layer_simulation_lit.jl

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@ using SolidStateDetectors
1111
T = Float64
1212

1313
# the geometry parameters of the model for following display
14-
mm=T(1/1000)
15-
det_rin=1*mm
16-
det_z=det_r=10*mm
17-
z_draw=det_z/2
18-
pn_r=8.957282*mm # this one was calculated by searching the zero impurity point (displayed in the following section)
14+
mm = T(1/1000)
15+
det_rin = 1*mm
16+
det_z = det_r = 10*mm
17+
z_draw = det_z/2
18+
pn_r = 8.957282*mm # this one was calculated by searching the zero impurity point (displayed in the following section)
1919

2020
sim = Simulation{T}(SSD_examples[:TrueCoaxial])
21-
cfn=SSD_examples[:TrueCoaxial]
21+
cfn = SSD_examples[:TrueCoaxial]
2222
print(open(f -> read(f, String), cfn))
2323
plot(sim.detector, xunit = u"mm", yunit = u"mm", zunit = u"mm")
2424
#jl savefig("tutorial_det_dl.pdf") # hide
@@ -28,10 +28,10 @@ plot(sim.detector, xunit = u"mm", yunit = u"mm", zunit = u"mm")
2828

2929
# ## Display the impurity profile defined
3030
# > Above position of the PN junction boundary `pn_r` is calculate by searching the point on the curve where the density is zero.
31-
r_list=(0*mm):(0.01*mm):det_r
31+
r_list = (0*mm):(0.01*mm):det_r
3232
imp_list = T[]
3333
for r in r_list
34-
pt=CylindricalPoint{T}(r, 0, z_draw)
34+
pt = CylindricalPoint{T}(r, 0, z_draw)
3535
push!(imp_list, SolidStateDetectors.get_impurity_density(sim.detector.semiconductor.impurity_density_model, pt))
3636
end
3737
imp_list = imp_list ./ 1e6 # in cm^-3
@@ -47,12 +47,11 @@ vline!([pn_r/mm], lw = 2, ls = :dash, color = :darkred, label = "PN junction bou
4747
using SolidStateDetectors: Electron, Hole
4848
cdm = sim.detector.semiconductor.charge_drift_model
4949
depth_list = 0:(0.01*mm):(det_r-pn_r)
50-
hole_mobility_list=[]
51-
electron_mobility_list=[]
50+
hole_mobility_list = []
51+
electron_mobility_list = []
5252
for depth in depth_list
53-
r=det_r-depth
54-
pt = CylindricalPoint{T}([r, 0, z_draw])
55-
pt = CartesianPoint{T}(pt)
53+
r = det_r-depth
54+
pt = CartesianPoint{T}(r, 0, z_draw)
5655
push!(hole_mobility_list, SolidStateDetectors.calculate_mobility(cdm, pt, Hole))
5756
push!(electron_mobility_list, SolidStateDetectors.calculate_mobility(cdm, pt, Electron))
5857
end
@@ -70,9 +69,9 @@ plot!(ylabel = "Mobility [cm\$^2\$/V/s]", xlabel = "Depth to surface [mm]",
7069
calculate_electric_potential!(sim, max_n_iterations = 10, grid = Grid(sim), verbose = false, depletion_handling = true)
7170
g = sim.electric_potential.grid
7271
ax1, ax2, ax3 = g.axes
73-
bulk_tick_dis=0.05*mm
74-
dl_tick_dis=0.01*mm
75-
user_additional_ticks_ax1=sort(vcat(ax1.interval.left:bulk_tick_dis:pn_r, pn_r:dl_tick_dis:ax1.interval.right))
72+
bulk_tick_dis = 0.05*mm
73+
dl_tick_dis = 0.01*mm
74+
user_additional_ticks_ax1 = sort(vcat(ax1.interval.left:bulk_tick_dis:pn_r, pn_r:dl_tick_dis:ax1.interval.right))
7675
user_ax1 = typeof(ax1)(ax1.interval, user_additional_ticks_ax1)
7776
user_g = typeof(g)((user_ax1, ax2, ax3))
7877
calculate_electric_potential!(sim, refinement_limits = 0.1, use_nthreads = 8, grid = user_g, depletion_handling = true)
@@ -81,7 +80,7 @@ calculate_weighting_potential!(sim, 1, use_nthreads = 8, depletion_handling = tr
8180
calculate_weighting_potential!(sim, 2, use_nthreads = 8, depletion_handling = true);
8281
plot(
8382
begin
84-
imp=plot(sim.imp_scale, φ = 0, xunit = u"mm", yunit = u"mm", title = "impurity scale")
83+
imp = plot(sim.imp_scale, φ = 0, xunit = u"mm", yunit = u"mm", title = "impurity scale")
8584
vline!([pn_r/mm], lw = 2, ls = :dash, color = :darkred, label = "PN junction boundary", legendfontsize = 6)
8685
end,
8786
begin
@@ -109,25 +108,25 @@ pulse_list = []
109108
totTime = 5 # us
110109
totEnergy = 1 # 1 keV --> simulating ~339 carrier pairs
111110
max_nsteps = Int(totTime * 1000)
112-
N=Int(totEnergy*1000÷2.95)
111+
N = Int(totEnergy*1000÷2.95)
113112
for depth in depth_list
114-
r=det_r-depth
113+
r = det_r-depth
115114
energy_depos = fill(T(2.95/1000), N) * u"keV"
116-
starting_positions = repeat([CylindricalPoint{T}(r, deg2rad(0), z_draw)], N)
115+
starting_positions = repeat([CartesianPoint{T}(r, deg2rad(0), z_draw)], N)
117116
evt = Event(starting_positions, energy_depos);
118117
simulate!(evt, sim, Δt = 1u"ns", max_nsteps = max_nsteps, diffusion = true, end_drift_when_no_field = false, self_repulsion = false)
119-
charge=ustrip(evt.waveforms[1].signal)
118+
charge = ustrip(evt.waveforms[1].signal)
120119
push!(pulse_list, charge)
121120
end
122-
pulse_plot=plot()
121+
pulse_plot = plot()
123122
eff_list = []
124123
for (i, depth) in enumerate(depth_list)
125-
depth=round(depth/mm, digits = 1)
124+
depth = round(depth/mm, digits = 1)
126125
plot!(pulse_list[i], label = "Depth: $(depth) mm", lw = 2, xlabel = "Time [ns]", ylabel = "Amplitude [e]",
127126
legend = :topright, grid = :on, minorgrid = :on, frame = :box)
128127
push!(eff_list, maximum(pulse_list[i])/N)
129128
end
130-
cce_plot=plot(depth_list/mm, eff_list, xlabel = "Depth to surface [mm]", lw = 2, ylabel = "Charge collection efficiency",
129+
cce_plot = plot(depth_list/mm, eff_list, xlabel = "Depth to surface [mm]", lw = 2, ylabel = "Charge collection efficiency",
131130
frame = :box, grid = :on, minorgrid = :on, xticks = 0:0.2:1.2, yticks = 0:0.1:1, dpi = 500, color = :black, label = "")
132131
plot(pulse_plot, cce_plot, layout = (1, 2), size = (1000, 400), margin = 5Plots.mm)
133132
#jl savefig("tutorial_pulse_cce_dl.pdf") # hide

docs/src/tutorials/geant4_ssd_lit.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ using Geant4
1212
# The extension features a function that creates a `Geant4.G4JLApplcation` object from a SSD `Simulation` object and a particle source.
1313

1414
using Plots
15-
using Unitful
15+
using ArraysOfArrays, Unitful
1616

1717
# Two types of particle source are pre-defined in `SolidStateDetectors`:
1818
#
@@ -89,7 +89,7 @@ events = run_geant4_simulation(app, N_events)
8989

9090
plot(sim.detector, show_passives = false, size = (500,500), fmt = :png)
9191
plot!(source_1)
92-
plot!(CartesianPoint.(broadcast(p -> ustrip.(u"m", p), events[1:1000].pos.data)), ms = 0.5, msw = 0, color=:black, label = "")
92+
plot!(ustrip.(u"m", flatview(events[1:1000].pos)), ms = 0.5, msw = 0, color=:black, label = "")
9393
#jl savefig("events.pdf") # hide
9494
#md savefig("events.pdf") # hide
9595
#md savefig("events.svg"); nothing # hide

ext/Geant4/io_gdml.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ using LightXML
2626
# Add <position> to <define> section, referenced in the geometry definition (in <solids>) via the name
2727
function create_position(e::AbstractConstructiveGeometry, x_define::XMLElement, name::String, v::Bool)
2828
# Calculate relative position of the volumes contained in the parent volume
29-
x, y, z = parse_origin(e.b) .- parse_origin(e.a)
29+
x, y, z = parse_origin(e.b) - parse_origin(e.a)
3030

3131
xpos = new_child(x_define, "position")
3232
set_attributes(xpos, OrderedDict(
@@ -515,9 +515,10 @@ function add_to_world(x_world::XMLElement, x_define::XMLElement, e::AbstractGeom
515515

516516
x_pos_ref = new_child(x_world, "positionref")
517517
set_attribute(x_pos_ref, "ref", "pos_" * name)
518-
518+
519519
x_pos_ref = new_child(x_define, "position")
520-
x, y, z = parse_origin(e)
520+
parsed_e = parse_origin(e)
521+
x, y, z = parsed_e.x, parsed_e.y, parsed_e.z
521522
set_attributes(x_pos_ref, OrderedDict(
522523
"name" => "pos_" * name,
523524
"x" => x,

ext/SolidStateDetectorsGeant4Ext.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,10 @@ function SolidStateDetectors.run_geant4_simulation(app::G4JLApplication, number_
219219
next!(p)
220220
evtno += 1
221221
end
222-
return RadiationDetectorSignals.group_by_evtno(Table(evts))
222+
223+
evts_with_points = map(evt -> merge(evt, (pos = cartesian_zero + evt.pos,)), evts)
224+
225+
return RadiationDetectorSignals.group_by_evtno(Table(evts_with_points))
223226
end
224227

225228

ext/SolidStateDetectorsLegendHDF5IOExt.jl

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import ..LegendHDF5IO
66

77
using ..SolidStateDetectors
88
using ..SolidStateDetectors: RealQuantity, SSDFloat, to_internal_units, chunked_ranges, LengthQuantity
9+
using ArraysOfArrays
10+
import Tables
911
using TypedTables, Unitful
1012
using Format
1113

@@ -24,7 +26,7 @@ end
2426

2527

2628

27-
function SolidStateDetectors.simulate_waveforms( mcevents::TypedTables.Table, sim::Simulation{T},
29+
function SolidStateDetectors.simulate_waveforms( mcevents::AbstractVector{<:NamedTuple}, sim::Simulation{T},
2830
output_dir::AbstractString,
2931
output_base_name::AbstractString = "generated_waveforms";
3032
chunk_n_physics_events::Int = 1000,
@@ -42,19 +44,22 @@ function SolidStateDetectors.simulate_waveforms( mcevents::TypedTables.Table, si
4244
Δtime = T(to_internal_units(Δt))
4345
n_contacts = length(sim.detector.contacts)
4446
@info "Detector has $(n_contacts) contact(s)"
45-
contacts = sim.detector.contacts
4647
if !ispath(output_dir) mkpath(output_dir) end
4748
nfmt(i::Int) = format(i, zeropadding = true, width = length(digits(n_total_physics_events)))
4849
evt_ranges = chunked_ranges(n_total_physics_events, chunk_n_physics_events)
49-
@info "-> $(sum(length.(mcevents.edep))) energy depositions to simulate."
50+
@info "-> $(length(mcevents)) events to simulate."
5051

5152
for evtrange in evt_ranges
5253
ofn = joinpath(output_dir, "$(output_base_name)_evts_$(nfmt(first(evtrange)))-$(nfmt(last(evtrange))).h5")
5354
@info "Now simulating $(evtrange) and storing it in\n\t \"$ofn\""
5455
mcevents_sub = simulate_waveforms(mcevents[evtrange], sim; Δt, max_nsteps, diffusion, self_repulsion, number_of_carriers, number_of_shells, max_interaction_distance, end_drift_when_no_field, geometry_check, verbose)
5556

57+
# LH5 can't handle CartesianPoint, turn positions into CartesianVectors which will be saved as SVectors
58+
pos_vec = VectorOfVectors([[CartesianPoint(p...) - cartesian_zero for p in ps] for ps in mcevents_sub.pos])
59+
new_mcevents_sub = TypedTables.Table(merge(Tables.columns(mcevents_sub), (pos = pos_vec,)))
60+
5661
LegendHDF5IO.lh5open(ofn, "w") do h5f
57-
LegendHDF5IO.writedata(h5f.data_store, "generated_waveforms", mcevents_sub)
62+
LegendHDF5IO.writedata(h5f.data_store, "generated_waveforms", new_mcevents_sub)
5863
end
5964
end
6065
end

0 commit comments

Comments
 (0)