Skip to content

Commit de16c17

Browse files
committed
Direct passing of seqd to GPU kernels, new abstract type for discrete sequences, moved spatial gradient calculation to own function.
1 parent fcf1a37 commit de16c17

12 files changed

Lines changed: 55 additions & 43 deletions

File tree

KomaMRIBase/src/KomaMRIBase.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export γ # gyro-magnetic ratio [Hz/T]
4141
export Scanner, Sequence, Phantom
4242
export Grad, RF, ADC, Delay
4343
export dur, get_block_start_times, get_samples
44-
export DiscreteSequence
44+
export DiscreteSequence, AbstractDiscreteSequence
4545
export discretize, get_adc_phase_compensation, get_adc_sampling_times
4646
export is_Gx_on, is_Gy_on, is_Gz_on, is_RF_on, is_ADC_on
4747
export times, ampls, freqs

KomaMRIBase/src/datatypes/simulation/DiscreteSequence.jl

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
abstract type AbstractDiscreteSequence end
2+
13
"""
24
seqd = DiscreteSequence(Gx, Gy, Gz, B1, Δf, ADC, t, Δt)
35
@@ -17,15 +19,18 @@ times. DiscreteSequence is the struct used for simulation.
1719
# Returns
1820
- `seqd`: (`::DiscreteSequence`) DiscreteSequence struct
1921
"""
20-
struct DiscreteSequence{T<:Real}
21-
Gx::AbstractVector{T}
22-
Gy::AbstractVector{T}
23-
Gz::AbstractVector{T}
24-
B1::AbstractVector{Complex{T}}
25-
Δf::AbstractVector{T}
26-
ADC::AbstractVector{Bool}
27-
t::AbstractVector{T}
28-
Δt::AbstractVector{T}
22+
struct DiscreteSequence{T<:Real,
23+
AT<:AbstractVector{T},
24+
ACT<:AbstractVector{Complex{T}},
25+
AB<:AbstractVector{Bool}} <: AbstractDiscreteSequence
26+
Gx::AT
27+
Gy::AT
28+
Gz::AT
29+
B1::ACT
30+
Δf::AT
31+
ADC::AB
32+
t::AT
33+
Δt::AT
2934
end
3035

3136
Base.length(seq::DiscreteSequence) = length(seq.Δt)

KomaMRICore/src/KomaMRICore.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ include("rawdata/ISMRMRD.jl")
1818
include("datatypes/Spinor.jl")
1919
include("other/DiffusionModel.jl")
2020
# Simulator
21+
include("simulation/SpatialEncoding.jl")
2122
include("simulation/GPUFunctions.jl")
2223
include("simulation/Functors.jl")
2324
include("simulation/SimulatorCore.jl")

KomaMRICore/src/simulation/Functors.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Adapt: adapt, adapt_storage
1+
import Adapt: adapt, adapt_storage, @adapt_structure
22
import Functors: @functor, functor, fmap, isleaf
33

44
#Aux. funcitons to check if the variable we want to move to the GPU is numeric
@@ -115,5 +115,6 @@ adapt_storage(T::Type{<:Real}, xs::MotionList) = MotionList(paramtype.(T, xs.mot
115115
@functor Spinor
116116
# DiscreteSequence
117117
@functor DiscreteSequence
118+
@adapt_structure DiscreteSequence
118119

119120
export gpu, cpu, f32, f64

KomaMRICore/src/simulation/SimMethods/Bloch/cpu/BlochCPU.jl

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ function run_spin_precession!(
6666
Mxy = prealloc.M.xy
6767
ΔBz = prealloc.ΔBz
6868
fill!(ϕ, zero(T))
69-
@. Bz_old = x[:,1] * seq.Gx[1] + y[:,1] * seq.Gy[1] + z[:,1] * seq.Gz[1] + ΔBz
70-
69+
Bz_old = get_Bz(seq, x, y, z, 1) + ΔBz
70+
7171
# Fill sig[1] if needed
7272
ADC_idx = 1
7373
if (seq.ADC[1])
@@ -81,7 +81,7 @@ function run_spin_precession!(
8181
t_seq += seq.Δt[seq_idx-1]
8282

8383
#Effective Field
84-
@. Bz_new = x * seq.Gx[seq_idx] + y * seq.Gy[seq_idx] + z * seq.Gz[seq_idx] + ΔBz
84+
Bz_new = get_Bz(seq, x, y, z, seq_idx) + ΔBz
8585

8686
#Rotation
8787
@. ϕ += (Bz_old + Bz_new) * T(-π * γ) * seq.Δt[seq_idx-1]
@@ -136,24 +136,24 @@ function run_spin_excitation!(
136136
Maux_z = prealloc.M.z
137137

138138
#Simulation
139-
for s in seq #This iterates over seq, "s = seq[i,:]"
139+
for i in eachindex(seq.Δt)
140140
#Motion
141-
x, y, z = get_spin_coords(p.motion, p.x, p.y, p.z, s.t)
141+
x, y, z = get_spin_coords(p.motion, p.x, p.y, p.z, seq.t[i])
142142
#Effective field
143-
@. Bz = (s.Gx * x + s.Gy * y + s.Gz * z) + ΔBz - s.Δf / T(γ) # ΔB_0 = (B_0 - ω_rf/γ), Need to add a component here to model scanner's dB0(x,y,z)
144-
@. B = sqrt(abs(s.B1)^2 + abs(Bz)^2)
143+
Bz .= get_Bz(seq, x, y, z, i) .+ ΔBz .- seq.Δf[i] / T(γ) # ΔB_0 = (B_0 - ω_rf/γ), Need to add a component here to model scanner's dB0(x,y,z)
144+
@. B = sqrt(abs(seq.B1[i])^2 + abs(Bz)^2)
145145
@. B[B == 0] = eps(T)
146146
#Spinor Rotation
147-
@. φ = T(-π * γ) * (B * s.Δt) # TODO: Use trapezoidal integration here (?), this is just Forward Euler
147+
@. φ = T(-π * γ) * (B * seq.Δt[i]) # TODO: Use trapezoidal integration here (?), this is just Forward Euler
148148
@. α = cos(φ) - Complex{T}(im) * (Bz / B) * sin(φ)
149-
@. β = -Complex{T}(im) * (s.B1 / B) * sin(φ)
149+
@. β = -Complex{T}(im) * (seq.B1[i] / B) * sin(φ)
150150
mul!(Spinor(α, β), M, Maux_xy, Maux_z)
151151
#Relaxation
152-
@. M.xy = M.xy * exp(-s.Δt / p.T2)
153-
@. M.z = M.z * exp(-s.Δt / p.T1) + p.ρ * (T(1) - exp(-s.Δt / p.T1))
152+
@. M.xy = M.xy * exp(-seq.Δt[i] / p.T2)
153+
@. M.z = M.z * exp(-seq.Δt[i] / p.T1) + p.ρ * (T(1) - exp(-seq.Δt[i] / p.T1))
154154

155155
#Reset Spin-State (Magnetization). Only for FlowPath
156-
outflow_spin_reset!(M, s.t, p.motion; replace_by=p.ρ)
156+
outflow_spin_reset!(M, seq.t[i + 1, :], p.motion; replace_by=p.ρ)
157157
end
158158
#Acquired signal
159159
#sig .= -1.4im #<-- This was to test if an ADC point was inside an RF block

KomaMRICore/src/simulation/SimMethods/Bloch/gpu/BlochGPU.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ end
2020

2121
function run_spin_precession!(
2222
p::Phantom{T},
23-
seq::DiscreteSequence{T},
23+
seq::AbstractDiscreteSequence,
2424
sig::AbstractArray{Complex{T}},
2525
M::Mag{T},
2626
sim_method::Bloch,
@@ -36,7 +36,7 @@ function run_spin_precession!(
3636
pre.sig_output,
3737
M.xy, M.z,
3838
x, y, z, pre.ΔBz, p.T1, p.T2, p.ρ, UInt32(length(M.xy)),
39-
seq.Gx, seq.Gy, seq.Gz, seq.Δt, seq.ADC, UInt32(length(seq.Δt)+1),
39+
seq, UInt32(length(seq.Δt)+1),
4040
Val(!(p.motion isa NoMotion)), Val(supports_warp_reduction(backend)),
4141
ndrange=(cld(length(M.xy), groupsize) * groupsize)
4242
)
@@ -53,7 +53,7 @@ end
5353

5454
function run_spin_excitation!(
5555
p::Phantom{T},
56-
seq::DiscreteSequence{T},
56+
seq::AbstractDiscreteSequence,
5757
sig::AbstractArray{Complex{T}},
5858
M::Mag{T},
5959
sim_method::Bloch,
@@ -68,7 +68,7 @@ function run_spin_excitation!(
6868
excitation_kernel!(backend, groupsize)(
6969
M.xy, M.z,
7070
x, y, z, pre.ΔBz, p.T1, p.T2, p.ρ, UInt32(length(M.xy)),
71-
seq.Gx, seq.Gy, seq.Gz, seq.Δt, seq.Δf, seq.B1, UInt32(length(seq.Δt)),
71+
seq, UInt32(length(seq.Δt)),
7272
Val(!(p.motion isa NoMotion)),
7373
ndrange=(cld(length(M.xy), groupsize) * groupsize)
7474
)

KomaMRICore/src/simulation/SimMethods/Bloch/gpu/ExcitationKernel.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
@kernel unsafe_indices=true inbounds=true function excitation_kernel!(
44
M_xy::AbstractVector{Complex{T}}, M_z,
55
@Const(p_x), @Const(p_y), @Const(p_z), @Const(p_ΔBz), @Const(p_T1), @Const(p_T2), @Const(p_ρ), N_Spins,
6-
@Const(s_Gx), @Const(s_Gy), @Const(s_Gz), @Const(s_Δt), @Const(s_Δf), @Const(s_B1), N_Δt,
6+
seq::AbstractDiscreteSequence, N_Δt,
77
::Val{MOTION}
88
) where {T, MOTION}
99

@@ -27,10 +27,10 @@
2727
x, y, z = get_spin_coordinates(p_x, p_y, p_z, i, s_idx)
2828
end
2929

30-
Bz = (x * s_Gx[s_idx] + y * s_Gy[s_idx] + z * s_Gz[s_idx]) + ΔBz - s_Δf[s_idx] / T(γ)
31-
B1_r, B1_i = reim(s_B1[s_idx])
30+
Bz = get_Bz(seq, x, y, z, s_idx) + ΔBz - seq.Δf[s_idx] / T(γ)
31+
B1_r, B1_i = reim(seq.B1[s_idx])
3232
B = sqrt(B1_r^2 + B1_i^2 + Bz^2)
33-
Δt = s_Δt[s_idx]
33+
Δt = seq.Δt[s_idx]
3434
φ = T(-π * γ) * B * Δt
3535
sin_φ, cos_φ = sincos(φ)
3636
α_r = cos_φ

KomaMRICore/src/simulation/SimMethods/Bloch/gpu/PrecessionKernel.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
sig_output::AbstractMatrix{Complex{T}},
55
M_xy, M_z,
66
@Const(p_x), @Const(p_y), @Const(p_z), @Const(p_ΔBz), @Const(p_T1), @Const(p_T2), @Const(p_ρ), N_spins,
7-
@Const(s_Gx), @Const(s_Gy), @Const(s_Gz), @Const(s_Δt), @Const(s_ADC), s_length,
7+
seq::AbstractDiscreteSequence, s_length,
88
::Val{MOTION}, ::Val{USE_WARP_REDUCTION},
99
) where {T, MOTION, USE_WARP_REDUCTION}
1010

@@ -37,11 +37,11 @@
3737
ΔBz = p_ΔBz[i]
3838
T2 = p_T2[i]
3939
x, y, z = get_spin_coordinates(p_x, p_y, p_z, i, 1)
40-
Bz_prev = x * s_Gx[1] + y * s_Gy[1] + z * s_Gz[1] + ΔBz
40+
Bz_prev = get_Bz(seq, x, y, z, 1) + ΔBz
4141
end
4242

4343
ADC_idx = 1u32
44-
if s_ADC[1]
44+
if seq.ADC[1]
4545
sig_r, sig_i = reduce_signal!(sig_r, sig_i, sig_group_r, sig_group_i, i_l, N, T, Val(USE_WARP_REDUCTION))
4646
if i_l == 1u32
4747
sig_output[i_g, 1] = complex(sig_r, sig_i)
@@ -56,13 +56,13 @@
5656
x, y, z = get_spin_coordinates(p_x, p_y, p_z, i, s_idx)
5757
end
5858

59-
Δt = s_Δt[s_idx-1]
59+
Δt = seq.Δt[s_idx-1]
6060
t += Δt
61-
Bz_next = x * s_Gx[s_idx] + y * s_Gy[s_idx] + z * s_Gz[s_idx] + ΔBz
61+
Bz_next = get_Bz(seq, x, y, z, s_idx) + ΔBz
6262
ϕ += (Bz_prev + Bz_next) * T(-π * γ) * Δt
6363
end
6464

65-
if s_idx < s_length && s_ADC[s_idx]
65+
if s_idx < s_length && seq.ADC[s_idx]
6666
if i <= N_spins
6767
ΔT2 = exp(-t / T2)
6868
cis_ϕ_i, cis_ϕ_r = sincos(ϕ)

KomaMRICore/src/simulation/SimMethods/BlochDict/BlochDict.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ precession.
3131
"""
3232
function run_spin_precession!(
3333
p::Phantom{T},
34-
seq::DiscreteSequence{T},
34+
seq::AbstractDiscreteSequence,
3535
sig::AbstractArray{Complex{T}},
3636
M::Mag{T},
3737
sim_method::BlochDict,

KomaMRICore/src/simulation/SimMethods/BlochSimple/BlochSimple.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ precession.
2323
"""
2424
function run_spin_precession!(
2525
p::Phantom{T},
26-
seq::DiscreteSequence{T},
26+
seq::AbstractDiscreteSequence,
2727
sig::AbstractArray{Complex{T}},
2828
M::Mag{T},
2929
sim_method::SimulationMethod,
@@ -73,7 +73,7 @@ It gives rise to a rotation of `M0` with an angle given by the efective magnetic
7373
"""
7474
function run_spin_excitation!(
7575
p::Phantom{T},
76-
seq::DiscreteSequence{T},
76+
seq::AbstractDiscreteSequence,
7777
sig::AbstractArray{Complex{T}},
7878
M::Mag{T},
7979
sim_method::SimulationMethod,

0 commit comments

Comments
 (0)