diff --git a/notebooks/MultiFluidTutorial.ipynb b/notebooks/MultiFluidTutorial.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..18cedf2f0f3ce256849f6620024eb84bbe68f511
--- /dev/null
+++ b/notebooks/MultiFluidTutorial.ipynb
@@ -0,0 +1,262 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Anatomy of a multi-fluid model load\n",
+    "\n",
+    "Peering into the innards of teqp"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 51,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import timeit, json\n",
+    "import pandas\n",
+    "import numpy as np\n",
+    "import teqp"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Pure fluid loading"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 52,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "9 ms ± 422 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
+     ]
+    }
+   ],
+   "source": [
+    "# By default teqp looks for fluids relative to the set of fluids in ROOT/dev/fluids\n",
+    "# The name (case-sensitive) should match the .json file, without the json extension.\n",
+    "%timeit model = teqp.build_multifluid_model([\"Methane\", \"Ethane\"], teqp.get_datapath())"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 53,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "82.3 ms ± 431 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n"
+     ]
+    }
+   ],
+   "source": [
+    "# And if you provide valid aliases, alias lookup will be used to resolve the name\n",
+    "# But beware, this is rather a lot slower than the above because all fluid files need to be read\n",
+    "# in to build the alias map\n",
+    "%timeit model = teqp.build_multifluid_model([\"n-C1H4\", \"n-C3H8\"], teqp.get_datapath())"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "So, how to make it faster? Only do it once and cache"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 54,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "71.1 ms ± 226 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n"
+     ]
+    },
+    {
+     "data": {
+      "text/plain": [
+       "dict"
+      ]
+     },
+     "execution_count": 54,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "# Here is the set of possible aliases to absolute paths of files\n",
+    "# Building this map takes a little while (somewhat faster in C++) due to all the file reads\n",
+    "# If you know your files will not change, good idea to build this alias map yourself.\n",
+    "%timeit aliasmap = teqp.build_alias_map(teqp.get_datapath())\n",
+    "type(aliasmap)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 55,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "8.93 ms ± 203 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
+     ]
+    }
+   ],
+   "source": [
+    "# Then load the absolute paths from the alias map, \n",
+    "# which will guarantee that you hit exactly what you were looking for,\n",
+    "# resolving aliases as needed\n",
+    "identifiers = [aliasmap[n] for n in [\"Methane\", \"Ethane\"]]\n",
+    "%timeit model = teqp.build_multifluid_model(identifiers, teqp.get_datapath())"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "At some point soon teqp will support in-memory loading of JSON data for the pure components, without requiring reads from the operating system"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Mixture model loading"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 62,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Load the default JSON for the binary interaction parameters\n",
+    "BIP = json.load(open(teqp.get_datapath()+'/dev/mixtures/mixture_binary_pairs.json'))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 63,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'BibTeX': 'Kunz-JCED-2012',\n",
+       " 'CAS1': '74-82-8',\n",
+       " 'CAS2': '74-84-0',\n",
+       " 'F': 1.0,\n",
+       " 'Name1': 'Methane',\n",
+       " 'Name2': 'Ethane',\n",
+       " 'betaT': 0.996336508,\n",
+       " 'betaV': 0.997547866,\n",
+       " 'function': 'Methane-Ethane',\n",
+       " 'gammaT': 1.049707697,\n",
+       " 'gammaV': 1.006617867}"
+      ]
+     },
+     "execution_count": 63,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "# You can obtain interaction parameters either by pairs of names, where name is the name that teqp uses, the [\"INFO\"][\"NAME\"] field\n",
+    "params, swap_needed = teqp.get_BIPdep(BIP, ['Methane','Ethane'])\n",
+    "params"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 64,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'BibTeX': 'Kunz-JCED-2012',\n",
+       " 'CAS1': '74-82-8',\n",
+       " 'CAS2': '74-84-0',\n",
+       " 'F': 1.0,\n",
+       " 'Name1': 'Methane',\n",
+       " 'Name2': 'Ethane',\n",
+       " 'betaT': 0.996336508,\n",
+       " 'betaV': 0.997547866,\n",
+       " 'function': 'Methane-Ethane',\n",
+       " 'gammaT': 1.049707697,\n",
+       " 'gammaV': 1.006617867}"
+      ]
+     },
+     "execution_count": 64,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "# Or also by CAS#\n",
+    "params, swap_needed = teqp.get_BIPdep(BIP, ['74-82-8','74-84-0'])\n",
+    "params"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 48,
+   "metadata": {},
+   "outputs": [
+    {
+     "ename": "ValueError",
+     "evalue": "Can't match the binary pair for: 74-82-8/Ethane",
+     "output_type": "error",
+     "traceback": [
+      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[1;31mValueError\u001b[0m                                Traceback (most recent call last)",
+      "\u001b[1;32m<ipython-input-48-cb81a483843f>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[1;31m# But mixing is not allowed\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0mparams\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mswap_needed\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mteqp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget_BIPdep\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mBIP\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;34m'74-82-8'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;34m'Ethane'\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m      3\u001b[0m \u001b[0mparams\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
+      "\u001b[1;31mValueError\u001b[0m: Can't match the binary pair for: 74-82-8/Ethane"
+     ]
+    }
+   ],
+   "source": [
+    "# But mixing is not allowed\n",
+    "params, swap_needed = teqp.get_BIPdep(BIP, ['74-82-8','Ethane'])\n",
+    "params"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.8.5"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}