Skip to content

Moe’s Homepage

Knows how to provide Solution

Menu
  • Home
  • About
    • About Me
Menu

Time To Empty

Posted on November 14, 2025November 14, 2025 by mabouali

I saw a LinkedIn post (here) that took me back to my undergraduate course, regarding hydraulics structures and fluid mechanics. It is a very simple question! Which bucket will empty first?

The question just reminded me of the old time during my undergraduate classes, when the problem statements were clear. Anyway, based on the comments that people left on the post, It just motivated me to write a post about it.

To find the answer (i.e. which bucket will be emptied first), we need to first figure out how fast the water is going to exit the bucket. But before calculating that, we need to learn about Bernoulli's Equation

Table of Contents

Toggle
  • Bernoulli’s Equation (or Principle)
  • Torricelli’s Law
  • Deriving An Equation Between Time And Height Of Water
  • Cylindrical Tank
  • The Semi-Cone Shaped Bucket
  • Let’s plug-in the numbers
  • Solving Time To Empty Numerically
  • Could we guess which bucket empties faster without all these?
  • A reminder of the past

Bernoulli’s Equation (or Principle)

Bernoulli's Equation essentially is the Conservation of Energy (or Sir Isaac Newton's Law of Motion) but for fluids. When we say conservation of energy, this means that this equation can only be used when there is no dissipation of energy due to turbulence and/or viscosity. If you are civil engineer, you should be very familiar with this equation, since it is used a lot in calculating pressure and speed in pipes.

The Bernoulli's equation simply says:

    \[\displaystyle  \frac{P}{\rho} + gh + \frac{v^2}{2} = \mathtext{constant}\]

where:

  • P is the pressure
  • \rho is the density of the fluid and it must be constant (incompressible),
  • g is the gravitational acceleration,
  • h is the height from a datum, and
  • v is the fluid velocity.

You can read more about Bernoulli's equation here.

Let's see in the next section, how we can use Bernoulli's equation to derive an equation between the speed of water exiting the faucet (or spigot) and the height or depth of the water.

Torricelli’s Law

Torricelli's law, which relates the speed of water flowing out to the height of the water in a container, was discovered about 100 years earlier than Bernoulli's equation. However, here we are going to use Bernoulli's equation to derive the Torricelli's law (as already done in many text-books and in wikipedia linked here).

Remember that Bernoulli's equation stated that \displaystyle \frac{P}{\rho} + gh + \frac{v^2}{2} is a constant value. Hence, the sum of these three terms at a point inside the bucket at the top of the water should be the same as the sum of these terms at the faucet when the water exits the bucket. In another word, we have:

    \[\displaystyle  \frac{P_T}{\rho} + gh_T + \frac{v_T^2}{2} =\frac{P_S}{\rho} + gh_S + \frac{v_S^2}{2}\]

Anywhere you see a <\cdot>_T we are referring to a value in the Tank; likewise, anywhere you see <\cdot>_S we are referring to a value at the faucet or spigot.

Based on the above equation, and the problem setup we have:

  • \displaystyle \frac{P_T}{\rho} = \frac{P_S}{\rho}, since both have the same pressure
  • we can assume h_S=0 and simplify h_T = h.

Now we only need an equation to relate v_T that is the velocity of water (going down) in the tank to v_S which is the velocity of water exiting the faucet or spigot. That's were the continuity equation comes in handy.

We know that the flow of water is equal to speed of water multiplied by the area of the cross section projected to a plane that is perpendicular to the water velocity. In this case, we can say that:

    \[v_T*A_T=v_S*A_S\]

therefore, we have:

    \[\begin{matrix} v_T &=& \displaystyle \frac{A_S}{A_T}v_S\\[10]     &=& cv_s\\ \end{matrix}\]

where c=\displaystyle \frac{A_S}{A_T}.

Now we can rewrite the Bernoulli's equation as:

    \[ \begin{array}{rcl} \cancel{\displaystyle \frac{P_T}{\rho}} + gh_T + \displaystyle \frac{v_T^2}{2} &=& \cancel{\displaystyle \frac{P_S}{\rho}} + \cancel{gh_S} + \displaystyle \frac{v_S^2}{2} \\ [15] gh +\displaystyle c^2\frac{v_S^2}{2} &=& \displaystyle \frac{v_S^2}{2} \\[15] \left( 1 - c^2 \right ) v_S^2 &=& 2gh \\[15] \end{array}\]

Which finally gives us the relation between height of water and the speed of water at the spigot:

    \[v_s = \sqrt{\displaystyle \frac{2gh}{1 - c^2}}\]

Notice that in many engineering classes and applications A_S \lll A_T, therefore, we have \lim{\left( 1-c^2\right )}=\lim{\left( 1-\frac{A_S}{A_T} \right)} = 1 and we can assume:

    \[$v_s = \sqrt{2gh}$\]

Deriving An Equation Between Time And Height Of Water

Now we are ready to derive an equation to relate the height of water in the tank (h) to elapsed time (t) since the faucet or spigot was openned.

In the water tank, we know the volume of the water that has exited the Tank is:

    \[d\mathbf{V} = - A_T\times\,dh\]

Notice that small v (i.e. v) is used for speed; and capital V (i.e. V) is used for volume.

On the other hand the volume of water that is exiting the spigot can be calculated as:

    \[\begin{array}{ccl} d\mathbf{V} &=& A_S \times v_S \times \,dt \\[10] &=& A_S \times \sqrt{\displaystyle \frac{2gh}{1 - c^2}} \times \,dt\\ \end{array}\]

The dV calculated by the above two equation should be equal; hence, we have:

    \[\begin{array}{rcl} - A_T\times\,dh &=& A_S \times \sqrt{\displaystyle \frac{2gh}{1 - c^2}} \times \,dt\\[20] -A_T\frac{dh}{\sqrt{h}} &=&  A_S\sqrt{\displaystyle \frac{2g}{1 - c^2}}\,dt\\ \end{array}\]

if we assume:

    \[\alpha = A_S\sqrt{\frac{2g}{1 - c^2}}\]

then we can write:

(1)   \begin{equation*}  -A_T\frac{dh}{\sqrt{h}} = \alpha\,dt \end{equation*}

Cylindrical Tank

Before we get to our original problem, let's solve the above equation for a cylindrical tank. For a cylindrical tank we have:

    \[A_T = \pi\,R^2 = \mathtext{constant}\]

Regardless of the shape of the tank, we can assume that the spigot or faucet area is also constant, i.e. A_S=\mathtext{constant}.

Now we can intergrate both side of the equation:

    \[ \begin{array}{ccc} \displaystyle \bigint_{h_{max}}^{0}{-\frac{dh}{\sqrt{h}}} &=& \displaystyle \bigint_{0}^{t}{\frac{A_S}{A_T}\sqrt{\frac{2g}{1 - c^2}}\,dt} \end{array}\]

Integrating both side we will have:

    \[-2\sqrt{h}\Bigg|_{h_{max}}^{0} = \displaystyle \frac{A_S}{A_T}\sqrt{\frac{2g}{1 - c^2}}t\Bigg|_{0}^{t_{empty}}\]

If we assume H_T=h_{max}, is the maximum height of the water (i.e. height of the tank), and T=t_{empty} is the time that the tank will be empty (i.e. h=0), we have:

    \[T= \displaystyle 2\frac{A_T}{A_S}\sqrt{\frac{1 - c^2}{2g}}\sqrt{H_T}\]

For the rest of this document, let's assume A_S \lll A_T hence \lim{\left( 1-c^2\right )} = 1. If we multiply the right hand side by \dfrac{\sqrt{H_T}}{\sqrt{H_T}}, and remember that V_T=A_TH_T for a cylindrical tank, we have:

    \[T= 2{\frac{A_T}{A_S}\sqrt{\frac{1}{2g}}\sqrt{H_T}\times \dfrac{\sqrt{H_T}}{\sqrt{H_T}}\]

    \[T= \displaystyle 2\frac{A_TH_T}{A_S}\sqrt{\frac{1}{2g}}\times \dfrac{1}{\sqrt{H_T}}\]

    \[T= \displaystyle \frac{\mathbf{V}_T}{A_S}\sqrt{\frac{2}{gH_T}}\]

This means that if we have two water tanks that have the same volume (i.e. V_{T,1}=V_{T,2}); however, one of them has a smaller base (i.e. it is thinner or A_{T,1} < A_{T,2}); hence, one is taller (i.e. H_{T,1} > H_{T,2}), the tank that is taller will be emptied faster (i.e. T_1 < T_2).

The Semi-Cone Shaped Bucket

Now we can start to address our original problem, that is "time to empty" of tanks that are shaped as Semi-Cone (left bucket or Tank X) or inverted semi-cone (right bucket or Tank Y).

We can still integrate both sides of equation (1) to derive a relation between time (t) and height of water (h); however, remember that in this case, we can no longer assume that A_T = \mathtext{constant}. In fact, now A_T is a function of height of water, which changes with time.

For a semi-cone we can say that:

    \[A_T\left( h \right ) = \pi\,R\left( h \right )^2\]

where:

    \[\begin{array}{ccl} R \left( h \right ) &=& \displaystyle \frac{R_F - R_E}{H_T}h+R_E \\[10] &=& ah+b \\ \end{array}\]

where:

  • a=\displaystyle \frac{R_F - R_E}{H_T},
  • b=R_E,
  • R_F is the radius of the tank at the top, when it is Full, and
  • R_E is the radius of the tank at the bottom, with it is completely Empty.

By substituting R \left( h \right ) in A_T\left( h \right ) equation we have:

    \[\begin{array}{ccl} A_T\left( h \right ) &=& \pi\,R\left( h \right )^2 \\[10] &=& \pi\,\left( ah+b \right )^2 \\[10] &=& \pi\,\left( a^2h^2 + 2abh + b^2 \right ) \\[10] &=& c_0 + c_1 h + c_2h^2 \end{array}\]

where c_0 = b^2\pi, c_1=2ab\pi, and c_2=a^2\pi.

Now if we use the above equation for A_T in equation (1), we have:

    \[\begin{array}{rcl} -A_T\frac{dh}{\sqrt{h}} &=& \alpha\,dt \\[10] \displaystyle -\frac{c_0 + c_1 h + c_2h^2}{\sqrt{h}}\,dh &=& \alpha\,dt \\ \end{array}\]

Now integrating both sides we have:

    \[ \displaystyle \bigint_{H_T}^{0}{-\frac{c_0 + c_1 h + c_2h^2}{\sqrt{h}}\,dh} = \bigint_{0}^{T}{\alpha\,dt}\]

and we will have:

    \[-\left(2c_0h^{\frac{1}{2}} + \frac{2}{3}c_1h^{\frac{3}{2}} + \frac{2}{5}c_2h^{\frac{5}{2}}\right) \Bigg|_{H_T}^{0} = \left( \alpha t\right) \Bigg|_{0}^{T}\]

Which gives us:

    \[T = \displaystyle \frac{1}{\alpha} \left( 2c_0H_T^{\frac{1}{2}} + \frac{2}{3}c_1H_T^{\frac{3}{2}} + \frac{2}{5}c_2H_T^{\frac{5}{2}}\right)\]

Let’s plug-in the numbers

Let's now plugin some numbers and finally see which bucket will empty faster:

VariableSemi-ConeInverted Semi-Cone
R_E0.3 [m]1.0 [m]
R_F1.0 [m]0.3 [m]
H_T0.7 [m]0.7 [m]
\displaystyle V_T = \frac{1}{3}\pi H_T\left( R_E^2 + R_ER_F+R_F^2\right)1.019 [m^3]1.019 [m^3]
a=\displaystyle \frac{R_F - R_E}{H_T}1.0-1.0
b=R_E0.3 [m]1.0 [m]
c_0 = b^2\pi0.2833.142
c_1=2ab\pi1.885-6.283
c_2=a^2\pi3.1423.142
A_S0.0254 [m]0.0254 [m]
\alpha=A_S\sqrt{2g}0.1090.109
\frac{1}{\alpha}9.1889.188
H_T^{\frac{1}{2}}0.8370.837
H_T^{\frac{3}{2}}0.5860.586
H_T^{\frac{5}{2}}0.4100.410
T = \displaystyle \frac{1}{\alpha} \left( 2c_0H_T^{\frac{1}{2}} + \frac{2}{3}c_1H_T^{\frac{3}{2}} + \frac{2}{5}c_2H_T^{\frac{5}{2}}\right)15.843 [s]30.494 [s]

As you can see the inverted bucket (i.e. tank Y on the right) takes almost twice the time to fully drain!!!

Solving Time To Empty Numerically

Although this problem could be very real, but usually, in real applications we are not so lucky that we can really integrate the problem and get a closed-form solution for our problem.

So, now that we know the closed-form solution, let's see if we can solve this problem numerically, without the hurdle of going through integration. Although, I absolutely enjoyed it; It was a while that I had to do some closed-form solution.

Anyway, let's solve this problem numerically. Remember that we already derived a formula to calculate the speed that water is exiting the faucet/spigot knowing the height of the tank, which was:

    \[v_s = \sqrt{\frac{2gh}{1 - c^2}}\]

Notice that this velocity has nothing to do with the shape of the tank. So, no matter what shape your tank is, the speed at which the water exits the tank can be calculated using only the height of the water in the tank.

Also remember that volume of the water that is being drained can be calculated as:

    \[\begin{array}{ccl} d\mathbf{V} &=& A_S \times v_S \times \,dt \\[10] &=& A_S \times \sqrt{\displaystyle \frac{2gh}{1 - c^2}} \times \,dt\\ \end{array}\]

So, here is the approach we use:

  1. Assume a small dt=0.01~[s]
  2. initialize h=H_T and V =V_T.
  3. compute v_S = \sqrt{\frac{2gh}{1 - c^2}},
  4. compute dV = A_S \times v_S \times \,dt,
  5. Update V by deducting d\mathbf{V}
  6. update h using semi-cone volume formula,
  7. if V >0 go to step 3; otherwise, end the computation.

The above steps are shown in the flow chart below:

flowchart TD A(["Start"]) A --> B["Initialize h and V"] B --> C["compute vs"] C --> D["compute drained volume"] D --> E["update V and h"] E --> F{"Is V > 0"} F -->|yes| C F -->|no| G(["end"])

Here is a Python implementation of the naive approach mentioned above:

import math
from scipy.optimize import fsolve

g: float = 9.18  # [m/s^2]

def update_height(V: float, R_F: float, R_E: float, H_T: float, h: float):
    a = (R_F - R_E) / H_T
    b = R_E
    R = lambda h: a * h + b
    volume = lambda h: (1.0/3.0) * math.pi * h * (R_E * R_E + R_E * R(h) + R(h) * R(h))
    residual = lambda h: volume(h) - V
    return float(fsolve(residual, h)[0])

def area_at_height(h: float, R_F: float, R_E: float, H_T):
    a = (R_F - R_E) / H_T
    b = R_E
    R = a * h + b
    return math.pi * R * R

def time_to_empty(
    H_T: float, 
    R_F: float,
    R_E: float,
    area_spigot: float = 0.0254, 
    dt: float = 0.01,
    ignore_spigot_ratio: bool = True
):
    h = H_T  # Setting initial height ot bucket highet H
    V = (1.0/3.0) * math.pi * H_T * (R_F * R_F + R_E * R_F + R_E * R_E)
    drained_volume = 0
    counter = 0
    while True:
        if counter == 0:
            print(f"---------------------------------------------------")
            print(f"{'step':^6} | {'t':^8}| {'h':^7} | {'V':^7} | {'dV':^12}")
            print(f"---------------------------------------------------")

        if counter % 100 == 0:
            t = counter * dt
            print(f"{counter:^6d} | {t:^8.3f}| {h:^7.3f} | {V:^7.3f} | {drained_volume:^12.6f}")
            
        area_bucket_at_h = area_at_height(h=h, R_F=R_F, R_E=R_E, H_T=H_T)
        c = 0.0 if ignore_spigot_ratio else area_spigot/area_bucket_at_h
        vs = math.sqrt(2*g*h/(1 - c*c))

        drained_volume = vs * area_spigot * dt

        if V < drained_volume:
            t = counter * dt
            print(f"{counter:^6d} | {t:^8.3f}| {h:^7.3f} | {V:^7.3f} | {drained_volume:^12.6f}")
            print(f"---------------------------------------------------")
            break
            
        V = V - drained_volume
        h = update_height(V=V, R_F=R_F, R_E=R_E, H_T=H_T, h=h)
        counter = counter + 1

Let's run our code and check what we get:

> time_to_empty(H_T=0.7, R_F=1.0, R_E=0.3, dt=0.01)

---------------------------------------------------
 step  |    t    |    h    |    V    |      dV     
---------------------------------------------------
  0    |  0.000  |  0.700  |  1.019  |   0.000000  
 100   |  1.000  |  0.670  |  0.929  |   0.000891  
 200   |  2.000  |  0.640  |  0.841  |   0.000871  
 300   |  3.000  |  0.608  |  0.755  |   0.000849  
 400   |  4.000  |  0.574  |  0.671  |   0.000825  
 500   |  5.000  |  0.539  |  0.590  |   0.000799  
 600   |  6.000  |  0.502  |  0.511  |   0.000771  
 700   |  7.000  |  0.462  |  0.436  |   0.000740  
 800   |  8.000  |  0.420  |  0.363  |   0.000706  
 900   |  9.000  |  0.376  |  0.295  |   0.000667  
 1000  |  10.000 |  0.327  |  0.230  |   0.000623  
 1100  |  11.000 |  0.275  |  0.170  |   0.000571  
 1200  |  12.000 |  0.217  |  0.116  |   0.000508  
 1300  |  13.000 |  0.154  |  0.069  |   0.000428  
 1400  |  14.000 |  0.086  |  0.032  |   0.000320  
 1500  |  15.000 |  0.023  |  0.007  |   0.000168  
 1580  |  15.800 |  0.000  |  0.000  |   0.000003  
---------------------------------------------------

And now if we run same code for the inverted semi-cone we get:

> time_to_empty(H_T=0.7, R_F=0.3, R_E=1.0, dt=0.01)

---------------------------------------------------
 step  |    t    |    h    |    V    |      dV     
---------------------------------------------------
  0    |  0.000  |  0.700  |  1.019  |   0.000000  
 100   |  1.000  |  0.525  |  0.935  |   0.000789  
 200   |  2.000  |  0.436  |  0.860  |   0.000719  
 300   |  3.000  |  0.374  |  0.790  |   0.000666  
 400   |  4.000  |  0.326  |  0.726  |   0.000622  
 500   |  5.000  |  0.286  |  0.666  |   0.000582  
 600   |  6.000  |  0.252  |  0.610  |   0.000547  
 700   |  7.000  |  0.223  |  0.557  |   0.000515  
 800   |  8.000  |  0.198  |  0.507  |   0.000484  
 900   |  9.000  |  0.175  |  0.460  |   0.000456  
 1000  |  10.000 |  0.155  |  0.415  |   0.000429  
 1100  |  11.000 |  0.137  |  0.374  |   0.000403  
 1200  |  12.000 |  0.121  |  0.335  |   0.000378  
 1300  |  13.000 |  0.106  |  0.298  |   0.000354  
 1400  |  14.000 |  0.092  |  0.264  |   0.000331  
 1500  |  15.000 |  0.080  |  0.232  |   0.000308  
 1600  |  16.000 |  0.069  |  0.202  |   0.000286  
 1700  |  17.000 |  0.059  |  0.175  |   0.000265  
 1800  |  18.000 |  0.050  |  0.149  |   0.000244  
 1900  |  19.000 |  0.042  |  0.126  |   0.000223  
 2000  |  20.000 |  0.035  |  0.105  |   0.000203  
 2100  |  21.000 |  0.028  |  0.086  |   0.000182  
 2200  |  22.000 |  0.022  |  0.068  |   0.000163  
 2300  |  23.000 |  0.017  |  0.053  |   0.000143  
 2400  |  24.000 |  0.013  |  0.040  |   0.000123  
 2500  |  25.000 |  0.009  |  0.028  |   0.000104  
 2600  |  26.000 |  0.006  |  0.019  |   0.000085  
 2700  |  27.000 |  0.004  |  0.011  |   0.000066  
 2800  |  28.000 |  0.002  |  0.006  |   0.000047  
 2900  |  29.000 |  0.001  |  0.002  |   0.000028  
 3000  |  30.000 |  0.000  |  0.000  |   0.000009  
 3044  |  30.440 |  0.000  |  0.000  |   0.000000  
---------------------------------------------------

Could we guess which bucket empties faster without all these?

Yes, we could. All we need to know that:

  1. only the height of the water in the tank determines the water velocity existing the spigot, and
  2. the shape of the tank doesn't have anything to do with the velocity of the water existing the tank.

However, remember that like most dams, the majority of the volume of the water in the tank like tank x on the left is at the top. Therefore, the big part of the volume would be exited at a higher velocity.

Again notice that the velocity that the water exits the tank is not a function of the volume of the water remaining in the tank, but the height of the water. At the same height both tank will empty exactly at the same rate. Since tank X has most of its volume at higher height, it will be drained faster.

A reminder of the past

Remember that I said earlier in this post that this problem reminded me of something that happened in the past?!!!

Many years ago, more than two decades ago, in one of my university classes, the instructor provided similar problem. Not exactly as this one, but similar. No one in our class was able to solve the problem, except one another student and I.

Other students asked us about how we solved it. The other students solution was rather easy to understand; but, not correct! His solution sounded logical, rational, and understandable, but it was not the right solution and it was not producing the correct answer.

My solution, however, sounded much more complex and, of course, it used differential equations and integration; a bit harder than the one that we saw here (just a bit).

At the end the class decided to go with the solution that they could understand, rather than the solution that I had which they could not understand. One student even said that my solution must be wrong, because she couldn't understand it and it is unnecessarily too complicated.

Anyway, when the instructor came back with the graded assignments, he had two messages for the class:

  1. They should not just copy an answer from another student unless if they understand it.
  2. Only one person in the class solved the problem correctly.

That event actually taught me something. Yes, sometimes your solution is tagged as wrong and/or complicated; and people might not go with it; they might reject it; But, don't worry! The problem might not be what you are proposing at all.

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Search Posts

Latest Posts

  • Queen or Not-Queen, That’s The Question
  • Zipping
  • Mini-Sudoko
  • Let’s Tango!
  • Time To Empty

Categories

  • Constraint Programming
  • Fluid Mechanics
  • Fundamentals
  • Linear Algebra
  • Mathematics
  • Memories
  • opinion
  • Optimization
  • Optimization
  • OR-Tools
  • Physics
  • Piecewise-Linear
  • Programming
  • Python
  • Python
  • SQL
  • Stories
  • Tools
  • Uncategorized

Archive

  • December 2025
  • November 2025
  • October 2025
  • September 2024
  • March 2024
  • February 2024
  • January 2024
  • December 2023
© 2026 Moe’s Homepage | Powered by Minimalist Blog WordPress Theme