A curiosity journal of math, physics, programming, astronomy, and more.

Analysis of incremental water heating

Having explored this thermodynamics problem numerically, I now want to look at it analytically and see what math points to as the theoretical limit for how warm we can get the cold water (and how cold we can get the hot water).

The core logic we've used so far has been this function:

(defn equalize-temperatures [{a1 :amount t1 :temp} {a2 :amount t2 :temp}]
  (let [change (/ (- (max t1 t2) (min t1 t2))
                  (/ (+ a1 a2) a1))
        new-temp (if (<= t1 t2)
                   (- t2 change)
                   (+ t2 change))]
    [{:amount a1 :temp new-temp}
     {:amount a2 :temp new-temp}]))

To express this in symbolic math, we'll think in terms of an iterative system, in which the temperature of the hot water at each step depends on the temperature of the hot water at the previous step, the constant temperature of the cold water, and the amount of cold water immersed in the hot water.

Continuing to work in code for a moment, we can simplify the logic by making a few assumptions:

  1. a1 and t1 always refers to the hot water
  2. a1 is always 1 (all the hot water)
  3. a2 is never more than 1
  4. t2 (the cold water's temperature) is always less than t1 (the hot water's temperature)
  5. we only need the new temperature at equilibrium

With those assumptions, the code boils down to this:

(defn new-temperature [{t1 :temp} {a :amount t2 :temp}]
  (+ t2 (/ (- t1 t2) (+ 1 a))))

which is much easier to translate into math:

StartLayout 1st Row 1st Column upper H Subscript n plus 1 2nd Column equals upper C plus left-parenthesis upper H Subscript n Baseline minus upper C right-parenthesis StartFraction 1 Over 1 plus a EndFraction EndLayout

What we really want is the difference in temperature at each step:

StartLayout 1st Row 1st Column normal upper Delta upper H Subscript n plus 1 2nd Column equals upper H Subscript n plus 1 Baseline minus upper H Subscript n Baseline 2nd Row 1st Column Blank 2nd Column equals upper C plus left-parenthesis upper H Subscript n Baseline minus upper C right-parenthesis StartFraction 1 Over 1 plus a EndFraction minus upper H Subscript n Baseline 3rd Row 1st Column Blank 2nd Column equals upper C left-parenthesis 1 minus StartFraction 1 Over 1 plus a EndFraction right-parenthesis plus upper H Subscript n Baseline left-parenthesis StartFraction 1 Over 1 plus a EndFraction minus 1 right-parenthesis 4th Row 1st Column Blank 2nd Column equals left-parenthesis StartFraction 1 Over 1 plus a EndFraction minus 1 right-parenthesis left-parenthesis upper H Subscript n Baseline minus upper C right-parenthesis 5th Row 1st Column Blank 2nd Column equals minus StartFraction a Over 1 plus a EndFraction left-parenthesis upper H Subscript n Baseline minus upper C right-parenthesis EndLayout

Translating from discrete to continuous terms gives us this:

StartLayout 1st Row 1st Column StartFraction d upper H Over d t EndFraction 2nd Column equals minus StartFraction a Over 1 plus a EndFraction left-parenthesis upper H left-parenthesis t right-parenthesis minus upper C right-parenthesis EndLayout

Stated non-symbolically, the rate of the hot water's temperature change is proportional to the difference between its temperature at any given moment and the temperature of the cold water. That means the above formulation is just Newton's Law of Cooling:

StartLayout 1st Row 1st Column StartFraction d upper T Over d t EndFraction 2nd Column equals minus k left-parenthesis upper T left-parenthesis t right-parenthesis minus upper T Subscript e n v Baseline right-parenthesis EndLayout

Newton's Law of Cooling is a differential equation whose solution is

StartLayout 1st Row 1st Column upper T left-parenthesis t right-parenthesis 2nd Column equals upper T Subscript e n v Baseline plus left-parenthesis upper T left-parenthesis 0 right-parenthesis minus upper T Subscript e n v Baseline right-parenthesis e Superscript minus k t EndLayout

Substituting in the elements from our formulation above gives us

StartLayout 1st Row 1st Column upper H left-parenthesis t right-parenthesis 2nd Column equals upper C plus left-parenthesis upper H left-parenthesis 0 right-parenthesis minus upper C right-parenthesis e Superscript minus StartFraction a Over 1 plus a EndFraction t EndLayout

In the discrete form, n ranged from 0 to the number of batches, which is the reciprocal of the fractional amount, or 1/a. In the continuous form, t has the same range. The final temperature of the hot water, then, is

StartLayout 1st Row 1st Column upper H left-parenthesis 1 slash a right-parenthesis 2nd Column equals upper C plus left-parenthesis upper H left-parenthesis 0 right-parenthesis minus upper C right-parenthesis e Superscript minus StartFraction a Over 1 plus a EndFraction StartFraction 1 Over a EndFraction Baseline 2nd Row 1st Column Blank 2nd Column equals upper C plus left-parenthesis upper H left-parenthesis 0 right-parenthesis minus upper C right-parenthesis e Superscript minus StartFraction 1 Over 1 plus a EndFraction EndLayout

As a goes to zero, we get

StartLayout 1st Row 1st Column limit Underscript a right-arrow 0 Endscripts upper H left-parenthesis 1 slash a right-parenthesis 2nd Column equals limit Underscript a right-arrow 0 Endscripts left-parenthesis upper C plus left-parenthesis upper H left-parenthesis 0 right-parenthesis minus upper C right-parenthesis e Superscript minus StartFraction 1 Over 1 plus a EndFraction Baseline right-parenthesis 2nd Row 1st Column Blank 2nd Column equals upper C plus left-parenthesis upper H left-parenthesis 0 right-parenthesis minus upper C right-parenthesis e Superscript negative 1 EndLayout

Substitute in known values:

StartLayout 1st Row 1st Column limit Underscript a right-arrow 0 Endscripts upper H left-parenthesis 1 slash a right-parenthesis 2nd Column equals 20 plus left-parenthesis 80 minus 20 right-parenthesis e Superscript negative 1 Baseline 2nd Row 1st Column Blank 2nd Column equals 20 plus 60 e Superscript negative 1 Baseline 3rd Row 1st Column Blank 2nd Column almost-equals 20 plus 60 dot 0.36787944117144233 4th Row 1st Column Blank 2nd Column equals 42.07276647028654 EndLayout

Thus, in theory, the hot water could get down to about 42.0728°C, at which point the cold water would be 57.9272°C. Those results match to three decimal places the numbers we got numerically when we divided the cold water into 10,000 separate batches:

(heat-cold-water
  {:amount 1 :temp 80}
  (repeat 1e5 {:amount 1e-5 :temp 20}))
{:hot {:amount 1, :temp 42.072876833515096},
 :cold {:amount 0.9999999999980838, :temp 57.92712316626038}}

Since 10,000 batches got us within 0.0003% of the theoretical limit, what's the fewest batches would we need to get within just 1% of the theoretical limit?

(let [limit (+ 20 (* 60 (Math/exp -1)))]
  (sequence
    (comp
      (map (fn [batches]
             [batches
              (-> (heat-cold-water
                    {:amount 1 :temp 80}
                    (repeat batches {:amount (/ batches) :temp 20}))
                :hot :temp
                (as-> $ (/ (- $ limit) limit)))]))
      (drop-while (comp #(< 0.01 %) second))
      (take 1))
    (iterate inc 2)))
([26 0.009930457750641221])

Only 26 batches. Seems feasible (under ideal conditions).