@@ -421,12 +421,113 @@ plot(wp)
421421
422422## Part 1: Implementing the Henon-Heiles System (B)
423423
424+ ```julia
425+ function henon(dz,z,p,t)
426+ p₁, p₂, q₁, q₂ = z[1], z[2], z[3], z[4]
427+ dp₁ = -q₁*(1 + 2q₂)
428+ dp₂ = -q₂-(q₁^2 - q₂^2)
429+ dq₁ = p₁
430+ dq₂ = p₂
431+
432+ dz .= [dp₁, dp₂, dq₁, dq₂]
433+ return nothing
434+ end
435+
436+ u₀ = [0.1, 0.0, 0.0, 0.5]
437+ prob = ODEProblem(henon, u₀, (0., 1000.))
438+ sol = solve(prob, Vern9(), abstol=1e-14, reltol=1e-14)
439+
440+ plot(sol, vars=[(3,4,1)], tspan=(0,100))
441+ ```
442+
424443## (Optional) Part 2: Alternative Dynamical Implmentations of Henon-Heiles (B)
425444
445+ ```julia
446+ function henon(ddz,dz,z,p,t)
447+ p₁, p₂ = dz[1], dz[2]
448+ q₁, q₂ = z[1], z[2]
449+ ddq₁ = -q₁*(1 + 2q₂)
450+ ddq₂ = -q₂-(q₁^2 - q₂^2)
451+
452+ ddz .= [ddq₁, ddq₂]
453+ end
454+
455+ p₀ = u₀[1:2]
456+ q₀ = u₀[3:4]
457+ prob2 = SecondOrderODEProblem(henon, p₀, q₀, (0., 1000.))
458+ sol = solve(prob2, DPRKN6(), abstol=1e-10, reltol=1e-10)
459+
460+ plot(sol, vars=[(3,4)], tspan=(0,100))
461+
462+ H(p, q, params) = 1/2 * (p[1]^2 + p[2]^2) + 1/2 * (q[1]^2 + q[2]^2 + 2q[1]^2 * q[2] - 2/3*q[2]^3)
463+
464+ prob3 = HamiltonianProblem(H, p₀, q₀, (0., 1000.))
465+ sol = solve(prob3, DPRKN6(), abstol=1e-10, reltol=1e-10)
466+
467+ plot(sol, vars=[(3,4)], tspan=(0,100))
468+ ```
469+
426470## Part 3: Parallelized Ensemble Solving
427471
472+ In order to solve with an ensamble we need some initial conditions.
473+ ```julia
474+ function generate_ics(E,n)
475+ # The hardcoded values bellow can be estimated by looking at the
476+ # figures in the Henon-Heiles 1964 article
477+ qrange = range(-0.4, stop = 1.0, length = n)
478+ prange = range(-0.5, stop = 0.5, length = n)
479+ z0 = Vector{Vector{typeof(E)}}()
480+ for q in qrange
481+ V = H([0,0],[0,q],nothing)
482+ V ≥ E && continue
483+ for p in prange
484+ T = 1/2*p^2
485+ T + V ≥ E && continue
486+ z = [√(2(E-V-T)), p, 0, q]
487+ push!(z0, z)
488+ end
489+ end
490+ return z0
491+ end
492+
493+ z0 = generate_ics(0.125, 10)
494+
495+ function prob_func(prob,i,repeat)
496+ @. prob.u0 = z0[i]
497+ prob
498+ end
499+
500+ ensprob = EnsembleProblem(prob, prob_func=prob_func)
501+ sim = solve(ensprob, Vern9(), EnsembleThreads(), trajectories=length(z0))
502+
503+ plot(sim, vars=(3,4), tspan=(0,10))
504+ ```
505+
428506## Part 4: Parallelized GPU Ensemble Solving
429507
508+ In order to use GPU parallelization we must make all inputs
509+ (initial conditions, tspan, etc.) `Float32` and the function
510+ definition should be in the in-place form, avoid bound checking and
511+ return `nothing`.
512+
513+ ```julia
514+ using DiffEqGPU
515+
516+ function henon_gpu(dz,z,p,t)
517+ @inbounds begin
518+ dz[1] = -z[3]*(1 + 2z[4])
519+ dz[2] = -z[4]-(z[3]^2 - z[4]^2)
520+ dz[3] = z[1]
521+ dz[4] = z[2]
522+ end
523+ return nothing
524+ end
525+
526+ z0 = generate_ics(0.125f0, 50)
527+ prob_gpu = ODEProblem(henon_gpu, Float32.(u₀), (0.f0, 1000.f0))
528+ ensprob = EnsembleProblem(prob_gpu, prob_func=prob_func)
529+ sim = solve(ensprob, Tsit5(), EnsembleGPUArray(), trajectories=length(z0))
530+ ```
430531# Problem 6: Training Neural Stochastic Differential Equations with GPU acceleration (I)
431532
432533## Part 1: Constructing and Training a Basic Neural ODE
0 commit comments