Formula Triangles in Python Part 2
The Inner Workings of the Universe With Just Three Numbers
In Part 1 of this series I introduced the concept of formula triangles. These illustrate the relationships between three quantities used in science, technology, engineering and other fields, specifically how an unknown value can be calculated from two known values. The Python code in Part 1 included functions to print formula triangles to the terminal and calculate unknown values, as well as a single example relating the distance, speed and time of a journey. Here in Part 2 I'll show a few more examples.
Please read Part 1 if you haven't already done so as this article will probably be a bit baffling otherwise!
The Code
The code shown below all lives in a file called formulatriangledemo_2.py but imports formulatriangle.py from the first article. All the files for Part 1 and Part 2 are in the Github repository where you can download or clone them. This is the first part of formulatriangledemo_2.py.
formulatriangledemo_2.py [partial]
import formulatriangle as ft
def main():
print("---------------------")
print("| codedrome.com |")
print("| Formula Triangles |")
print("---------------------\n")
# distance_speed_time()
volts_amps_ohms()
# mass_density_volume()
# force_mass_acceleration()
# speed_wavelength_frequency()
# energy_power_time()
.
.
.
if __name__ == "__main__":
main() The file contains six functions, each implementing a separate set of three quantities and values. To call each one just uncomment it is main and run the program. The distance_speed_time() function was described in Part 1 so I'll start with the volts_amps_ohms() function.
Electricity & Ohm's Law
The formula triangle below represents Ohm's Law which describes the relationship between the three major quantities involved in the flow of electricity through a wire or other electrical/electronic component.
These quantities are:
V - voltage or potential difference in volts
I - current in amps
R - resistance in ohms (Ω)
Let's look at each of these in more detail.
Voltage or potential difference is often described as being analagous to water pressure in a pipe, while others indignantly point out that electricity and water are completely different! Personally I think it's a reasonable description and most people have enough common sense to realise that it's only a rough analogy.
Electricity is carried by electrons which crawl through wires very slowly but which create waves travelling almost at the speed of light. Electrons have a negative charge, and as like charges repel if they are more densely packed at one end of a wire then they will start to move along the wire to, creating a flow of current and therefore electrical energy. It's easy to imagine forcing water to one end of a pipe, releasing the pressure and watching the water flow to the other end. This is why I believe the water analogy is perfectly valid.
Current is a measure of how many electrons move past a particular point in a given time, and therefore the energy being transferred. The SI unit of current is the ampere (usually shortened to amp), 1 amp (1A) being 6.241509074×1018 electrons per second. That is 6,241,509,074,000,000,000 electrons - over six quintillion - each with an elementary charge of 1e. That many elementary charges is known as a coulomb or 1C, therefore 1 ampere is 1 coulomb per second.
Resistance is a measure of, well, resistance! Current doesn't flow through wires or anything else completely freely and a certain amount of energy is lost along the way. Resistance is measured in ohms (the symbol being the Greek letter omega Ω). If you connect a 1V power supply to a wire and obtain a current of 1A then the wire has a resistance of 1Ω.
The volts_amps_ohms function shown below implements Ohm's Law.
def volts_amps_ohms():
'''
Ohm's Law
'''
voltage = ft.Quantity("Voltage", "V", "Volt", "V")
current = ft.Quantity("Current", "I", "Amp", "A")
resistance = ft.Quantity("Resistance", "R", "Ohm", "Ω")
ft.output(voltage, current, resistance)
# set I & R, and calculate V
I = 1.5
R = 6.0
V = ft.evaluate(float('nan'), I, R)
print()
print(f"I = {I}A")
print(f"R = {R}Ω")
print(f"V = {V}V")
# set V & R, and calculate I
V = 9.0
R = 6.0
I = ft.evaluate(V, float('nan'), R)
print()
print(f"V = {V}V")
print(f"R = {R}Ω")
print(f"I = {I}A")
# set V & I, and calculate R
V = 9.0
I = 1.5
R = ft.evaluate(V, I, float('nan'))
print()
print(f"V = {V}V")
print(f"I = {I}A")
print(f"R = {R}Ω")The overall pattern of functions is the same for all examples. Firstly three named tuples are created for the three quantities used by the formula triangle, and these then passed to the formulatriangle module's output function.
After that variables for each possible pair of quantities are created and passed to the formulatriangle module's evaluate function to calculate the unknown quantity, and all three values are then printed. Note that I've used the same values for each of the three sets of quantities.
Make sure volts_amps_ohms() is uncommented in main and run the program like this:
python3 formulatriangledemo_2.py
This is the output.
After showing details of the quantities, a representation of the formula triangle and individual formulas the actual quantities are shown.
As I mentioned above I've used the same values all the way through, and these are a realistic representation of running a small light bulb from a battery.
The first example calculates the voltage V from the current I and the resistance R. This is the calculation you'd need if you know your bulb uses a current of 1.5A and the circuit has a resistance of 6Ω (which could include a resistor to deliberately cut down the current to that needed by the bulb) and you want to know what voltage battery to use: the answer is 9V.
The second example calculates the current from the voltage and resistance, and could be used to select a suitable bulb which won't blow when wired up to the circuit.
Lastly we calculate the resistance from the voltage and current. This is probably the most useful of the three calculations as resistance is the easiest and most convenient quantity to change. If you have a fixed 9V supply and need to use a bulb drawing 1.5A then you just need to use a 6Ω resistor.
Density
The next triangle shows the relationship between density, mass and volume.
ρ - density in kg/m³ (the symbol is the Greek letter rho)
m - mass in kilograms
V - volume in m³
Density does not have its own named unit so we use a derived unit, ie. one consisting of two or more other units. In this case we use kilograms per metre cubed, or the mass in kg of a cubic metre of the substance.
Mass is measured in kilograms and specifies the amount of matter in a body or sample of a substance. The kilogram is more familiar as a unit of weight, although weight is a result of gravity so such usage is only suitable on Earth. Weight is more generally measured in Newtons as the force exerted by a certain mass under a certain gravity so varies depending on which planet (if any) you happen to be on.
Volume is a measure of the physical dimensions of the sample of a substance assuming it's the shape of a cube, relative to a cubic metre.
Let's now implement the density/mass/volume triangle.
def mass_density_volume():
mass = ft.Quantity("Mass", "m", "Kilogram", "kg")
density = ft.Quantity("Density", "ρ", "Kilograms per cubic metre", "kg/m³")
volume = ft.Quantity("Volume", "V", "Cubic metre", "m³")
ft.output(mass, density, volume)
# set ρ and V, and calculate m
ρ = 19300.0
V = 0.000001
m = ft.evaluate(float('nan'), ρ, V)
print()
print(f"ρ = {ρ:0.0f}kg/m³")
print(f"V = {V:0.6f}m³")
print(f"m = {m:0.4f}kg")
# set m and V, and calculate ρ
m = 0.0193
V = 0.000001
ρ = ft.evaluate(m, float('nan'), V)
print()
print(f"m = {m:0.4f}kg")
print(f"V = {V:0.6f}m³")
print(f"ρ = {ρ:0.0f}kg/m³")
# set m and ρ, and calculate V
m = 0.0193
ρ = 19300.0
V = ft.evaluate(m, ρ, float('nan'))
print()
print(f"m = {m:0.4f}kg")
print(f"ρ = {ρ:0.0f}kg/m³")
print(f"V = {V:0.6f}m³") Uncomment mass_density_volume in main and run the program; this is the output.
If you're wondering what "weighs" nearly 20t per cubic metre the answer is gold! The volume of 0.000001m³ is 1 cubic centimetre (cc). If you had 1cc of water then by definition it would have a mass of 1 gram but as you can see from the output a similar volume of gold has a mass of 0.0193kg or nearly 20g.
I won't belabour the point beyond this current example, but I'll just reiterate the following:
If you know the density ρ and volume V you can calculate the mass m
If you know the mass and volume you can calculate the density
If you know the mass and density you can calculate the volume
Newton's First and Second Laws
This example ties together three simple quantities into one of the most important and profound principles of all physics. These quantities are:
F - force in newtons
m - mass in kilograms
a - acceleration in m/s²
Force is what causes a body (anything from an atom to a planet or even a galaxy) to speed up, slow down or change direction. In more technical terms a force causes a change in velocity which is a two-part quantity consisting of both speed and direction.
There are only four fundamental forces, two of them being the weak and strong forces which are only relevant at subatomic levels. That leaves us gravity and electromagnetism to deal with using the formulas in this example, and which of these forces or combination of forces you apply the formulas to is of no importance: they work exactly the same for both.
The newton is not a familiar unit outside of science and technology so to get a feel for it lets break it down into its constituent units. A force of 1 newton or 1N causes a mass of 1kg to accelerate by 1m/s², so if you push something with a mass of 1kg (say a 1 litre bottle of water) with a force of 1N it will be moving at 1m/s after 1 second, 2m/s after 2 seconds and so on. (This article doesn't go into Newton's Third Law but I'll just mention that it shows that the force you feel while pushing the bottle of water is also 1N.)
Mass can simplistically be defined as the amount of matter in a body but more accurately and usefully for our purposes it is the resistance to change in velocity, ie.speeding up, slowing down or changing direction. This makes perfect sense: the bigger the bottle of water the harder you have to push it to make it move.
Mass is measured in kilograms which confusingly is used in everyday life for measuring weight. Mass and weight are two different things, weight being the force exerted by a body due to gravity. Being a force, weight is measured in newtons and varies depending on what planet (if any) you are on. Most of us are going to be stranded on Earth for the foreseeable future, so for practical purposes we can consider the weight of a certain mass to be constant and can therefore get away with using kilograms for weight.
Acceleration is commonly used to mean an increase in speed but its actual meaning is a change in speed or direction. As I mentioned above these two quantities combined constitute velocity therefore acceleration is a change in velocity and is measured in m/s², perhaps most descriptively expressed as "metres per second per second".
Before looking at the code it's necessary to gain a basic understanding of Newton's First and Second Laws of Motion, and also to understand the connection between them.
Let's start with the second which is most frequently expressed by the formula F = ma, or in prose such as "a body's acceleration is proportional to the net force acting on it, and inversely proportional to its mass". The harder you push something the more it accelerates, but the heavier it is the less effect your push will have. Common sense isn't it?!
Now let's look at Newton's First Law of Motion: a body remains stationary or moves at a constant velocity (remember: velocity is speed AND direction) unless a force causes it to do otherwise. This is pretty much impossible to demonstrate on earth as everything you give a push to will eventually stop due to various sources of friction from the ground, the air or whatever. Our cars, trains and aircraft require a constant source of propulsion.
Not everything made by humankind needs a constant push though: the Pioneer 10 space probe, its rockets having given it an initial shove, will keep moving forever. (OK, it will probably be affected by tiny amounts of interstellar dust and might just hit something a lot bigger but it's the best example of Newton's First we have.)
Have you spotted the connection between Newton's first two laws? It is that if you apply one of the variations of the second law formulas, a = F/m, with a force of 0N you get an acceleration of 0. The First Law is no more than a special case of the Second Law with no force!
Now let's look at the code.
The force_mass_acceleration Function
def force_mass_acceleration():
'''
Newton's Second Law of Motion
'''
force = ft.Quantity("Force", "F", "Newton", "N")
mass = ft.Quantity("Mass", "m", "Kilogram", "kg")
acceleration = ft.Quantity("Acceleration", "a", "Metre per second squared", "m/s²")
ft.output(force, mass, acceleration)
# set m and a, calculate F
m = 1600.0
a = 3.0
F = ft.evaluate(float('nan'), m, a)
print()
print(f"m = {m}kg")
print(f"a = {a}m/s²")
print(f"F = {F}N")
# set F and a, calculate m
F = 4800.0
a = 3.0
m = ft.evaluate(F, float('nan'), a)
print()
print(f"F = {F}N")
print(f"a = {a}m/s²")
print(f"m = {m}kg")
# set F and m, calculate a
F = 4800.0
m = 1600.0
a = ft.evaluate(F, m, float('nan'))
print()
print(f"F = {F}N")
print(f"m = {m}kg")
print(f"a = {a}m/s²")The pattern is familiar by now so I won't go through it unnecessarily except to say that the numbers are intended to represent a car of average mass and power accelerating. Run the code which will give you this output.
If you want to apply the formulas to Newton's First Law then just change a or F to 0.
I've gone into more detail with the descriptions than with the other examples but what I have written would only be Chapter 1, page 1 of a long book on Newtonian Mechanics. Bear in mind that most of the time a body has two or more forces acting on it and it's necessary to calculate from them one single net force before working out how that force changes the body's velocity. In the formula triangle remember that F is the net force, often know as the resultant force as it's the result of combining several others.
What Is the Wavelength of My Wave?
This example examines waves, and specifically sound waves. The same arithmetic applies to light waves which is a complex topic I'll look at in more detail in a future article. The three quantities used are:
v - speed in m/s
f - frequency in hertz
λ - wavelength in m (the symbol is the Greek letter lambda)
In air the speed of sound is approximately constant, varying only slightly with temperature. The frequency and wavelength however can vary, and as one increases the other decreases and vice versa. There is a one to one correspondence and if you know one and the speed you can calculate the other, which is exactly what we'll do.
The human ear (or actually both of them!) can detect sounds between about 20Hz and 20,000Hz and we all have an intuitive understanding of "low-pitch" and "high-pitch" sounds. The one I have chosen for this example is 261.63Hz which is middle C. If you have a piano handy go and bash the middle C key just to give yourself a bit of a break from this long and rather demanding article.
This is the formula triangle describing the relationship between our three quantities.
And this is the code which doesn't present any surprises.
speed_wavelength_frequency Function
def speed_wavelength_frequency():
speed = ft.Quantity("Speed", "v", "Metres per second", "m/s")
frequency = ft.Quantity("Frequency", "f", "Hertz", "Hz")
wavelength = ft.Quantity("Wavelength", "λ", "Metre", "m")
ft.output(speed, frequency, wavelength)
# set f and λ, calculate V
f = 261.63
λ = 1.261323243
v = ft.evaluate(float('nan'), f, λ)
print()
print(f"f = {f}Hz")
print(f"λ = {λ}m")
print(f"v = {v:0.0f}m/s")
# set v and λ, calculate f
v = 330
λ = 1.261323243
f = ft.evaluate(v, float('nan'), λ)
print()
print(f"v = {v:0.0f}m/s")
print(f"λ = {λ}m")
print(f"f = {f}Hz")
# set v and f, calculate λ
v = 330
f = 261.63
λ = ft.evaluate(v, f, float('nan'))
print()
print(f"v = {v:0.0f}m/s")
print(f"f = {f}Hz")
print(f"λ = {λ}m") As I mentioned above I've used the middle C value for the frequency of 261.63Hz which corresponds to the wavelength of 1.26m (2dp). The speed of sound in air is the generally accepted value for a temperature of 0°C. Sound travels faster in warmer temperatures as the air is less dense and therefore the molecules can vibrate more easily.
Run the code which will give you this output. If you want to try out other values remember that audible sound for humans is about 20Hz and 20,000Hz but other animals can hear sounds outside that range. Also, you might prefer a more comfortable temperature of 20°C where sound travels a bit faster, 343m/s in fact.
Transfer of Energy
The final example involves a crane lifting its load using energy and power. That might sound straightforward but it involves thinking about exactly what energy and power are, and the relationship between them. First though let's look at our three quantities.
E - energy in joules
P - power in watts
t - time in seconds
You know what time is so I'll concentrate on explaining energy and power.
Energy
Energy is a quantity which is able to create a force causing a change in a physical system. In short, it's what makes things happen. There are many forms of energy and the "making things happen" I mentioned in the previous sentence occurs when energy is transformed from one type to another, a process given the rather mundane name of work *.
The SI unit of energy is the joule, named after the 19th century English physicist James Prescott Joule. This was a time when steam engines powered the world and people were working hard to understand the scientific principles behind machines that had been developed by trial and error.
The joule is a derived SI unit which means it is constructed from other more fundamental units. While it's good to see Joule's name immortalised in this way it does obscure the underlying units and the hints they provide. There are many ways of defining a joule in terms of other units, each relevant to different situations. The one most useful in our crane example is the newton metre (N⋅m) which defines a joule as the work done when a force of one newton causes a mass to move 1 metre.
* This is well beyond the scope of the article but you might like to note that energy can never be "used up", just transferred from one form to another, including to and from matter.
Power
The amount of energy needed for a specific change in a physical system is always the same however long the task takes. Variations in the time taken are caused by the rate at which the energy is transferred, and this rate is known as power. The SI unit of power is the watt, named after the Scottish engineer James Watt, a leading light in the Industrial Revolution. One watt is the transfer of 1 joule per second, and the higher the power or wattage of our crane the faster it can lift its load.
The Formula
Having got our heads round energy and power, and their relationship with time, let's look at how we can calculate each one from the other two.
energy_power_time Function
def energy_power_time():
energy = ft.Quantity("Energy", "E", "Joule", "J")
power = ft.Quantity("Power", "P", "Watt", "W")
time = ft.Quantity("Time", "t", "Second", "s")
ft.output(energy, power, time)
# set P and t, calculate E
P = 2450.0
t = 30.0
E = ft.evaluate(float('nan'), P, t)
print()
print(f"P = {P}W")
print(f"t = {t}s")
print(f"E = {E}J")
# set E and t, calculate P
E = 73500
t = 30
P = ft.evaluate(E, float('nan'), t)
print()
print(f"E = {E}J")
print(f"t = {t}s")
print(f"P = {P}W")
# set E and P, calculate t
E = 73500
P = 2450.0
T = ft.evaluate(E, P, float('nan'))
print()
print(f"E = {E}J")
print(f"P = {P}W")
print(f"t = {t}s") The numbers used in this example roughly approximate the task of lifting a 500kg load 15m (say lifting a steel girder to the top of a building) in 30 seconds using a crane with a 2,450 watt motor. As ever I've coded the function to calculate each of the three quantities from the other two.
This is just one example of energy use, and the same formula triangle can be used for very different applications such as heating water. If you want to try this out you'll need to know that it takes 4,184J to heat 1kg (ie. 1 litre) by 1°C.
Conclusion
I mentioned at the beginning of Part 1 that many people assume that calculations in fields such as physics and engineering are extremely complex, understandable only by a small elite. I hope this pair of articles has convinced you that many useful and practical calculations are extremely simple and involve only very basic arithmetic.
If you can think up any further examples, and I am sure there are many, please let me know. You might also like to fork the repository and add them, following the pattern of the functions in this article.













