Stoichiometry - Part 1#

As seen in the first lecture, stoichiometry is one of the pillars of Chemical Reaction Engineering.

In Python, we will divide the topics into two parts:

  • Part 1 will cover simple mole-mole calculations, mass-mass reactions and finally provide a solution for balancing coefficients

  • Part 2 will focus on the application of the stoichiometric table to Batch Reactors and Flow Systems.

Mole-mole calculations in Python#

Given a balanced reaction, we want to write a function to where calculate how many moles of a molecule B are needed to react with a given amount of moles A.

Given the following reaction:

\(3H_2 + N_2 → 2NH_3\)

In Python, we can do the following:

#we multiply the moles of A by the ratio of what needs to be found and what is given
# so moles A*coefficient B/coefficient A = moles B
def mole_mole_calculation(moles_A, coeff_A, coeff_B):
    """
    This function calculates how many moles of a compound B are needed to the given moles of A.
    To achieve this, we multiply the given moles of A by the ratio 
    of what needs to be found (coeff B) and what is given (coeff A).
    So moles B needed = moles A* coefficient B/coefficient A.
    Input: 
        moles A, coeff_A, coeff_B
    Output: 
        moles B
    """
    return moles_A*(coeff_B/coeff_A)

A_moles = 7.5 # mol
coeff_A = 3
coeff_B = 1
B_moles = mole_mole_calculation(A_moles, coeff_A, coeff_B)
print(f'{B_moles} mols of N2 are needed to react with 7.5 mols of H2, since they have a 1:3 ratio')
2.5 mols of N2 are needed to react with 7.5 mols of H2, since they have a 1:3 ratio

Exercise: How many moles of H2 are needed to produce 0.8 moles NH3?

Level: Easy.

A_moles = 0.8 # mol
coeff_A = 2
coeff_B = 3
B_moles = mole_mole_calculation(A_moles, coeff_A, coeff_B)
print(f'{round(B_moles, 2)} mols of H2 are needed to react with 0.8 mols of NH3')
1.2 mols of H2 are needed to react with 0.8 mols of NH3

Exercise: Given the methane reaction: \( CH_4 + 2O_2 → CO_2 + 2H_2O \), use the given function to calculate how many moles of O_2 are needed to produce 0.6 moles H_2O.

Level: Easy.

A_moles = 0.6 # mol
coeff_A = 2
coeff_B = 2
B_moles = mole_mole_calculation(A_moles, coeff_A, coeff_B)
print(f'{round(B_moles, 2)} mols of O2 are needed to react with 0.6 mols of H2O')
0.6 mols of O2 are needed to react with 0.6 mols of H2O

Mass-mass reactions in Python#

How many grams of NH_3 is produced if you react 42 g of N_2?

def mass_mass_calculation(mass_A, molar_mass_A, molar_mass_B, coeff_A, coeff_B):
    """
    This function calculates how many moles of a compound B are needed to the given moles of A.
    To achieve this, we multiply the given mass of A by 1/molar mass of A,
    then multiply the calculated moles of A by the ratio of what needs to be found (coeff B) and what is given (coeff A).
    inally, the mass of B is given by the product of the calculated moles of B by molar mass of B.
    Input: 
        mass_A, molar_mass_A, molar_mass_B, coeff_A, coeff_B
    Output: 
        mass B
    """
    # convert mass of N2 to moles of N2 using the molar mass of N2
    moles_A = mass_A*(1/molar_mass_A) # 1 mol N2/ g N2
    
    # mole-mole calculation
    moles_B = moles_A*(coeff_B/coeff_A)
    
    # convert moles of ammonia to mass of ammonia using the molar mass of ammonia
    mass_B = moles_B*(molar_mass_B) # g NH3/ 1 mol NH3
    return mass_B

mass_A = 42 # g N2
molar_mass_A = 28 # g N2 in 1 mol of N2
molar_mass_B = 17 # g NH3 in 1 mol of NH3
coeff_A = 1
coeff_B = 2
mass_B = mass_mass_calculation(mass_A, molar_mass_A, molar_mass_B, coeff_A, coeff_B)
print(f'{mass_B} grams of NH3 produced from reacting 42 g of N2')
51.0 grams of NH3 produced from reacting 42 g of N2

How to balance coefficients in Python#

Take some time to investigate and understand the code below. Try to take the code apart and verify what each function is doing. Once you understand the code, try to see if you can simplify it.

Suggested readings:

# code adapted from https://medium.com/swlh/balancing-chemical-equations-with-python-837518c9075b

import re
from sympy import Matrix, lcm

element_list = []
element_matrix = []
reaction = 'H2 + N2 -> NH3'
reactants = reaction.split("->")[0].replace(' ', '').split("+")
products = reaction.split("->")[1].replace(' ', '').split("+")

def add_matrix(element, index, count, side):
    if(index == len(element_matrix)):
        element_matrix.append([])
        for x in element_list:
            element_matrix[index].append(0)
    if(element not in element_list):
        element_list.append(element)
        for i in range(len(element_matrix)):
            element_matrix[i].append(0)
    column = element_list.index(element)
    element_matrix[index][column] += count*side
    
def find_elements(segment, index, side):
    elements_numbers=re.split('([A-Z][a-z]?)',segment)
    i=0
    while(i < len(elements_numbers)-1):#last element always blank
        i += 1
        if(len(elements_numbers[i]) > 0):
            if(elements_numbers[i+1].isdigit()):
                count = int(elements_numbers[i+1])
                add_matrix(elements_numbers[i], index, count, side)
                i+=1
            else:
                add_matrix(elements_numbers[i], index, 1, side)        
            
for i in range(len(reactants)):
    find_elements(reactants[i], i, 1)
    
for i in range(len(products)):
    find_elements(products[i], i+len(reactants), -1)

# use Matrix function from sympy to convert list of lists to matrix
element_matrix = Matrix(element_matrix)
# transpose matrix vertically
element_matrix = element_matrix.transpose()
# nullspace or kernel mapping
solution = element_matrix.nullspace()[0]
# find the least common multiple (smallest positive integer that is divisible by the found coefficients)
multiple = lcm([val.q for val in solution])
# multiply solution my lcm
solution = multiple*solution
coeff = solution.tolist()
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Cell In[5], line 4
      1 # code adapted from https://medium.com/swlh/balancing-chemical-equations-with-python-837518c9075b
      3 import re
----> 4 from sympy import Matrix, lcm
      6 element_list = []
      7 element_matrix = []

ModuleNotFoundError: No module named 'sympy'

Once we balanced the reaction, we can print it in a nice form. This is what the following code is doing.

# assign the found coefficients to the reactants
output = ""
for i in range(len(reactants)):
    output += str(coeff[i][0])+reactants[i]
    if i < len(reactants)-1:
        output += " + "

# assign the found coefficients to the reactants
output += " -> "
for i in range(len(products)):
    output += str(coeff[i+len(reactants)][0])+products[i]
    if i < len(products)-1:
        output += " + "
        
# print the final reaction
print(output)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[6], line 3
      1 # assign the found coefficients to the reactants
      2 output = ""
----> 3 for i in range(len(reactants)):
      4     output += str(coeff[i][0])+reactants[i]
      5     if i < len(reactants)-1:

NameError: name 'reactants' is not defined