This is the first useful program I've written in the language of
Bicicleta.  It runs under the current Bicicleta available from
http://pobox.com/~kragen/sw/bicicleta.  (Older versions don't have
working exponentiation.)

I think this is a *much* better example program than the factorial and
such examples, because it shows how it's plausible to use it as the
programming language for everyday tasks in an end-user programming
system.

#!./bicicleta_run_script
# Icebox thermodynamics program.

# I had done a bunch of calculations for a kragen-tol post (and
# possibly a household project) about building an icebox to keep food
# frozen.  I kept having to change my assumptions and recalculate
# things by hand.  After I wrote the post, I realized that it would
# have been better to write the calculations in Bicicleta, so I did.
# It worked surprisingly well, but it takes an absurdly long amount of
# time to run --- like 20 seconds.  Doing the calculations in a
# spreadsheet would have been a little less convenient; I could have
# copied and pasted a range of cells and then made changes, but that's
# a little less convenient as writing "less_stringent_freezer =
# freezer { ice_kg = 16.0 }", and much more painful to understand
# after the fact.

# Example output:
# "<p>Thermal insulators in general conduct heat at
# about 0.04 W/m/K.  Styrofoam is a better
# insulator than some others; it conducts heat at about
# 0.033 W/m/K.</p>
# 
# <p>So let's consider building an icebox out of styrofoam.  The idea is
# that you put in some ice from some other source every so often, and
# that ice keeps the icebox cold.  If you salt the ice, it will melt
# below the freezing point of pure water, so your icebox can be a
# freezer.</p>
# 
# <p>Suppose you want a 2. L of salted
# ice in bottles to keep the temperature at -5°C for 24 hours
# at a time.  That means the total heat flux out has to be 2. L *
# 80 kcal/L over those 24 hours, which is
# 6.66666666667 kcal/h.  (That's 7.75333333333 watts.)</p>
# 
# <p>Suppose the interior of the freezer is
# 250. L in a convenient cubical shape; that's a 62.9960524947-cm
# cube, which has 2.38110157795 m² of surface area to lose heat through.
# Suppose the outside air temperature is 35°C, for a
# difference of 40 K.  0.033 W/m/K * 2.38110157795 m² * 40 K / 
# 7.75333333333 W = 0.405381008112 m of wall thickness, for a
# total size of 1.44072254117 m, cubed.</p>
# 
# <p>That's unwieldy, so suppose
# you're willing to use more ice. Suppose you want a 16. L of salted
# ice in bottles to keep the temperature at -5°C for 24 hours
# at a time.  That means the total heat flux out has to be 16. L *
# 80 kcal/L over those 24 hours, which is
# 53.3333333333 kcal/h.  (That's 62.0266666667 watts.)
# 0.033 W/m/K * 2.38110157795 m² * 40 K / 
# 62.0266666667 W = 0.050672626014 m of wall thickness, for a
# total size of 0.731305776976 m, cubed.  That's 7.64617160485 times 
smaller.</p>
# 
# <p>Suppose that the outside
# temperature is only 23°C on average.  Now, to
# melt the same amount of ice per day, the walls of the icebox that
# melts 2. kg of ice per day can be 0.283766705679 m thick, and
# the walls of the smaller icebox that melts 16. kg
# of ice per day can be only 0.0354708382098 m thick.
# 
# </p>
# "

{freezer:
        explanation = freezer.template % freezer
        template = "<p>Thermal insulators in general conduct heat at
about {standard_insulator_conductivity} W/m/K.  Styrofoam is a better
insulator than some others; it conducts heat at about
{styrofoam_conductivity} W/m/K.</p>

<p>So let's consider building an icebox out of styrofoam.  The idea is
that you put in some ice from some other source every so often, and
that ice keeps the icebox cold.  If you salt the ice, it will melt
below the freezing point of pure water, so your icebox can be a
freezer.</p>

<p>{heat_flux_paragraph}</p>

<p>{shape_paragraph}</p>

<p>{less_stringent_shape_paragraph}</p>

<p>{more_normal_temperature_paragraph}</p>
"
        standard_insulator_conductivity = 0.04 # W/m/K
        styrofoam_conductivity = 0.033 # W/m/K
        insulator_conductivity = freezer.styrofoam_conductivity

        heat_flux_paragraph = "Suppose you want a {ice_kg} L of salted
ice in bottles to keep the temperature at {temp}°C for {hours} hours
at a time.  That means the total heat flux out has to be {ice_kg} L *
{ice_heat_of_fusion} kcal/L over those {hours} hours, which is
{heat_flux} kcal/h.  (That's {heat_flux_watts} watts.)" % freezer

        ice_kg = 2.0
        temp = 0 - 5 # °C
        hours = 24   # to melt that much ice
        ice_heat_of_fusion = 80  # kcal/L
        heat_flux = freezer.ice_kg * freezer.ice_heat_of_fusion / freezer.hours
        heat_flux_watts = freezer.heat_flux * freezer.kcalh_to_watts
        kcalh_to_watts = 1.163  # according to units(1)

        shape_paragraph = "Suppose the interior of the freezer is
{capacity} L in a convenient cubical shape; that's a {cube_side_cm}-cm
cube, which has {area} m² of surface area to lose heat through.
Suppose the outside air temperature is {outside_temp}°C, for a
difference of {temp_gap} K.  {shape}" % freezer

        shape = "{insulator_conductivity} W/m/K * {area} m² * {temp_gap} K / 
{heat_flux_watts} W = {wall_thickness} m of wall thickness, for a
total size of {total_size} m, cubed." % freezer

        capacity = 250.0  # liters
        cube_side_cm = freezer.cuberoot(freezer.capacity / 1000) * 100
        # A function to calculate cube roots.
        # XXX mixed-mode 1 / 3.0 doesn't work yet
        cuberoot = {f: arg1 = 27.0, '()' = f.arg1 ** (1.0 / 3) }  
        area = (freezer.cube_side_cm / 100)**2 * 6
        outside_temp = 35 # °C
        temp_gap = freezer.outside_temp - freezer.temp  # kelvins
        wall_thickness = freezer.insulator_conductivity * freezer.area 
                * freezer.temp_gap / freezer.heat_flux_watts
        # note that due to lack of operator precedence, these parens are 
mandatory
        total_size = freezer.cube_side_cm / 100 + (freezer.wall_thickness * 2)

        less_stringent_shape_paragraph = "That's unwieldy, so suppose
you're willing to use more ice. {less_stringent_heat_flux_paragraph}
{less_stringent_shape}  That's {volume_ratio} times smaller." % freezer
        less_stringent_freezer = freezer { ice_kg = 16.0 }
        less_stringent_shape = freezer.less_stringent_freezer.shape
        less_stringent_heat_flux_paragraph = 
                freezer.less_stringent_freezer.heat_flux_paragraph
        volume_ratio = freezer.total_size**3 / 
                (freezer.less_stringent_freezer.total_size**3)

        more_normal_temperature_paragraph = "Suppose that the outside
temperature is only {more_normal_temperature}°C on average.  Now, to
melt the same amount of ice per day, the walls of the icebox that
melts {ice_kg} kg of ice per day can be {thinner_walls} m thick, and
the walls of the smaller icebox that melts {less_stringent_ice_kg} kg
of ice per day can be only {less_stringent_thinner_walls} m thick.

" % freezer
        more_normal_temperature = 23 # °C; lately the range has been 18-28
        in_more_normal_temperature = freezer { 
                outside_temp = freezer.more_normal_temperature 
        }
        thinner_walls = freezer.in_more_normal_temperature.wall_thickness
        less_stringent_ice_kg = freezer.less_stringent_freezer.ice_kg
        less_stringent_thinner_walls = freezer.in_more_normal_temperature
                .less_stringent_freezer.wall_thickness
}.explanation

Reply via email to