I'll start with the aside that the question neglects buoyancy; if the
"ball" is a party balloon, it could remain aloft for a long time, or
indefinitely if it is lighter than air.
Buoyancy aside, my intuition was similar to N. Virgo's, that with
sufficiently high drag and initial velocity, it should be possible to
get the ball-in-air case to "punch" through to a high altitude, from
which it would then descend slowly at terminal velocity, slowly enough
for the ball-in-vacuum case to catch up and win.
But experimentally, that is wrong. I wrote a simple simulator in
Python, and played with the parameters, and found that as long as drag
is at least linear, the ball-in-air always wins. Adding superlinear
drag only makes the ball-in-air return to the ground even faster due to
quickly arresting the ascent, after which the linear term dominates
during terminal velocity descent. Adding more initial velocity merely
increases the advantage for the air case.
But here's the weird thing, which makes me think there may be a simple
analytical argument hiding here: regardless of the parameters,
the velocity of the balls is the same at the moment the first one
hits the ground! That is, the ball-in-air consistently hits the
ground, at its terminal velocity, just as the ball-in-vacuum is reaching
that same speed, as it begins its descent!
Example 1:
inputs:
initialVelocity : 100.00 m/s
gravity : -10.00 m/s^2
timeStep : 0.10 s
linearResistance : 0.10 1/s
quadraticResistance: 0.00 1/m
outputs: Annotated comments
winner: B (air) -------------------
t : 16.00 s Time when B hits the ground.
xA : 328.00 m Height of A.
max_xA: 505.00 m Maximum height of A.
vA : -60.00 m/s <--- Velocity of A.
vAturn: 10.10 s When A turned around.
xB : -0.55 m Height of B (it hit the ground).
max_xB: 310.33 m Maximum height of B.
vB : -59.94 m/s <--- Velocity of B (~terminal).
vBturn: 6.90 s When B turned.
Notice that the final vA
and vB
are nearly the same. A (in vacuum)
of course would keep accelerating downward if the simulator continued,
while B has long since reached its terminal velocity.
Example 2 (10x faster initial velocity):
inputs:
initialVelocity : 1000.00 m/s
gravity : -10.00 m/s^2
timeStep : 0.10 s
linearResistance : 0.10 1/s
quadraticResistance: 0.00 1/m
outputs:
winner: B (air)
t : 110.00 s
xA : 49555.00 m
max_xA: 50050.00 m
vA : -100.00 m/s <---
vAturn: 100.10 s
xB : -0.17 m
max_xB: 7614.13 m
vB : -99.98 m/s <---
vBturn: 23.90 s
Again, the final vA
and vB
are nearly the same.
Example 3 (2x linear drag coefficient):
inputs:
initialVelocity : 100.00 m/s
gravity : -10.00 m/s^2
timeStep : 0.10 s
linearResistance : 0.20 1/s
quadraticResistance: 0.00 1/m
outputs:
winner: B (air)
t : 14.20 s
xA : 418.90 m
max_xA: 505.00 m
vA : -42.00 m/s <---
vAturn: 10.10 s
xB : -2.58 m
max_xB: 228.11 m
vB : -41.48 m/s <---
vBturn: 5.50 s
I suspect this is true in general for linear resistance, which would
then prove that the ball-in-air always lands first. But I don't know
how to prove this, especially using high school physics math.
Simulator code:
#!/usr/bin/env python3
"""Simulate two thrown balls."""
# Initial upward velocity in m/s.
initialVelocity = 100
# Uniform gravity in m/s^2.
gravity = -10
# Simulation time step in s.
timeStep = 0.1
# Linear air resistance factor in 1/s. That is, ball B experiences
# acceleration of `-vB*linearResistance`.
linearResistance = 0.1
# Quadratic air resistance factor in 1/m. B experiences acceleration
# of `-abs(vB)*vB*quadraticResistance`.
quadraticResistance = 0
# True to print every time step.
debug = False
def simLoop():
# Elapsed time.
t = 0
# A is in a vacuum.
xA = 0
vA = initialVelocity
max_xA = 0
vA_turned_time = None
# B is in air.
xB = 0
vB = initialVelocity
max_xB = 0
vB_turned_time = None
# Who hits first?
winner = None
if debug:
print(f" [-------- vacuum --------] [--------- air ----------]")
print(f" t xA vA xB vB")
print(f"------------ ------------ ------------ ------------ ------------")
while winner is None:
t += timeStep
# Update A by one time step.
xA += vA * timeStep
vA += gravity * timeStep
if xA > max_xA:
max_xA = xA
if vA_turned_time is None and vA < 0:
vA_turned_time = t
# Update B by one time step.
xB += vB * timeStep
vB += (gravity
- vB * linearResistance
- abs(vB) * vB * quadraticResistance) * timeStep
if xB > max_xB:
max_xB = xB
if vB_turned_time is None and vB < 0:
vB_turned_time = t
# Current system state.
if debug:
print(f"{t:12.2f} {xA:12.2f} {vA:12.2f} {xB:12.2f} {vB:12.2f}")
# Winner?
if xA <= 0:
if xB <= 0:
winner = "Tie"
else:
winner = "A (vacuum)"
elif xB <= 0:
winner = "B (air)"
if debug:
print("")
vA_rising = " A is still rising!" if vA > 0 else ""
vB_rising = " B is still rising!" if vB > 0 else ""
print("inputs:")
print(f" initialVelocity : {initialVelocity:12.2f} m/s")
print(f" gravity : {gravity:12.2f} m/s^2")
print(f" timeStep : {timeStep:12.2f} s")
print(f" linearResistance : {linearResistance:12.2f} 1/s")
print(f" quadraticResistance: {quadraticResistance:12.2f} 1/m")
print("")
print("outputs:")
print(f" winner: {winner}")
print(f" t : {t:12.2f} s")
print(f" xA : {xA:12.2f} m")
print(f" max_xA: {max_xA:12.2f} m")
print(f" vA : {vA:12.2f} m/s{vA_rising}")
if vA_turned_time is not None:
print(f" vAturn: {vA_turned_time:12.2f} s")
print(f" xB : {xB:12.2f} m")
print(f" max_xB: {max_xB:12.2f} m")
print(f" vB : {vB:12.2f} m/s{vB_rising}")
if vB_turned_time is not None:
print(f" vBturn: {vB_turned_time:12.2f} s")
def main():
simLoop()
main()
# EOF