Tutorials

This section provides examples to show you how to use the ChemApp for Python friendly module function groups. The examples are small bits of code that you can use to build a full size investigation.

Working with Info Functions

The easiest way to get all the information about ChemApp, is by requesting a ChemAppInfo object, and printing it. Here is an example, code: 30-friendly/Info/01-basic-use.py

"""
This script gives examples of how to get a info object
"""
from chemapp.friendly import Info as cai

# extract all information related to chemapp into a ChemAppInfo object
info = cai.get_object()

# print the object
print(info)

Here is the result:

========================================================================
 ChemApp Information
------------------------------------------------------------------------
Class:           ChemAppInfo

Program ID:      CAFU
Version:         816
Is Light:        False
Expiration date: 2022/7

User ID:         1234
User Name:       Acme Ltd.

Dongle Type:
Dongle ID:       0

Copyright:
This program contains ChemApp.
Copyright GTT-Technologies, Kaiserstrasse 103, D-52134 Herzogenrath, Germany.
http://www.gtt-technologies.de
-------------------------------------------------------------------------
Array Sizes:
Item   Maximum   Used  Description
na       3000    3000  Number of constituents
nb         48      48  Number of system components
nc        150     150  Number of mixture phases
nd       2000    2000  Number of excess Gibbs energy coefficients for a
                       mixture phase
ne        500     500  Number of excess magnetic coefficients for a
                       mixture phase
nf          5       5  Number of sublattices for a mixture phase
ng       3000    3000  Number of constituents of a sublattice
nh         48      48  Number of oxide constituents of a phase described
                       by the Gaye-Kapoor-Frohberg or modified
                       quasichemical formalisms
ni         20      20  Number of Gibbs energy/heat capacity equations
                       for a constituent
nj      20000   20000  Number of Gibbs energy/heat capacity equations
nk       3000    3000  Number of constituents with P,T-dependent molar
                       volumes
===========================================================================

You can also use individual functions in the Info group, and you can use individual properties of ChemAppInfo objects that you obtain from the Info group. This provides ample flexibility for doing what you need. You can use the help function in python to find other functions of the Info functions.

Working with Units Functions

Checking Units

It is good practise to check the current units in ChemApp for Python before doing calculations. This can be done by printing them. Here is an example based on this example code: 30-friendly/Units/01-basic-use.py

"""
This script gives examples of how to use the core unit
"""
from chemapp.friendly import Units

# check the current units in ChemAppPy
units = Units.get_str()

# print the units
print(units)

Here is the result:

Units Currently Used by ChemApp
===============================
Pressure:    bar
Volume:      dm3
Temperature: K
Energy:      J
Amount:      mol

Changing Units

It is simple to change any of the units in ChemApp for Python. To change the pressure unit, here is an example, the code is found here: 30-friendly/Units/02-change-unit.py

"""
This script gives examples of how to use the core unit
"""
from chemapp.friendly import Units, PressureUnit

# set the pressure units to atmospheres
Units.set_P_unit(PressureUnit.atm)

# print to check that the units have been changed
print(Units.get_P_unit())

To check that the units are now correct you can print the unit again. The result is:

PressureUnit.atm

Working with Thermochemical Functions

Load thermochemical datafile

Before being able to do equilibrium calculations with ChemApp for Python you need to create a thermochemical system. You do this by loading a thermochemical data file, see the example below. This refers to 30-friendly/ThermochemicalSystem/01-basic-use.py

"""
ThermochemicalSystem Example 1
==============================

This example demonstrates the most basic steps involved in working with the
``friendly`` module's ``ThermochemicalSystem`` group of functions.
"""

from chemapp.friendly import (
    ThermochemicalSystem)


# load a thermochemical system from a data file
ThermochemicalSystem.load('../../data/cosi.dat')

# convert the thermochemical system to a core.ThermochemicalSystem object
ts = ThermochemicalSystem.get_object()

# print the core.ThermochemicalSystem object
print(ts)

To check if the thermochemical data file was loaded you can print it. It is useful to save the printed information in a text file so that you can refer to it later.

Getting the molar mass

You can get the molar mass of a particular phase, phase constituent or system component. This example is for a phase constituent, and the example code can be found here: 30-friendly/ThermochemicalSystem/055-get-molar-mass.py.

"""
This script gets the molar mass of a phase constituent
"""

from chemapp.friendly import ThermochemicalSystem, Units, AmountUnit


# load a thermochemical system from a data file
ThermochemicalSystem.load('../../data/fec.dat')

Units.set_A_unit(AmountUnit.gram)

# get the molar mass of O2 in the gas phase
mm_c = ThermochemicalSystem.get_mm_sc('C')

# print the molar mass
print(mm_c*1000.0)

The molar mass is:

12.010700000000002

Get Y (mass fraction) of a system component or phase constituent

You can get the mass fraction of a phase constituent in a phase or the mass fraction of a system component in a phase constituent. The example below shows how to calculate the mass fraction of carbon in carbon monoxide in the gas phase. This example refers to 30-friendly/ThermochemicalSystem/03-get-mass-fraction.py:

"""
This script gives an example of how to get the mass fraction of a system
component in a phase constituent
"""

from chemapp.friendly import ThermochemicalSystem

# load a thermochemical system from a data file
ThermochemicalSystem.load('../../data/cosi.dat')

# get mass fraction of C in CO
y_c = ThermochemicalSystem.get_y_sc_pc('GAS', 'CO', 'C')

# print result
print(y_c)

Result:

0.42880501528003884

Set the status of a phase

Before running a calculation, you can set the status of a particular phase or phase constituent. The options are ENTERED, ELIMINTATED or DORMANT. Here is an example. The code is: 30-friendly/ThermochemicalSystem/04-set-phase-status.py

"""
This scripts sets the status of a phase in ChemAppPy
"""

from chemapp.friendly import ThermochemicalSystem, Status

# load a thermochemical system from a data file
ThermochemicalSystem.load('../../data/fec.dat')

# set the status of the FCC phase as ENTERED
ThermochemicalSystem.set_status_ph('FCC_A1', Status.ENTERED)

# check if the status is now ENTERED
status = ThermochemicalSystem.get_status_ph('FCC_A1')

# print status
print(status)

The result:

Status.ENTERED

Working with EquilibriumCalculation Functions

Equilibrium calculation

One can do simple equilibrium calculation in ChemApp for Python. The example below shows how to calculate the mass of liquid alloy formed when heating up cementite with pure carbon. Here is an example, the code is here: 30-friendly/EquilibriumCalculation/01-basic-use.py.

"""
This scripts shows how to do a simple equilibrium calculation with
EquilibriumCalculation
"""

from chemapp.friendly import (
    ThermochemicalSystem as cats,
    EquilibriumCalculation as caec,
    Status, Units)

# load a thermochemical system from a data file
cats.load('../../data/fec.dat')
Units.set()

# convert the thermochemical system to a core.ThermochemicalSystem object
ts = cats.get_object()

# set input parameters
T_feed = 25.00  # C, feed temperature
T_equilib = 1600.00 # C, equilibrium temperature
P_feed = 1.0  # atm, feed pressure
P_equilib = 1.0  # atm, equilibrium pressure
m_fec = 500.0  # kg, mass of cementite added
m_c = 1.0  # kg, mass of graphite added

# set input parameters in ChemApp for Python with EquilibriumCalculation
caec.set_IA_pc('Fe3C_CEMENTITE', 'Fe3C_CEMENTITE', m_fec)
caec.set_IA_pc('C_GRAPHITE', 'C_GRAPHITE', m_c)

# set equilibrium conditions
caec.set_eq_T(T_equilib)
caec.set_eq_P(P_equilib)

# calculate equilibrium
caec.calculate_eq(print_results=False)

# get amount of liquid alloy formed
m_liq = caec.get_eq_A_ph('LIQUID')

# print result
print('Liquid-alloy: %f kg' % m_liq )

The mass of liquid alloy formed is:

Liquid-alloy: 493.640494 kg

Target equilibrium calculation

It is also possible to set the target formation phase for the calculation. Here is an example to do this, code: 30-friendly/EquilibriumCalculation/02-set-target-eq-condition.py In this example we calculate the temperature at which liquid alloy starts forming:

"""
This scripts shows how to do a simple equilibrium calculation with
EquilibriumCalculation
"""

from chemapp.friendly import (
    ThermochemicalSystem as cats,
    EquilibriumCalculation as caec,
    Info as cai,
    Units)

# load a thermochemical system from a data file
cats.load('../../data/fec.dat')
Units.set()

# Check if we are working with the 'light' version.
# If we do, omit the following phase target calculation(s).
if cai.is_light():
    raise ValueError(f'Target calculations are not supported when using ChemApp Light.'
                     ' This example is included in the documentation to illustrate the'
                     ' abilities available with the full version of ChemApp.')


# convert the thermochemical system to a core.ThermochemicalSystem object
ts = cats.get_object()

# set input parameters
T_feed = 25.00  # C, feed temperature
T_equilib = 1600.00 # C, equilibrium temperature
P_feed = 1.0  # atm, feed pressure
P_equilib = 1.0  # atm, equilibrium pressure
m_fec = 500.0  # kg, mass of cementite added
m_c = 1.0  # kg, mass of graphite added

# set input parameters in ChemApp for Python with EquilibriumCalculation
caec.set_IA_pc('Fe3C_CEMENTITE', 'Fe3C_CEMENTITE', m_fec)
caec.set_IA_pc('C_GRAPHITE', 'C_GRAPHITE', m_c)

# set equilibrium conditions
caec.set_target_formation_of_ph('LIQUID')
caec.set_eq_P(P_equilib)

# calculate equilibrium
caec.calculate_eq_T(T_equilib)

# get amount of liquid alloy formed
T_formation = caec.get_eq_T()

# print result
print(T_formation)

Result:

1153.4357094806123 C

Working with StreamCalculation Functions

Equilibrium calculation with two streams

An example of a simple stream calculation is to calculate the amount of energy required or change in energy when smelting iron oxide with graphite at a high temperature. Here is an example, see code: 30-friendly/StreamCalculation/01-basic-use.py

"""
This script is a basic example of how an stream equilibrium calculation is done.
"""

from chemapp.friendly import \
    ThermochemicalSystem as cats, \
    StreamCalculation

# load a thermochemical system from a data file
cats.load('../../data/fec.dat')

# get thermochemical system as object
ts = cats.get_object()

# set parameters
T_amb = 25.00 # C
P_amb = 1 # atm
T_equilib = 1500.00 # C
P_equilib = 1 # atm
m_red = 1.0 # kg
m_ore = 500.0 # kg

y_feo = 0.4 # kg/kg, mass fraction feo in ore
y_fe2o3 = 0.6 # kg/kg, mass fraction fe2o3 in ore

m_feo = m_ore*y_feo
m_fe2o3 = m_ore*y_fe2o3

# create ore stream
StreamCalculation.create_st('ore', T_amb, P_amb)
StreamCalculation.set_IA_pc('ore', 'Fe3C_CEMENTITE', 'Fe3C_CEMENTITE',
                            m_feo)


# create reductant stream
StreamCalculation.create_st('reductant', T_amb, P_amb)
StreamCalculation.set_IA_pc('reductant', 'C_GRAPHITE', 'C_GRAPHITE',
                            m_red)

# set equilibrium conditions
StreamCalculation.set_eq_T(T_equilib)
StreamCalculation.set_eq_P(P_equilib)

# calculate equilibrium
StreamCalculation.calculate_eq(print_results=False)

# calculate change in enthalpy
dH = StreamCalculation.get_eq_H()

# print result
print(f'dH reaction: {dH} kWh')

Results:

dH reaction: 73.290423 kWh

Target calculation with stream calculation

You can also calculate the equilibrium by seting a formation or precipitation phase target. This is an example of a target precipitation phase, 30-friendly/StreamCalculation/02-set-target-eq-condition.py

"""
This script is a basic example of how an stream equilibrium calculation is
done with a target precipitation phase.
"""

from chemapp.friendly import \
    ThermochemicalSystem as cats, \
    StreamCalculation

# load a thermochemical system from a data file
cats.load('../../data/fec.dat')

# get thermochemical system as object
ts = cats.get_object()

# set parameters
T_amb = 1600.00  # C
P_amb = 1.0  # atm
T_equilib = 500.00  # C
P_equilib = 1  # atm
m_alloy = 500.0  # kg

y_fe = 0.8  # kg/kg, mass fraction fe in alloy
y_c = 0.05  # kg/kg, mass fraction carbon in alloy

m_fe = m_alloy*y_fe
m_c = m_alloy*y_c

# create alloy stream
StreamCalculation.create_st('alloy', T_amb, P_amb)
StreamCalculation.set_IA_pc('alloy', 'LIQUID', 'Fe',
                            m_fe)
StreamCalculation.set_IA_pc('alloy', 'LIQUID', 'C',
                            m_c)

# set equilibrium conditions
# set precipitation target phase as the liquid alloy
StreamCalculation.set_target_formation_of_ph('LIQUID')
StreamCalculation.set_eq_P(P_equilib)

# calculate equilibrium
StreamCalculation.calculate_eq_T(T_equilib)

# get the temperature at which precipitation occurs
T_precept = StreamCalculation.get_eq_T()

# print result
print(T_precept)

The result:

1153.4358038309547

Working with PhaseMap Functions

These functions allow one-dimensional phase mapping. To use these functions, one of three variables can be adjusted; pressure, temperature or composition.

Equilibrium calculation with two streams

Phase transitions can be determined by varying the temperature. See the example, 30-friendly/PhaseMapCalculation/01-basic-use.py.

from chemapp.friendly import (
    ThermochemicalSystem as cats,
    PhaseMapCalculation as pmc,
    Units)
from chemapp.core import (
    AmountUnit,
    TemperatureUnit)
import chemapp

from pathlib import Path

# Local ChemApp for Python data directory
cap_path = Path(chemapp.__file__).parent
data_path = cap_path / "data"

# Load the PbSn thermochemical system
cats.load(data_path / 'pbsn.dat')

# Set amount units to kg and temperature units to K
Units.set_A_unit(AmountUnit.kg)
Units.set_T_unit(TemperatureUnit.K)

# Get and print the thermochemical system
ts = cats.get_object()
print(ts)

# Set incoming amounts to 0.8 mol Pb and 0.2 mol Sn
pmc.set_IA_sc("Pb", 0.8)
pmc.set_IA_sc("Sn", 0.2)

# Calculate the one dimensional phase boundaries when varying temperature
results = pmc.calculate_ph_txs_T(300, 700, False)

# Print the results in table format
template = "{TEMP:<30}{PHASES:<30}{AMOUNT:<30}"
print(template.format(
    TEMP="Temperature(K)",
    PHASES="Stable phases",
    AMOUNT="Amount(kg)"))

for result in results:
    print(template.format(TEMP=result.T,
                          PHASES="",
                          AMOUNT=""))
    stable_phases = result.get_eq_phs()
    for stable_phase in stable_phases:
        print(template.format(TEMP="",
                              PHASES=stable_phase.name,
                              AMOUNT=stable_phase.A))
Temperature (K)    Stable Phases      Amount (mol)
300.000000
                    BCT_A5#1             0.178784
                    FCC_A1             0.821216
454.561924
                    BCT_A5#1             0.038190
                    FCC_A1             0.961810
541.876513
                    LIQUID             1.000000
700.000000
                    LIQUID             1.000000

Vary incoming amounts to get phase transition

You can use composition to find the phase transitions as well. In this case you will keep temperature and pressure constant. See this example, 30-friendly/PhaseMapCalculation/02-incoming-amounts-variation.py

"""
This script gives an example of how to do a phase map calculation with ChemApp for Python
"""

from chemapp.friendly import \
    ThermochemicalSystem as cats, \
    PhaseMapCalculation as pmc

# load a thermochemical system from a data file
cats.load('../../data/femgsio4.dat')

# set parameters
P_equilib = 1  # atm

# set the equilibrium pressure
pmc.set_eq_P(P_equilib)

# create ranges of incoming amounts
fe2sio4_range = pmc.IA_range('Fe2SiO4', '', 0.0, 0.2)
mg2sio4_range = pmc.IA_range('Mg2SiO4', '', 1.0, 0.8)
ranges = [fe2sio4_range, mg2sio4_range]

# calculate phase map results
results = pmc.calculate_ph_txs_IA(ranges, print_results=False)

# Print the results in table format
print('X(Fe2SiO4)     X(Mg2SiO4)       Stable Phases        Amount (mol)')
for result in results:
    print('%f             %f' % (result.IAs[0].A, result.IAs[1].A))
    stable_phases = result.get_eq_phs()
    for stable_phase in stable_phases:
        print('                                %s               %f' % (
            stable_phase.name, stable_phase.A))

The result:

X(Fe2SiO4)     X(Mg2SiO4)       Stable Phases        Amount (mol)
0.000000             1.000000
                                Olivine               1.000000
0.200000             0.800000
                                Olivine               1.000000