{
“cells”: [
{

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“# Thermo property packages”

]

}, {

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“A [Thermo](../Thermo.txt) object defines a thermodynamic property package. To build a Thermo object, we must first define all the chemicals involed. In the following example, we create a property package that [BioSTEAM](https://biosteam.readthedocs.io/en/latest/) can use to model the co-production of biodiesel and ethanol from lipid-cane [[1-2]](#References).n”, “n”, “![](./lipidcane_areas.png "Lipid-cane diagram")”

]

}, {

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“### Creating chemicals”

]

}, {

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“We can first start by defining the common chemicals already in the data base:”

]

}, {

“cell_type”: “code”, “execution_count”: 1, “metadata”: {}, “outputs”: [], “source”: [

“import thermosteam as tmon”, “Biodiesel = tmo.Chemical(‘Biodiesel’,n”, ” search_ID=’Methyl oleate’)n”, “lipidcane_chemicals = tmo.Chemicals(n”, ” [‘Water’, ‘Methanol’, ‘Ethanol’, ‘Glycerol’,n”, ” ‘Glucose’, ‘Sucrose’, ‘H3PO4’, ‘P4O10’, ‘CO2’,n”, ” ‘Octane’, ‘O2’, Biodiesel])n”, “n”, “(Water, Methanol, Ethanol,n”, ” Glycerol, Glucose, Sucrose,n”, ” H3PO4, P4O10, CO2, Octane, O2, Biodiesel) = lipidcane_chemicals”

]

}, {

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“We can assume that CO2 and O2 will always remain a gas in the process by setting the state:”

]

}, {

“cell_type”: “code”, “execution_count”: 2, “metadata”: {}, “outputs”: [], “source”: [

“O2.at_state(phase=’g’)n”, “CO2.at_state(phase=’g’)”

]

}, {

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“Similarly, we can assume glucose, sucrose, and phosphoric acid all remain as solids:”

]

}, {

“cell_type”: “code”, “execution_count”: 3, “metadata”: {}, “outputs”: [], “source”: [

“H3PO4.at_state(phase=’s’)n”, “P4O10.at_state(phase=’s’)n”, “Glucose.at_state(phase=’s’)n”, “Sucrose.at_state(phase=’s’)”

]

}, {

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“Now we can define the solids in the process (both soluble and insoluble). We can use the Chemical.blank method to create a "blank" Chemical object and add the thermo models ourselves:”

]

}, {

“cell_type”: “code”, “execution_count”: 4, “metadata”: {}, “outputs”: [], “source”: [

“def create_new_chemical(ID, phase=’s’, **constants):n”, ” # Create a new solid chemical without any datan”, ” solid = tmo.Chemical.blank(ID, phase=phase, **constants)n”, ” n”, ” # Add chemical to the Chemicals objectn”, ” lipidcane_chemicals.append(solid)n”, ” n”, ” return solidn”, “n”, “# Cellulose and hemicellulose are modeledn”, “# as their monomer minus on H2O.n”, “Cellulose = create_new_chemical(‘Cellulose’,n”, ” formula="C6H10O5", # Hydrolyzed glucose monomern”, ” Hf=-975708.8)n”, “Hemicellulose = create_new_chemical(‘Hemicellulose’,n”, ” formula="C5H8O5", # Hydrolyzed xylose monomern”, ” Hf=-761906.4)n”, “Flocculant = create_new_chemical(‘Flocculant’, MW=1.)n”, “# Lignin is modeled as vanillin.n”, “Lignin = create_new_chemical(‘Lignin’,n”, ” formula=’C8H8O3’, # Vanillinn”, ” Hf=-452909.632)n”, “Ash = create_new_chemical(‘Ash’, MW=1.)n”, “Solids = create_new_chemical(‘Solids’, MW=1.)n”, “DryYeast = create_new_chemical(‘DryYeast’, MW=1., CAS=’Yeast’)n”, “NaOCH3 = create_new_chemical(‘NaOCH3’, formula=’NaOCH3’)n”, “CaO = create_new_chemical(‘CaO’, formula=’CaO’)n”, “HCl = create_new_chemical(‘HCl’, formula=’HCl’)n”, “NaOH = create_new_chemical(‘NaOH’, formula=’NaOH’)”

]

}, {

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“Note that we are still missing the lipid, modeled as Triolein. However, Triolein is not in the data bank, so let’s start making it from scratch:”

]

}, {

“cell_type”: “code”, “execution_count”: 5, “metadata”: {}, “outputs”: [], “source”: [

“Lipid = create_new_chemical(n”, ” ‘Lipid’,n”, ” phase=’l’,n”, ” Hf=-2193.7e3,n”, ” formula = ‘C57H104O6’,n”, “)”

]

}, {

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“Instead of creating new models based on external sources, here we will approximate Triolein with the properties of Tripalmitin (which does exist in the data bank):”

]

}, {

“cell_type”: “code”, “execution_count”: 6, “metadata”: {}, “outputs”: [], “source”: [

“Tripalmitin = tmo.Chemical(‘Tripalmitin’).at_state(phase=’l’, copy=True)n”, “Lipid.copy_models_from(Tripalmitin, [‘V’, ‘sigma’, ‘kappa’, ‘Cn’])”

]

}, {

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“All what is left is to fill the chemical properties. This done through the add_model method of the chemical model handles. Let’s begin with the solids using data from [[2-4]](#References):”

]

}, {

“cell_type”: “code”, “execution_count”: 7, “metadata”: {}, “outputs”: [

{
“data”: {
“text/plain”: [

“1.1”

]

}, “execution_count”: 7, “metadata”: {}, “output_type”: “execute_result”

}

], “source”: [

“from thermosteam import functional as fnn”, “n”, “# Assume a constant volume for lipidn”, “lipid_molar_volume = fn.rho_to_V(rho=900, MW=Lipid.MW)n”, “Lipid.V.add_model(lipid_molar_volume)n”, “n”, “# Insolubles occupy a significant volumen”, “insoluble_solids = (Ash, Cellulose, Hemicellulose,n”, ” Flocculant, Lignin, Solids, DryYeast, P4O10)n”, “for chemical in insoluble_solids:n”, ” V = fn.rho_to_V(rho=1540, MW=chemical.MW)n”, ” chemical.V.add_model(V, top_priority=True)n”, “n”, “# Solubles don’t occupy much volumen”, “soluble_solids = (CaO, HCl, NaOH, H3PO4, Sucrose, Glucose) n”, “for chemical in soluble_solids:n”, ” V = fn.rho_to_V(rho=1e5, MW=chemical.MW)n”, ” chemical.V.add_model(V, top_priority=True)n”, “n”, “n”, “# Assume sodium methoxide has some of the same properities as methanoln”, “LiquidMethanol = Methanol.at_state(phase=’l’, copy=True)n”, “NaOCH3.copy_models_from(LiquidMethanol, [‘V’, ‘sigma’,’kappa’, ‘Cn’])n”, “n”, “# Add constant models for molar heat capacity of solidsn”, “Ash.Cn.add_model(0.09 * 4.184 * Ash.MW) n”, “CaO.Cn.add_model(1.02388 * CaO.MW) n”, “Cellulose.Cn.add_model(1.364 * Cellulose.MW) n”, “Hemicellulose.Cn.add_model(1.364 * Hemicellulose.MW)n”, “Flocculant.Cn.add_model(4.184 * Flocculant.MW)n”, “Lignin.Cn.add_model(1.364 * Lignin.MW)n”, “Solids.Cn.add_model(1.100 * Solids.MW)n”

]

}, {

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“We don’t care much about the rest of the properties (e.g. thermal conductivity), so we can default them to the values of water:”

]

}, {

“cell_type”: “code”, “execution_count”: 8, “metadata”: {}, “outputs”: [], “source”: [

“for chemical in lipidcane_chemicals: chemical.default()”

]

}, {

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“Finalize the chemicals by compiling:”

]

}, {

“cell_type”: “code”, “execution_count”: 9, “metadata”: {}, “outputs”: [], “source”: [

“lipidcane_chemicals.compile()”

]

}, {

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“This enables methods such as <CompiledChemicals>.array to create chemical data ordered according to the IDs, as well as <CompiledChemicals>.get_index to get the index of a chemical:”

]

}, {

“cell_type”: “code”, “execution_count”: 10, “metadata”: {}, “outputs”: [

{
“data”: {
“text/plain”: [

“array([2., 0., 2., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,n”, ” 0., 0., 0., 0., 0., 0., 0.])”

]

}, “execution_count”: 10, “metadata”: {}, “output_type”: “execute_result”

}

], “source”: [

“lipidcane_chemicals.array([‘Water’, ‘Ethanol’], [2, 2])”

]

}, {

“cell_type”: “code”, “execution_count”: 11, “metadata”: {}, “outputs”: [

{
“data”: {
“text/plain”: [

“[0, 2]”

]

}, “execution_count”: 11, “metadata”: {}, “output_type”: “execute_result”

}

], “source”: [

“lipidcane_chemicals.get_index((‘Water’, ‘Ethanol’))”

]

}, {

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“After compiling, it is possible to set synonyms for indexing:”

]

}, {

“cell_type”: “code”, “execution_count”: 12, “metadata”: {}, “outputs”: [

{

“name”: “stdout”, “output_type”: “stream”, “text”: [

“Watern”

]

}

], “source”: [

“lipidcane_chemicals.set_synonym(‘Water’, ‘H2O’)n”, “print(lipidcane_chemicals.H2O)”

]

}, {

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“### Mixture objects”

]

}, {

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“Before creating a Thermo object, we must define the mixing rules to calculate mixture properties. A Mixture object is able to calculate mixture properties through functors. In this example we will use a function to create a Mixture object with ideal mixing rules:”

]

}, {

“cell_type”: “code”, “execution_count”: 13, “metadata”: {}, “outputs”: [

{

“name”: “stdout”, “output_type”: “stream”, “text”: [

“Mixture(n”, ” rule=’ideal mixing’, …n”, ” include_excess_energies=Falsen”, “)n”

]

}

], “source”: [

“mixture = tmo.mixture.ideal_mixture(lipidcane_chemicals,n”, ” include_excess_energies=False)n”, “mixture.show()”

]

}, {

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“You can use the mixture for estimating mixture properties:”

]

}, {

“cell_type”: “code”, “execution_count”: 14, “metadata”: {}, “outputs”: [

{
“data”: {
“text/plain”: [

“694.8277782515652”

]

}, “execution_count”: 14, “metadata”: {}, “output_type”: “execute_result”

}

], “source”: [

“array = lipidcane_chemicals.arrayn”, “mol = array([‘Water’, ‘Ethanol’], [2, 2])n”, “mixture.H(‘l’, mol, 300, 101325)”

]

}, {

“cell_type”: “code”, “execution_count”: 15, “metadata”: {}, “outputs”: [

{
“data”: {
“text/plain”: [

“376.3037481383151”

]

}, “execution_count”: 15, “metadata”: {}, “output_type”: “execute_result”

}

], “source”: [

“mol = array([‘Water’, ‘Ethanol’], [2, 2])n”, “mixture.Cn(‘l’, mol, 300)”

]

}, {

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“You can also estimate multi-phase mixture properties through methods that start with "x" (e.g. xCn):”

]

}, {

“cell_type”: “code”, “execution_count”: 16, “metadata”: {}, “outputs”: [

{
“data”: {
“text/plain”: [

“574.6441052202636”

]

}, “execution_count”: 16, “metadata”: {}, “output_type”: “execute_result”

}

], “source”: [

“mol_liquid = array([‘Water’, ‘Ethanol’], [2, 2])n”, “mol_vapor = array([‘Water’, ‘Ethanol’], [2, 2])n”, “phase_data = [(‘l’, mol_liquid), (‘g’, mol_vapor)]n”, “mixture.xCn(phase_data, T=300)”

]

}, {

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“Note: To implement a your own Mixture object, you can request help through https://github.com/BioSTEAMDevelopmentGroup/thermosteam.”

]

}, {

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“### Thermo objects”

]

}, {

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“Once the chemicals and mixture objects are finalized, we can compile them into a Thermo object:”

]

}, {

“cell_type”: “code”, “execution_count”: 17, “metadata”: {}, “outputs”: [

{

“name”: “stdout”, “output_type”: “stream”, “text”: [

“Thermo(n”, ” chemicals=CompiledChemicals([Water, Methanol, Ethanol, Glycerol, Glucose, Sucrose, H3PO4, P4O10, CO2, Octane, O2, Biodiesel, Cellulose, Hemicellulose, Flocculant, Lignin, Ash, Solids, DryYeast, NaOCH3, CaO, HCl, NaOH, Lipid]),n”, ” mixture=Mixture(n”, ” rule=’ideal mixing’, …n”, ” include_excess_energies=Falsen”, ” ),n”, ” Gamma=DortmundActivityCoefficients,n”, ” Phi=IdealFugacityCoefficients,n”, ” PCF=IdealPoyintingCorrectionFactorsn”, “)n”

]

}

], “source”: [

“thermo = tmo.Thermo(lipidcane_chemicals, mixture)n”, “thermo.show()”

]

}, {

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“Note that a Thermo object contains ActivityCoefficients, FugacityCoefficients, and PoyintingCorrectionFactors subclasses to define fugacity estimation methods. By default, the Dortmund modified UNIFAC method for estimating activities is selected, while ideal values for (vapor phase) fugacity coefficients and poyinting correction factors are selected. Additionally, a Thermo object defaults to ideal mixing rules for estimating mixture properties, and neglects excess energies in the calculation of enthalpy and entropy:”

]

}, {

“cell_type”: “code”, “execution_count”: 18, “metadata”: {}, “outputs”: [

{

“name”: “stdout”, “output_type”: “stream”, “text”: [

“Mixture(n”, ” rule=’ideal mixing’, …n”, ” include_excess_energies=Falsen”, “)n”

]

}

], “source”: [

“thermo = tmo.Thermo(lipidcane_chemicals)n”, “thermo.mixture.show()”

]

}, {

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“### References”

]

}, {

“cell_type”: “markdown”, “metadata”: {}, “source”: [

“<a id=’References’></a>n”, “n”, “1. Huang, H., Long, S., & Singh, V. (2016) “Techno-economic analysis of biodiesel and ethanol co-production from lipid-producing sugarcane” Biofuels, Bioproducts and Biorefining, 10(3), 299–315. https://doi.org/10.1002/bbb.1640n”, “n”, “2. Cortes-Peña, Y.; Kumar, D.; Singh, V.; Guest, J. S. BioSTEAM: A Fast and Flexible Platform for the Design, Simulation, and Techno-Economic Analysis of Biorefineries under Uncertainty. ACS Sustainable Chem. Eng. 2020. https://doi.org/10.1021/acssuschemeng.9b07040.n”, “n”, “3. Hatakeyama, T., Nakamura, K., & Hatakeyama, H. (1982). Studies on heat capacity of cellulose and lignin by differential scanning calorimetry. Polymer, 23(12), 1801–1804. https://doi.org/10.1016/0032-3861(82)90125-2n”, “n”, “4. Thybring, E. E. (2014). Explaining the heat capacity of wood constituents by molecular vibrations. Journal of Materials Science, 49(3), 1317–1327. https://doi.org/10.1007/s10853-013-7815-6n

]

}

], “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.7.6”

}

}, “nbformat”: 4, “nbformat_minor”: 2

}