The BurnMan Tutorial

Part 2: The Composition Class

This file is part of BurnMan - a thermoelastic and thermodynamic toolkit for the Earth and Planetary Sciences

Copyright (C) 2012 - 2021 by the BurnMan team, released under the GNU GPL v2 or later.


This ipython notebook is the second in a series designed to introduce new users to the code structure and functionalities present in BurnMan.


  1. burnman.Composition: Defining Composition objects, converting between molar, weight and atomic amounts, changing component bases. and modifying compositions.

Everything in BurnMan and in this tutorial is defined in SI units.

The Composition class

It is quite common in petrology to want to perform simple manipulations on chemical compositions. These manipulations might include: - converting between molar and weight percent of oxides or elements - changing from one compositional basis to another (e.g. ‘FeO’ and ‘Fe2O3’ to ‘Fe’ and ‘O’) - adding new chemical components to an existing composition in specific proportions with existing components.

These operations are easy to perform in Excel (for example), but errors are surprisingly common, and are even present in published literature. BurnMan’s Composition class is designed to make some of these common tasks easy and hopefully less error prone. Composition objects are initialised with a dictionary of component amounts (in any format), followed by a string that indicates whether that composition is given in “molar” amounts or “weight” (more technically mass, but weight is a more commonly used word in chemistry).

from burnman import Composition

olivine_composition = Composition({'MgO': 1.8,
                                   'FeO': 0.2,
                                   'SiO2': 1.}, 'molar')
Warning: No module named 'cdd'. For full functionality of BurnMan, please install pycddlib.

After initialization, the “print” method can be used to directly print molar, weight or atomic amounts. Optional variables control the print precision and normalization of amounts.

olivine_composition.print('molar', significant_figures=4,
                          normalization_component='SiO2', normalization_amount=1.)
olivine_composition.print('weight', significant_figures=4,
                          normalization_component='total', normalization_amount=1.)
olivine_composition.print('atomic', significant_figures=4,
                          normalization_component='total', normalization_amount=7.)
Molar composition
FeO: 0.2000
MgO: 1.8000
SiO2: 1.0000
Weight composition
FeO: 0.0977
MgO: 0.4935
SiO2: 0.4087
Atomic composition
Fe: 0.2000
Mg: 1.8000
O: 4.0000
Si: 1.0000

Let’s do something a little more complicated. When we’re making a starting mix for petrological experiments, we often have to add additional components. For example, we add iron as Fe2O3 even if we want a reduced oxide starting mix, because FeO is not a stable stoichiometric compound.

Here we show how to use BurnMan to create such mixes. In this case, let’s say we want to create a KLB-1 starting mix (Takahashi, 1986). We know the weight proportions of the various oxides (including only components in the NCFMAS system):

KLB1 = Composition({'SiO2': 44.48,
                    'Al2O3': 3.59,
                    'FeO': 8.10,
                    'MgO': 39.22,
                    'CaO': 3.44,
                    'Na2O': 0.30}, 'weight')

However, this composition is not the composition we wish to make in the lab. We need to make the following changes: - \(\text{CaO}\) and \(\text{Na}_2\text{O}\) should be added as \(\text{CaCO}_3\) and \(\text{Na}_2\text{CO}_3\). - \(\text{FeO}\) should be added as \(\text{Fe}_2\text{O}_3\)

First, we change the bulk composition to satisfy these requirements. The molar amounts of the existing components are stored in a dictionary “molar_composition”, and can be used to determine the amounts of CO2 and O to add to the bulk composition:

CO2_molar = KLB1.molar_composition['CaO'] + KLB1.molar_composition['Na2O']
O_molar = KLB1.molar_composition['FeO']*0.5

KLB1.add_components(composition_dictionary = {'CO2': CO2_molar,
                                              'O': O_molar},
                    unit_type = 'molar')

Then we can change the component set to the oxidised, carbonated compounds and print the desired starting compositions, for 2 g total mass:

KLB1.change_component_set(['Na2CO3', 'CaCO3', 'Fe2O3', 'MgO', 'Al2O3', 'SiO2'])
KLB1.print('weight', significant_figures=4, normalization_amount=2.)
Weight composition
Al2O3: 0.0697
CaCO3: 0.1193
Fe2O3: 0.1749
MgO: 0.7620
Na2CO3: 0.0100
SiO2: 0.8642

And that’s it! The next tutorial will be on making Layer and Planet objects for planetary science applications.