Advanced features
This chapter explains the advanced features that ChemApp for Python has beyond the abilities of the C/Fortran ChemApp, such as using the state functions and object oriented approach to model processes.
Content Overview
Result objects
chemapp.core.EquilibriumCalculationResult
andchemapp.core.StreamCalculationResult
ChemApp logging
chemapp.core.Object
Input using chemical formulae using
set_IA_cfs()
One of the core features of ChemApp for Python is taking advantage of object
oriented structures to allow using calculation results of previous calculations
as input for further calculations, and therefore allowing e.g. process models to
be rapidly deployed without much tedious setup processes. This takes advantage
of the State
classes and EquilibriumCalculationResult
as well as
StreamCalculationResult
objects mentioned in the core section.
The practical use of the logging abilities of ChemApp for Python is another feature that allows quickly generating helpful information to debug and analyze your program code.
Furthermore, a convenient way to enter incoming amounts using chemical formula
instead of phase constituents or system components is introduced, using the
set_IA_cfs()
routine of the
EquilibriumCalculation
classes.
Result Objects
Most thermochemical calculations related to process manages are using multiple
calculation steps to describe. With ChemApp for Python, it is possible to easily
use results of previous calculations not only to store and investigate the
calculation results, but also as input for following calculations. To work with
calculation results as inputs for new calculations, they have to be converted
into StreamState
objects, which are objects that are defining input streams
in ChemApp. They do carry an initial temperature, initial pressure and phase
(constituent) amounts, all of which is necessary to define an input stream into
ChemApp for Python.
One of the main applications of stream or initial conditions based calculations
are in process modelling and in designing of material flow in multistage
reaction schemes. Functions to split, separate and combine StreamState
objects are available, as well as directly creating streams from equilibrium
results filtered by e.g. matter of state, phase or constituents.
Creation of result objects
After executing a calculation, a EquilibriumCalculationResult
and
StreamCalculationResult
can be created using the class routine
get_result_object
of EquilibriumCalculation
or StreamCalculation
.
The result objects are relatively rich data container classes, that expose
reasonable information of the calculation as properties, such as the conditions
and inputs, as well as e.g. the units in which the results are stored. All
fetchable thermodynamic data is stored in the object for all phases and
constituents. Most of the properties are constructed of the various data
structures that ChemApp for Python provides, such as PhaseState
classes.
It is recommended to always create a result object from a calculation, if any type of aggregating or deeper analysis of certain results is planned. The computational cost of collecting the data is relatively low. However, each calculation result object size can quickly become large for large datafiles.
Creation of stream objects
Note: An extended introduction to stream functionalities can be found in Stream Functionalities.
From these objects, the following routines can be used to create StreamState
classes, which then can be used as inputs for new calculations:
create_stream
create_stream_by_state
create_gas_stream
create_liquid_stream
create_solid_stream
Of these routines, create_stream
is the most versatile and allows for
various types of filters and selections, namely by specifically including or
excluding certain phases, as well as including or excluding certain elements. It
also allows to set a certain threshold to ignore residual amounts of phase
constituents.
Update checks & persistent configuration
The update mechanism and the persistent configuration (including the density
preference stored via Info.set_density_config
) are described in detail in
the dedicated chapter below. It explains how automatic and forced update
checks work, what is stored in chemapp_python.cfg
in the user home
directory, and how to select a VolumeEstimateSetting
.
More information on this: Update checks & persistent configuration.
ChemApp Logging
A debugging functionality has been added to ChemApp for Python that allows to output the ChemApp library calls in the original FORTRAN language calls to the ChemAPP API. It allows for users to generate a complete stream of the setup that was used in calculations, which can be very helpful to guide through e.g. presumed bugs in ChemApp, in some library code or to check if the program does indeed do as intended.
If a function returns a result, this result is printed directly after the function. Therefore it can also be used to quickly find off-by-one errors or other typical programming mishaps.
It can be enabled by using
from chemapp.basic import enable_logging, disable_logging # enable logging to 'calls.log' enable_logging() # and can subsequently deactivated using disable_logging()
The output is appended to the file ‘calls.log’ in the current working directory, and together with the datafile used in the calculation should be a valuable debugging ressource, especially if you consider contacting GTT for maintenance or support.
Input of complex chemical formulae
ChemApp for Python allows you to specify incoming amounts using full chemical
formula strings instead of listing system components or phase constituents
individually. This is done via the class method
set_IA_cfs()
(and the
analogous set_IA_cfs()
in stream calculations).
The parsing, validation and convenient (pretty) printing of chemical formulae
is handled by the Composition
class, which provides a
rich interface around a formula viewed as an ordered mapping
{element: amount}
.
Important
Calling set_IA_cfs()
REPLACES previously defined incoming amount
conditions for the involved system components. It is not additive. If you
want to change or extend the incoming amounts and use set_IA_cfs()
, you
have to use set_IA_sc()
or set_IA_pc()
only after set_IA_cfs()
has
been called (the same semantics apply for the StreamCalculation
variants).
Rationale & workflow
You supply one or more chemical formula strings plus the corresponding incoming amount values.
Each formula string is internally converted into a
Composition
object.The composition is validated: only elements that can be represented by the system components of the loaded datafile are accepted. Parentheses and fractional / decimal subscripts (e.g.
Cr0.3Mn0.7C
) are expanded.The element amounts are mapped onto system components; the resulting system component incoming amounts replace any prior ones.
Accepted input formats
Examples of accepted formula strings:
Fe2O3
Na(OH)2
(parentheses are expanded)Cr0.3Mn0.7C
(decimal amounts)Al2SiO5
If a composition cannot be expressed solely with the available system components an error is raised.
Using set_IA_cfs()
Basic usage:
from chemapp.friendly import EquilibriumCalculation
# Replace (not add to) any previously defined incoming amounts
EquilibriumCalculation.set_IA_cfs(
cfs=["CaO", "SiO2", "Al2O3"],
values=[10.0, 5.0, 2.0]
)
As long as all compositions can be expressed using the system components of the loaded data file, you can use:
EquilibriumCalculation.set_IA_cfs(
["Cr0.3Mn0.7C", "Na(OH)2"],
[1.2, 4.5]
)
Leveraging Composition
explicitly
While for set_IA_cfs()
you just pass formula strings, working directly with the
Composition
class (from chemapp.core import Composition
) to
inspect or transform formulae beforehand (e.g. for validation, normalization,
pretty printing or logging) can be helpful.
Key features of Composition
Ordered storage of elements as entered
Validation & tolerant parsing (parentheses, decimals)
Multiple string representations for consistent reporting
Scaling reduction to smallest integer ratio
Dictionary export (optionally reduced)
Properties & methods
formula
- canonical internal string representationpretty_formula
- elements sorted by Pauling order, amounts of 1 omittedreduced_formula
- smallest common denominator appliedpretty_reduced_formula
- combination of sorting + reductionelements
-frozenset
of element symbolsunordered
- original input order {element: amount}to_dict(reduced=False)
- export mapping, optionally reduced
Examples
Creating compositions:
from chemapp.core import Composition
c1 = Composition("Fe2O3")
c2 = Composition("Cs(OH)3")
c3 = Composition({"Cr": 0.3, "Mn": 0.7, "C": 1}) # from dict
c4 = Composition(c1) # copy from existing Composition
Inspecting representations:
c = Composition("Fe4O6")
c.formula # 'Fe4O6'
c.pretty_formula # e.g. 'Fe4O6'
c.reduced_formula # 'Fe2O3'
c.pretty_reduced_formula # 'Fe2O3'
c.to_dict() # {'Fe': 4.0, 'O': 6.0}
c.to_dict(reduced=True) # {'Fe': 2.0, 'O': 3.0}
Dealing with parentheses & reordering:
Composition("Cs(OH)3").formula # 'Cs1O3H3'
Composition("Cs(OH)3").pretty_formula # 'CsO3H3'
Composition("Cs(OH)3").reduced_formula # 'CsO3H3' (already reduced)
Logging / pretty printing in reports:
comps = [Composition(f) for f in ["Fe2O3", "Na(OH)2", "Cr0.3Mn0.7C"]]
for comp in comps:
print(f"Input: {comp.formula} Pretty: {comp.pretty_reduced_formula}")
Using it to e.g. validate user input:
formulas = ["Fe2O3", "Na(OH)2", "Cr0.3Mn0.7C"]
amounts = [3.0, 1.5, 0.8]
try:
compositions = [Composition(f) for f in formulas]
except:
# this would be a place where you could catch validation errors
...
# Single replacing call
EquilibriumCalculation.set_IA_cfs(formulas, amounts)