В вашем примере несколько ошибок. Большинство из них связаны не с программированием, а с физикой и математикой.
Вы игнорируете изменение знака в термине перетаскивания. Кроме того, термин перетаскивания, указанный в уравнении F
, имеет дополнительную ошибку (дополнительно 1 / м).
Кажется, вы путаете скорость и ускорение. du[2]
является ускорением, поскольку оно является производной от скорости (u[2]
). Вы используете u[1]
в качестве скорости.
du[1] = u[1]
дает экспоненциальное увеличение u[1]
, то, что вы хотите - du[1] = u[2]
, что говорит о том, что на позицию влияет скорость.
Порядок u0 = [v0;y0]
перевернут, u[1]
- это координата y
, а u[2]
- это скорость.
Единственная ошибка программирования, которую я вижу, заключается в использовании индексации на основе 0 при выборе переменных для построения.
После исправления вышеуказанных пунктов вы получите:
using DifferentialEquations
using Plots
g = 9.8 # Accelaration of gravity
p = 1.2 # Density of air
m = 0.100 # A 100 g ball
r = 0.10 # 10 cm radius
Cd = 0.5 # Drag coeficient for a small spherical object
y0 = 1000.0 # Initial height of the body (1000 m)
v0 = 10.0 # Initial velocity of the body (10 m/s^2, going up)
A = pi*r^2; # Cross-section area of the body;
u0 = [y0;v0] # Initial Conditions
tspan = (0.0,5.0) # Time span to solve for
p = [g;p;m;Cd;A]
function Terminal_Velocity(du,u,p,t)
du[1] = u[2] # velocity
du[2] = - p[1] - sign(u[2]) * 0.5 * (p[2]/p[3]) * (u[2]^2) * p[4] * p[5] # acceleration
end
prob = ODEProblem(Terminal_Velocity,u0,tspan,p)
sol = solve(prob)
plt1 = plot(sol; vars=1)
plt2 = plot(sol; vars=2)
plot(plt1, plt2)
Можно пойти еще дальше и использовать обратные вызовы, чтобы гарантировать, что смена знака не вызовет числовых ошибок.
Для этого замените строку solve
на
cond(u, t, i) = u[2]
callback = ContinuousCallback(cond, nothing)
sol = solve(prob; callback=callback)