Skip to content

Commit 51dcfc1

Browse files
type stable function calling
From the timings I'm not sure if it's worth it, but it does fix the dynamic dispatching. ```julia using LinearAlgebra using NBodySimulator using Plots using StaticArrays J_per_eV = 1.602176634e-19 kg_per_amu = 1.66054e-27 kb = 1.380649e-23 # J/K N = 864 m = 6.6335209e-26 # kg box_size = 3.47786e-9 # m σ = 0.34e-9 # m cutoff = 0.765e-9 # m ϵ = 1.657e-21 # J reference_temp = 94.4 # K mean_v = √(kb * reference_temp / m) # m/s thermostat_prob = 0.1 eq_steps = 2000 prod_steps = 5000 Δt = 1e-14 # s stride = 10 function get_final_bodies(sr::NBodySimulator.SimulationResult) positions = get_position(sr, sr.solution.t[end]) velocities = get_velocity(sr, sr.solution.t[end]) masses = get_masses(sr.simulation.system) N = length(masses) bodies = MassBody[] for i ∈ 1:N push!(bodies, MassBody(SVector{3}(positions[:, i]), SVector{3}(velocities[:, i]), masses[i])) end return bodies end initial_bodies = generate_bodies_in_cell_nodes(N, m, mean_v, box_size) potentials = Dict(:lennard_jones => LennardJonesParameters(ϵ, σ, cutoff)) eq_system = PotentialNBodySystem(initial_bodies, potentials) boundary_conditions = CubicPeriodicBoundaryConditions(box_size) eq_thermostat = AndersenThermostat(reference_temp, thermostat_prob / Δt) eq_simulation = NBodySimulation( eq_system, (0.0, eq_steps * Δt), boundary_conditions, eq_thermostat, kb ) simulator = VelocityVerlet() eq_result = run_simulation(eq_simulation, simulator, dt=Δt) eq_bodies = get_final_bodies(eq_result) prod_system = PotentialNBodySystem(eq_bodies, potentials) prod_simulation = NBodySimulation( prod_system, (eq_steps * Δt, (eq_steps + prod_steps) * Δt), boundary_conditions, kb ) @time prod_result = run_simulation(prod_simulation, simulator, dt=Δt); prod_bodies = get_final_bodies(prod_result) eq_time_range = [t * 1e12 for (i,t) ∈ enumerate(eq_result.solution.t) if (i - 1) % stride == 0] prod_time_range = [t * 1e12 for (i,t) ∈ enumerate(prod_result.solution.t) if (i - 1) % stride == 0] total_time_range = vcat(eq_time_range, prod_time_range) plot( title="Temperature during Simulation", xlab="Time [ps]", ylab="Temperature [K]", ) plot!( eq_time_range, t -> temperature(eq_result, t * 1e-12), label="Equilibrium Stage Temperature", color=1 ) plot!( prod_time_range, t -> temperature(prod_result, t * 1e-12), label="Production Stage Temperature", color=3 ) plot!( total_time_range, t -> reference_temp, label="Reference Temperature", color=2, linestyle=:dash ) vline!( [eq_time_range[end]], label=false, color=:black, linestyle=:dash ) plot( title="Energy during Simulation", xlab="Time [ps]", ylab="Energy [eV]", legend=:right ) plot!( eq_time_range, t -> kinetic_energy(eq_result, t * 1e-12) / J_per_eV, label="Kinetic Energy", color=2 ) plot!( eq_time_range, t -> potential_energy(eq_result, t * 1e-12) / J_per_eV, label="Potential Energy", color=1 ) plot!( eq_time_range, t -> total_energy(eq_result, t * 1e-12) / J_per_eV, label="Total Energy", color=3 ) plot!( prod_time_range, t -> kinetic_energy(prod_result, t * 1e-12) / J_per_eV, label=false, color=2 ) plot!( prod_time_range, t -> potential_energy(prod_result, t * 1e-12) / J_per_eV, label=false, color=1 ) plot!( prod_time_range, t -> total_energy(prod_result, t * 1e-12) / J_per_eV, label=false, color=3 ) vline!( [eq_time_range[end]], label=false, color=:black, linestyle=:dash ) using Profile @Profile prod_result = run_simulation(prod_simulation, simulator, dt=Δt); Juno.profiler() Profile.clear() ```
1 parent 5c9d950 commit 51dcfc1

File tree

1 file changed

+31
-26
lines changed

1 file changed

+31
-26
lines changed

src/nbody_to_ode.jl

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -296,15 +296,17 @@ function DiffEqBase.ODEProblem(simulation::NBodySimulation{<:PotentialNBodySyste
296296

297297
acceleration_functions = gather_accelerations_for_potentials(simulation)
298298

299-
function ode_system!(du, u, p, t)
300-
du[:, 1:n] = @view u[:, n + 1:2n];
301-
302-
@inbounds for i = 1:n
303-
a = MVector(0.0, 0.0, 0.0)
304-
for acceleration! in acceleration_functions
305-
acceleration!(a, u[:, 1:n], u[:, n + 1:end], t, i);
299+
ode_system! = let acceleration_functions = tuple(acceleration_functions...)
300+
function ode_system!(du, u, p, t)
301+
du[:, 1:n] = @view u[:, n + 1:2n];
302+
303+
@inbounds for i = 1:n
304+
a = MVector(0.0, 0.0, 0.0)
305+
for acceleration! in acceleration_functions
306+
acceleration!(a, u[:, 1:n], u[:, n + 1:end], t, i);
307+
end
308+
du[:, n + i] .= a
306309
end
307-
du[:, n + i] .= a
308310
end
309311
end
310312

@@ -318,19 +320,20 @@ function DiffEqBase.SecondOrderODEProblem(simulation::NBodySimulation{<:Potentia
318320
acceleration_functions = gather_accelerations_for_potentials(simulation)
319321
simultaneous_acceleration = gather_simultaneous_acceleration(simulation)
320322

321-
function soode_system!(dv, v, u, p, t)
322-
@inbounds for i = 1:n
323-
a = MVector(0.0, 0.0, 0.0)
324-
for acceleration! in acceleration_functions
325-
acceleration!(a, u, v, t, i);
323+
soode_system! = let acceleration_functions = tuple(acceleration_functions...), simultaneous_acceleration = tuple(simultaneous_acceleration...)
324+
function soode_system!(dv, v, u, p, t)
325+
@inbounds for i = 1:n
326+
a = MVector(0.0, 0.0, 0.0)
327+
for acceleration! in acceleration_functions
328+
acceleration!(a, u, v, t, i);
329+
end
330+
dv[:, i] .= a
331+
end
332+
for acceleration! in simultaneous_acceleration
333+
acceleration!(dv, u, v, t);
326334
end
327-
dv[:, i] .= a
328-
end
329-
for acceleration! in simultaneous_acceleration
330-
acceleration!(dv, u, v, t);
331335
end
332336
end
333-
334337
SecondOrderODEProblem(soode_system!, v0, u0, simulation.tspan)
335338
end
336339

@@ -391,17 +394,19 @@ function DiffEqBase.SDEProblem(simulation::NBodySimulation{<:PotentialNBodySyste
391394

392395
therm = simulation.thermostat
393396

394-
function deterministic_acceleration!(du, u, p, t)
395-
du[:, 1:n] = @view u[:, n + 1:2n];
397+
deterministic_acceleration! = let acceleration_functions = tuple(acceleration_functions...)
398+
function deterministic_acceleration!(du, u, p, t)
399+
du[:, 1:n] = @view u[:, n + 1:2n];
396400

397-
@inbounds for i = 1:n
398-
a = MVector(0.0, 0.0, 0.0)
399-
for acceleration! in acceleration_functions
400-
acceleration!(a, (@view u[:, 1:n]), (@view u[:, n + 1:end]), t, i);
401+
@inbounds for i = 1:n
402+
a = MVector(0.0, 0.0, 0.0)
403+
for acceleration! in acceleration_functions
404+
acceleration!(a, (@view u[:, 1:n]), (@view u[:, n + 1:end]), t, i);
405+
end
406+
du[:, n + i] .= a
401407
end
402-
du[:, n + i] .= a
408+
@. du[:, n + 1:end] -= therm.γ*u[:, n + 1:end]
403409
end
404-
@. du[:, n + 1:end] -= therm.γ*u[:, n + 1:end]
405410
end
406411

407412
σ = sqrt(2*therm.γ*simulation.kb*therm.T/simulation.system.bodies[1].m)

0 commit comments

Comments
 (0)