Hey everyone, I’m translating some code from Julia to MATLAB and I have a seismic imaging program that now works in Julia and is a bit faster than MATLAB - but not a ton. The profiler says that the function pasted below takes up the bulk of the calculation - is there is an obvious Julia error I’m making? The three list comprehensions are the vast bulk of the time.
New to Julia so the answer may be simple. I edited this so that the code includes the constructors and some dummy constructors to make the code executable.
This code is a simple interpolation scheme for pasting values from the model (scattered points in x, y with a value v in three separate fields) onto ray paths defined by xy coodinates, ray.x and ray.y. Then the last line calculates the time of a seismic phase through a medium with the seismic velocity (u, which is 1/velocity) and two anisotropic parameters (A, the magnitude of anisotropy, t, fast direction).
I’ve tried some MATLAB tricks like reducing references to structures and substructures, or the Julia trick of rewriting the loop to use column-major matrices, but with little to no improvement.
For context, ray and model are immutable structures and I’m storing stuff in their fields that are defined as Float64 arrays with 1 dimension (hence the broadcasting when storing stuff in ray’s fields).
struct mod_sub
n::Array{Float64,1}
x::Array{Float64,1}
y::Array{Float64,1}
v::Array{Float64,1}
end
struct model_const
u::mod_sub
A::mod_sub
t::mod_sub
error::Array{Float64,1}
BIC::Array{Float64,1}
fit::Array{Float64,1}
nfit::Array{Float64,1}
llh::Array{Float64,1}
end
struct ray_const
L::Array{Float64,1}
u::Array{Float64,1}
A::Array{Float64,1}
theta::Array{Float64,1}
phi::Array{Float64,1}
t::Array{Float64,1}
x::Array{Float64,1}
y::Array{Float64,1}
sta::Float64
evt::Float64
pick::Array{Float64,1}
end
function raytracer!( )
r = 1:20
model = model_const( mod_sub(8*ones(1), 100*rand(Float64, 8), 100*rand(Float64, 8), rand(Float64, 8)),
mod_sub(8*ones(1), 100*rand(Float64, 8), 100*rand(Float64, 8), 0.1*rand(Float64, 8)),
mod_sub(8*ones(1), 100*rand(Float64, 8), 100*rand(Float64, 8), pi*rand(Float64, 8) .+ -pi),
0.01*ones(1), ones(1), ones(1), ones(1), ones(1))
ray = ray_const(ones(length(r) - 1), ones(length(r) - 1), ones(length(r) - 1), ones(length(r) - 1),
ones(length(r) - 1), ones(1), range(0, 100, length=20), range(0, 100, length=20), 1, 1, ones(1))
np = length(ray.x)
u = zeros(np)
A = zeros(np)
t = zeros(np)
for k = 1:np
ru = [ ((ray.x[k] - mx).^2) .+ ((ray.y[k] - my).^2) for mx in model.u.x, my in model.u.y]
rA = [ ((ray.x[k] - mx).^2) .+ ((ray.y[k] - my).^2) for mx in model.A.x, my in model.A.y]
rt = [ ((ray.x[k] - mx).^2) .+ ((ray.y[k] - my).^2) for mx in model.t.x, my in model.t.y]
u[k] = sum((model.u.v ./ ru))./sum(1 ./ ru)
A[k] = sum((model.A.v ./ rA))./sum(1 ./ rA)
t[k] = sum((model.t.v ./ rt))./sum(1 ./ rt)
end
dx = diff(ray.x);
dy = diff(ray.y);
ray.L .= sqrt.(dx.^2 .+ dy.^2)
ray.phi .= atan.(dy./dx)
ray.u .= 0.5*(2*u[1:(length(u)-1)] .+ diff(u));
ray.A .= 0.5*(2*A[1:(length(A)-1)] .+ diff(A));
ray.theta .= 0.5*(2*t[1:(length(t)-1)] .+ diff(t));
ray.t .= sum(ray.L.*(ray.u.*(1 .+ ray.A.*cos.(2*(ray.phi .- ray.theta)))))
return ray
end