Hi,
I’m wondering how and where I can add type annotations to make some code type-stable.
I’m working with a structure:
struct sensor{T}
location
normal
α
parameters
id
end
The fields and location
, normal
are always 3-element floats, T
, is a type parameter that specifies the type of sensor and is not float or similar.
I’m running into type-stability issues when I pass this a struct into a function for integration with hcubature. In particular, the variables {xyz}_c
and {xyz}_d
are found to be any.
Does anyone have a tip how to add type annotations to the sensor struct to make the integrand type-stable?
function cylinder_sensor_response(
s::sensor,
X_c,
r::T,
h::T,
I0::T;
reltol::T = 1e-6,
abstol::T = 1e-9
) where {T}
# Unpack arguments
x_c, y_c, z_c = X_c
x_d, y_d, z_d = s.location
# Define the integrand in cylindrical coords: (ρ, φ, z_local)
# domain: ρ ∈ [0,r], φ ∈ [0,2π], z_local ∈ [-h/2, +h/2]
integrand(ρφz::SVector{3, T2}) where {T2} = @inbounds begin
ρ = ρφz[1]
φ = ρφz[2]
z_local = ρφz[3]
# Convert from cylinder coords to cartesian
x_s = x_c + ρ*cos(φ)
y_s = y_c + ρ*sin(φ)
z_s = z_c + z_local
# Vector from detector to source point
dx = x_s - x_d
dy = y_s - y_d
dz = z_s - z_d
# Distance
dist2 = dx*dx + dy*dy + dz*dz
#
return I0 * collimation_factor(det, Point3(x_s, y_s, z_s)) / dist2 * ρ
end
# Bounds in cylindrical coordinates
lower_bounds = [0.0, 0.0, -h/2]
upper_bounds = [r, 2π, +h/2]
# Perform the triple integral
result, err = hcubature(
integrand,
lower_bounds,
upper_bounds;
rtol = reltol,
atol = abstol
)
return result
end
MethodInstance for integrand(::SVector{3, Float64})
from integrand(ρφz::SVector{3, T2}) where T2 @ Main ~/julia_envs/phantoms_base/test/test_gridfree.jl:43
Static Parameters
T2 = Float64
Arguments
#self#::Core.Const(Main.integrand)
ρφz::SVector{3, Float64}
Locals
val::Union{}
dist2::Any
dz::Any
dy::Any
dx::Any
z_s::Any
y_s::Any
x_s::Any
z_local::Float64
φ::Float64
ρ::Float64
Body::Any
1 ─ nothing
│ (ρ = Base.getindex(ρφz, 1))
│ (φ = Base.getindex(ρφz, 2))
│ (z_local = Base.getindex(ρφz, 3))
│ %5 = Main.:+::Core.Const(+)
│ %6 = Main.x_c::Any
│ %7 = Main.:*::Core.Const(*)
│ %8 = ρ::Float64
│ %9 = φ::Float64
│ %10 = Main.cos(%9)::Float64
│ %11 = (%7)(%8, %10)::Float64
│ (x_s = (%5)(%6, %11))
│ %13 = Main.:+::Core.Const(+)
│ %14 = Main.y_c::Any
│ %15 = Main.:*::Core.Const(*)
│ %16 = ρ::Float64
│ %17 = φ::Float64
│ %18 = Main.sin(%17)::Float64
│ %19 = (%15)(%16, %18)::Float64
│ (y_s = (%13)(%14, %19))
│ %21 = Main.:+::Core.Const(+)
│ %22 = z_local::Float64
│ (z_s = (%21)(Main.z_c, %22))
│ %24 = x_s::Any
│ (dx = %24 - Main.x_d)
│ %26 = y_s::Any
│ (dy = %26 - Main.y_d)
│ %28 = z_s::Any
│ (dz = %28 - Main.z_d)
│ %30 = Main.:+::Core.Const(+)
│ %31 = dx::Any
│ %32 = dx::Any
│ %33 = (%31 * %32)::Any
│ %34 = dy::Any
│ %35 = dy::Any
│ %36 = (%34 * %35)::Any
│ %37 = dz::Any
│ %38 = dz::Any
│ %39 = (%37 * %38)::Any
│ (dist2 = (%30)(%33, %36, %39))
│ %41 = Main.:*::Core.Const(*)
│ %42 = Main.:/::Core.Const(/)
│ %43 = Main.:*::Core.Const(*)
│ %44 = Main.I0::Any
│ %45 = Main.collimation_factor::Core.Const(phantoms_base.collimation_factor)
│ %46 = Main.d::Any
│ %47 = x_s::Any
│ %48 = y_s::Any
│ %49 = z_s::Any
│ %50 = Main.Point3(%47, %48, %49)::Point
│ %51 = (%45)(%46, %50)::Any
│ %52 = (%43)(%44, %51)::Any
│ %53 = dist2::Any
│ %54 = (%42)(%52, %53)::Any
│ %55 = ρ::Float64
│ %56 = (%41)(%54, %55)::Any
└── return %56
2 ─ Core.Const(:(val = nothing))
│ Core.Const(nothing)
│ Core.Const(:(val))
└── Core.Const(:(return %60))