@@ -35,184 +35,104 @@ end
3535
3636# plot 3 - differential equation
3737
38- # using DifferentialEquations
39-
40- # # struct to hold problem constants
41- # struct SoccerConst
42- # m::Float64 # mass of the ball
43- # g::Float64 # acceleration due to gravity
44- # r::Float64 # radius of the ball
45- # ρ::Float64 # density of the air
46- # C_L::Float64 # lift coefficient
47- # C_D::Float64 # drag coefficient
48- # end
49-
50- # # inital conditions
51- # struct SoccerIC
52- # x::Float64 # initial x position
53- # y::Float64 # initial y position
54- # z::Float64 # initial z position
55- # v_x::Float64 # initial x velocity
56- # v_y::Float64 # initial y velocity
57- # v_z::Float64 # initial z velocity
58- # end
59-
60- # open("_posts/examples/diffeqviz/contour.html", "w") do io
61- # app = App() do
62- # markersize = Bonito.Slider(range(10, stop=100, length=100))
63-
64- # # Create a scatter plot
65- # fig, ax = meshscatter(rand(3, 100), markersize=markersize)
66-
67- # # Return the plot and the slider
68- # return Bonito.record_states(session, DOM.div(fig, markersize))
69- # end;
70-
71- # as_html(io, session, app)
72- # end
73-
74- # # plot 2 - volume plot
75- # open("_posts/examples/diffeqviz/sinc_surface.html", "w") do io
76- # # create sub session
77- # sub = Session(session)
78-
79- # app = App(volume(rand(10, 10, 10)))
80- # as_html(io, sub, app)
81- # end
82-
83- # open("_posts/examples/diffeqviz/diffeq.html", "w") do io
84- # # Create a Bonito session
85- # sub = Session(session)
86-
87- # # Define the Lorenz system
88- # function lorenz!(du, u, p, t)
89- # x, y, z = u
90- # σ, ρ, β = p
91- # du[1] = σ * (y - x)
92- # du[2] = x * (ρ - z) - y
93- # du[3] = x * y - β * z
94- # end
95-
96- # # Time span and initial condition
97- # tspan = (0.0, 40.0)
98- # u0 = [1.0, 0.0, 0.0]
99-
100- # # Default parameters (classic Lorenz with adjustable β)
101- # σ₀ = 10.0
102- # ρ₀ = 28.0
103- # β₀ = 2.666
104- # p₀ = (σ₀, ρ₀, β₀)
105-
106- # # Create the initial ODE solution
107- # prob = ODEProblem(lorenz!, u0, tspan, p₀)
108- # sol = solve(prob, Tsit5(), reltol=1e-8, abstol=1e-8, saveat=0.05)
109-
110- # # Create a Makie figure with two rows:
111- # # Row 1: 3D scene (LScene) with the Lorenz attractor.
112- # # Row 2: A slider grid controlling the parameters.
113- # fig = Figure(size = (900, 600))
114-
115- # # --- Row 1: 3D Plot ---
116- # ax = LScene(fig[1, 1], show_axis=true)
117- # lineplot = lines!(ax,
118- # sol[1, :], sol[2, :], sol[3, :],
119- # linewidth = 2
120- # )
121-
122- # # --- Row 2: Slider Grid ---
123- # sgrid = SliderGrid(fig[2, 1],
124- # (label = "σ", range = LinRange(0, 20, 100)),
125- # (label = "ρ", range = LinRange(0, 50, 100)),
126- # (label = "β", range = LinRange(0, 10, 100))
127- # )
128- # σ_slider, ρ_slider, β_slider = sgrid.sliders
129-
130- # # Set the slider default values.
131- # σ_slider.value[] = σ₀
132- # ρ_slider.value[] = ρ₀
133- # β_slider.value[] = β₀
134-
135- # # Function to re-solve the ODE and update the plot.
136- # function update_plot!()
137- # # Get the current parameter values from the sliders
138- # σ = σ_slider.value[]
139- # ρ = ρ_slider.value[]
140- # β = β_slider.value[]
141- # new_p = (σ, ρ, β)
142- # new_prob = remake(prob, p = new_p)
143- # new_sol = solve(new_prob, Tsit5(), reltol=1e-8, abstol=1e-8, saveat=0.1)
144- # # Update the line plot with the new solution
145- # lineplot[1][] = Point3f0.(new_sol[1, :], new_sol[2, :], new_sol[3, :])
146- # end
147-
148- # # Connect each slider’s observable to update_plot!
149- # for slider in (σ_slider, ρ_slider, β_slider)
150- # on(slider.value) do _
151- # update_plot!()
152- # end
153- # end
154-
155- # # --- Bonito App ---
156- # # Wrap the entire Makie figure (which includes the slider grid)
157- # # in a recorded DOM container so that slider changes propagate.
158- # app = App() do
159- # # By calling `Bonito.record_states` on the container,
160- # # all reactive states (including slider values) are captured.
161- # Bonito.record_states(sub, DOM.div(fig))
162- # end
163-
164- # # Write the Bonito app to an HTML file.
165- # as_html(io, sub, app)
166- # end
167-
168-
169-
170- # # plot 3 - differential equation
171- # open("_posts/examples/diffeqviz/diffeq.html", "w") do io
172-
173- # # function lorenz(du, u, p, t)
174- # # x, y, z = u
175- # # sigma, rho, beta = p
176- # # du[1] = sigma * (y - x)
177- # # du[2] = x * (rho - z) - y
178- # # du[3] = x * y - beta * z
179- # # end
180-
181- # # t_begin = 0.0
182- # # t_end = 10.0
183- # # tspan = (t_begin, t_end)
184- # # u_begin = [1.0, 0.0, 0.0]
185-
186- # app = App() do session
187-
188- # # create a slider
189- # a = Bonito.Slider(range(1, stop=3, length=3))
190-
191- # # setup the ODE problem
192- # # sol = lift(a) do a_val
193- # # p = [10.0, 28.0, a_val]
194- # # prob = ODEProblem(lorenz, u_begin, tspan, p)
195- # # solve(prob, Tsit5(), reltol = 1e-8, abstol = 1e-8)
196- # # end
197-
198- # # Create a 3D makie plot with the solution
199- # # fig = Figure(size=(800, 400))
200- # # ax = Axis3(fig[1, 1])
201- # # x = Vector{Float64}(sol[][:][1, :])
202- # # y = Vector{Float64}(sol[][:][2, :])
203- # # z = Vector{Float64}(sol[][:][3, :])
204-
205- # # fig, ax = meshscatter(
206- # # x,
207- # # y,
208- # # z,
209- # # markersize=1
210- # # )
211-
212- # # Create a scatter plot
213- # fig, ax = meshscatter(rand(3, 100), markersize=markersize)
214-
215- # # Return the plot and the slider
216- # return Bonito.record_states(session, DOM.div(fig, a))
217- # end
218- # end
38+ struct C
39+ m:: Float64 # mass of the ball
40+ g:: Float64 # acceleration due to gravity
41+ ρ:: Float64 # density of the air
42+ A:: Float64 # cross-sectional area of the ball
43+ C_D:: Float64 # drag coefficient
44+ r:: Float64 # radius of the ball
45+ ω₀:: Float64 # initial angular velocity
46+ end
47+
48+ struct IC
49+ x:: Float64 # initial x position
50+ y:: Float64 # initial y position
51+ z:: Float64 # initial z position
52+ v_x:: Float64 # initial x velocity
53+ v_y:: Float64 # initial y velocity
54+ v_z:: Float64 # initial z velocity
55+ end
56+
57+
58+ using DifferentialEquations
59+
60+ C₁ = C (0.43 , 9.81 , 1.225 , 0.013 , 0.2 , 0.11 , 88 )
61+ IC₁ = IC (0 , 0 , 0 , 20 , 0 , 0 )
62+
63+ # Define the ODE function. The state vector u = [x, y, z, vx, vy, vz]
64+ function projectile! (ddu, du, u, p, t)
65+ # Unpack state variables
66+ x, y, z = u
67+ vx, vy, vz = du
68+
69+ # Unpack parameters
70+ m, g, ρ, A, C_D, r, ω₀ = p
71+
72+ # Define constant H = (ρ * A) / (2 * m)
73+ H = (ρ * A) / (2 * m)
74+
75+ # Compute speed (magnitude of velocity)
76+ v = sqrt (vx^ 2 + vy^ 2 + vz^ 2 )
77+
78+ # Compute the decaying angular velocity ω(t)
79+ ω = ω₀ * exp (- t/ 7 )
80+
81+ # Compute lift coefficient, avoiding division by zero.
82+ C_L = (v == 0.0 ? 0.0 : (ω * r / v))
83+
84+ # Compute acceleration components
85+ ddu[1 ] = - v * H * (C_D * vx + C_L * vy)
86+ ddu[2 ] = - v * H * (C_D * vy - C_L * vx)
87+ ddu[3 ] = - v * H * (C_D * vz - g)
88+ end
89+
90+ # Problem constants:
91+ # m: mass (kg), g: gravity (m/s²), rho: air density (kg/m³),
92+ # A: cross-sectional area (m²), C_D: drag coefficient,
93+ # r: ball radius (m), omega0: initial angular velocity (rad/s)
94+ p = [C₁. m, C₁. g, C₁. ρ, C₁. A, C₁. C_D, C₁. r, C₁. ω₀]
95+
96+ # Initial conditions.
97+ # Here we assume the ball is kicked from the origin with an initial velocity.
98+ # For example: initial position (0, 0, 0) and initial velocity (30, 0, 30) m/s.
99+ dx₀ = [IC₁. v_x, IC₁. v_y, IC₁. v_z]
100+ x₀ = [IC₁. x, IC₁. y, IC₁. z]
101+
102+ # Time span for the simulation
103+ tspan = (0.0 , 50.0 )
104+
105+ # Define the ODE problem
106+ prob = SecondOrderODEProblem (projectile!, dx₀, x₀, tspan, p)
107+ sol = solve (prob, Tsit5 ())
108+
109+ # load image
110+ pitch = Makie. FileIO. load (expanduser (" _posts/guides/interactive-blog/soccer_pitch.png" ))
111+
112+ # soccer pitch size
113+ x_size = (0 , 68 )
114+ y_size = (0 , 105 )
115+ z_size = (0 , 20 )
116+
117+ # make a plot for the initial conditions and a field
118+ open (output_folder * " ode_ic.html" , " w" ) do io
119+ sub = Session (session)
120+ app = App () do
121+ fig = Figure (size= (500 , 500 ))
122+ ax = Axis3 (fig[1 , 1 ])
123+ p0 = Point3f (x₀)
124+ v0 = Vec3f (dx₀)
125+
126+ xlims! (ax, x_size)
127+ ylims! (ax, y_size)
128+ zlims! (ax, z_size)
129+ arrows! (ax, [p0], [v0], color= :red )
130+
131+ # set picture as xy plane
132+ surface! (ax, [0 , 0 , 68 , 68 ], [0 , 105 , 105 , 0 ], [0 , 0 , 0 , 0 ],
133+ color= :lightgreen , transparency= true )
134+
135+ fig
136+ end
137+ as_html (io, sub, app)
138+ end
0 commit comments