Loops

This notebook follows on in many ways from the functions notebook. The aim here is to show the utility of loops in Python programming. I will again endevour to use examples from chemistry related problems, but occasionally examples from physics or mathematics will come through.

As is the case with many aspects of programming the propose of a loop is to allow the programmer to write less code. This leads to the idiom that computers are really good at doing the same thing over and over, much better than humans.

A loop really is just that, a way to tell the computer to perform a task multiple times over.

The Pythonic way to have a loop is:

for i in array: operation

There are a few things here that need described.

  • for This tells the computer that you are wanting something to be looped through
  • i This is the iterator, it will become more clear the utility of this in later examples
  • array This is some array of objects that is to be itereated through. For each iteration the operation is performed.

Lets have a look at some examples.

In [ ]:
for i in range(0, 10):
    print('Hello World!')

This example says for i in the range 0 to 10 (including zero but not ten) print the string Hello World!.

The result is that the string is printed 10 times, once for each of the numbers 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. Essentially, i is counting from 0 to 9 and printing the string each time.

This is more clear if we include i in the string.

In [ ]:
for i in range(0, 10):
    print('Hello World {}!'.format(i))

Of course, the array doesn't just have to be a series of continuous integers. We can have really any type of array.

In [ ]:
array1 = [2.4, 6.7, 3.0, 8.2, 2.7, 7.4]
for i in array1:
    print(i)

And the iterator need not always be called i. This is just a convention in programming.

In [ ]:
array2 = ['dog', 'horse', 'bear', 'lion', 'camel']
for animal in array2:
    print(animal)

The examples above are all quite trival, lets have a look at something a bit more applicable. If you have looked at the functions notebook this example will be familiar.

It is the calculation of the equilibrium constant for the following reaction at a series of temperatures, from 300 K to 350 K in 10 K increaments.

$$\text{CH}_4\text{(g)} + 2\text{O}_2\text{(g)} \rightarrow \text{CO}_2\text{(g)} + 2\text{H}_2\text{O(l)} $$
Component $\Delta_fH$/kJmol$^{-1}$ $_rS$/kJmol$^{-1}$
CH$_4$ -74.8 0.1862
O$_2$ 0 0.2050
CO$_2$ -393.5 0.2136
H$_2$O -285.8 0.0699

The first thing we need it the function to calculate the equilibrium constant.

In [ ]:
import numpy as np
from scipy.constants import R

def equilibrium_constant(deltaH_products, deltaH_reactants, S_products, S_reactants, T):
    deltarH = np.sum(deltaH_products) - np.sum(deltaH_reactants)
    deltarS = np.sum(S_products) - np.sum(S_reactants)
    Gibbs_free_energy = deltarH - T * deltarS
    K = np.exp(-1 * Gibbs_free_energy/(R * 1e-3 *T))
    return K

And the range of temperatures.

In [ ]:
temperatures = [300., 310., 320., 330., 340., 350.]

Then we can make use of the loop as follows.

In [ ]:
deltaH_products = [-393.5, -285.8 * 2]
deltaH_reactants = [-74.8, 0 * 2]
S_products = [0.2136, 0.0699, 0.0699]
S_reactants = [0.1862, 0.2050, 0.2050]

for T in temperatures:
    K = equilibrium_constant(deltaH_products, deltaH_reactants, S_products, S_reactants, T)
    print('K @ {:.0f} K = {:.3e}'.format(T, K))

This procedure can be achieved for any range of temperatures, using the np.arange function. The below example also shows how the enumerate function can be utilised to count through the loops.

In [ ]:
temperatures = np.arange(300, 400, 20)

deltaH_products = [-393.5, -285.8 * 2]
deltaH_reactants = [-74.8, 0 * 2]
S_products = [0.2136, 0.0699, 0.0699]
S_reactants = [0.1862, 0.2050, 0.2050]

for i, T in enumerate(temperatures):
    K = equilibrium_constant(deltaH_products, deltaH_reactants, S_products, S_reactants, T)
    print('{}. K @ {:.0f} K = {:.3e}'.format(i+1, T, K))
In [ ]: