Detailed C++ object class description¶
FastChem
has been written in an object oriented way, split across
several different object classes. The entire source code of FastChem
is contained in the folder fastchem_src/
. For including FastChem
in another C++
project, only adding the main fastchem header file
fastchem.h
is required. All FastChem
code is encapsulated in its
own namespace called fastchem
to avoid clashing with other
libraries.
Some comments on coding conventions¶
The entire FastChem
code has been programmed using specific
conventions that make it easy to recognise and differentiate class,
method and variable names.
Class and structure names are always capitalised, for example
class FastChem{...
or struct Molecule{...
struct ChemicalElementData{...
No separators like _ are used
for class or structure names.FastChem.setElementAbundances(...)
or
Molecule.calcMassActionConstant(...)
Variable names are always written in lowercase and compound nouns are
separated by a _. For example: FastChem.element_calculation_order
or Element.molecule_list
The only exceptions are global constants.
They contain only capitalised letters, e.g.:
constexpr unsigned int FASTCHEM_UNKNOWN_SPECIES
or
constexpr double CONST_AMU
FastChem object class¶
The entire FastChem
model is encapsulated in an object class called
FastChem
that is defined in the header file fastchem.h
. The
object class is programmed as a template that can be used in either
double
or long double
precision. When creating an object of this
class by calling a corresponding constructor, one therefore has to
specify which of the two versions should be used:
FastChem<long double> fastchem("model_parameter_file.dat", 1);
FastChem<double> fastchem("model_parameter_file.dat", 1);
The long double
version has a slightly higher computational overhead and
larger memory requirements than the double
one. On the other hand,
it offers a higher numerical precision which is especially important
when dealing with chemical systems where the mass action constants and
number densities can vary by many orders of magnitudes. We strongly
suggest to always use the long double
version despite the additional
computational overhead. In fact, in our experience the increased
numerical precision of long double
can effectively lead to a smaller
number of iterations.
FastChem constants¶
FastChem
namespace fastchem
contains a number of constants that are all defined in the file fastchem_constants.h
. This includes the constantconstexpr unsigned int fastchem::FASTCHEM_UNKNOWN_SPECIES
that is returned by some FastChem
methods when a chemical species is not found. The chemistry calculation will return several output flags that are also defined in this file. This includes the following constants:
constexpr unsigned int fastchem::FASTCHEM_SUCCESS
Indicates that the calculation has been successful, i.e. that the chemistry iterations converged.
constexpr unsigned int fastchem::FASTCHEM_NO_CONVERGENCE
Indicates that the calculation was not successful, i.e. that the chemistry did not converge within the allowed maximum number of iterations steps given in the config file or set manually via
FastChem.setMaxChemistryIter
(see here). One way to solve such a problem is to increase the maximum number of iteration steps.constexpr unsigned int fastchem::FASTCHEM_INITIALIZATION_FAILED
Indicates that something went wrong during reading one of the input files. To find the source of the problem, one can set the verbose level in the config file or manually via
FastChem.setVerboseLevel
(see here) to a higher value and look at the terminal output.constexpr unsigned int fastchem::FASTCHEM_IS_BUSY
The chemistry calculations of
FastChem
can only be called once for each object class instance. Attempting to start a new calculation while another is still running, for example via OpenMP, will result inFastChem
returning this flag.constexpr unsigned int fastchem::FASTCHEM_WRONG_INPUT_VALUES
FastChem
returns this flag if some input values are wrong. Currently, this refers to the temperature and pressure vectors in the input structure not having the same size (see here for details on the input structure).constexpr unsigned int fastchem::FASTCHEM_PHASE_RULE_VIOLATION
FastChem
returns this flag if condensation is used and the system violates the phase rule. This happens when the number of elements contained in condensates equals the total number of elements. In this case, the gas phase lacks a degree of freedom to yield the correct gas pressure. Such a system cannot be solved as there has always to be at least one incondensable element in the gas phase (see the section about the phase rule in Paper III).
In addition to these flags, fastchem_constants.h
also includes a
constant string vector
const std::vector<std::string> fastchem::FASTCHEM_MSG
that contains string expressions for each of these flags. Using this vector with any
of the aforementioned flags fastchem::FASTCHEM_MSG[flag]
returns a
string with a description of the corresponding flag’s meaning. For
example,
fastchem::FASTCHEM_MSG[fastchem::FASTCHEM_NO_CONVERGENCE]
will return the string "convergence failed"
.
FastChem constructor¶
FastChem
is written as an object class, an instance of that
class (i.e. an object) needs to be created before FastChem
can be
used. This is done by calling the constructor of the FastChem
class. There are three primary ways to call the constructor and create
an object.FastChem(const std::string& model_parameter_file,
const unsigned int verbose_level_init)
This constructor requires two parameters: the location of the parameter file, described here, as well as the initial verbose, i.e. the amount of debug output in the terminal window. All main options and parameters will be read from the parameter file, but can be changed later by using the appropriate methods described here.
FastChem(const std::string& element_abundances_file,
const std::string& gas_species_data_file,
const unsigned int verbose_level)
This constructor requires three parameters: the locations of the element abundance and gas phase species data files, as well as the verbose level. All other options and parameters within
FastChem
will be set to their default values but can be later changed by using the appropriate methods described here. The default maximum number of chemistry iterations is 3000, the number of Newton, bisection and Nelder-Mead method iterations is 3000, and the default accuracy of the of Newton method and the chemistry iterations is set to \(10^{-4}\). This constructor will not read in any condensate data. Trying to use an object created via this method for a calculation using condensation will result in an error message.
FastChem(const std::string& element_abundances_file,
const std::string& gas_species_data_file,
const std::string& cond_species_data_file,
const unsigned int verbose_level)
This constructor requires four parameters: the locations of the element abundance and gas phase species data files, the condensate data file, as well as the verbose level. All other options and parameters within
FastChem
will be set to their default values but can be later changed by using the appropriate methods described here. The default maximum number of chemistry iterations is 3000, the number of Newton, bisection and Nelder-Mead method iterations is 3000, and the default accuracy of the of Newton method and the chemistry iterations is set to \(10^{-4}\). Note that instead of a location for the condensate data, a string containing"none"
can be used here as well. In that case, no condensate data will be read in and trying to use the object for a calculation using condensation will result in an error message.
A fourth way to create a FastChem
object is to make a copy of an
existing one. FastChem
contains an internal copy constructor that
manages the copy of all the object class’ data structures. Assuming that
fastchem_a
is a valid object instance of the FastChem
class, a
second object, say fastchem_b
, can simply be created by using
fastchem::FastChem fastchem_b(fastchem_a);
In this example, fastchem_b
is a direct copy of fastchem_a
, i.e.
all parameters, options, and species & element data structures are
identical. After the creation of fastchem_b
, both objects can be
used independently from each other and can even be run at the same time.
Input and output structures¶
When the chemistry calculation of FastChem,
FastChem.calcDensities(FastChemInput, FastChemOutput)
is called, input and output structures are required. Their definitions can be found
in the source file fastchem_src/input_output_struct.h
Input structure¶
The input structure is defined as follows:
struct FastChemInput
{
std::vector<double> temperature;
std::vector<double> pressure;
bool equilibrium_condensation = false;
bool rainout_condensation = false;
};
It contains vectors for the temperatures (in K) and pressures (in bar)
that the chemical composition should be calculated for. Both vectors
need to have the same length. Otherwise, FastChem.calcDensities
will
return the constant fastchem::FASTCHEM_WRONG_INPUT_VALUES
. Note that
even if you want to run the chemistry for only a single temperature and
pressure point, you still need to provide the input in vectorial form.
The two boolean variables enable the calculation of either equilibrium
condensation or the rainout approximation. By default, both are set to
false
. Note that when the flag rainout_condensation
is set to
true
, the value of the parameter equilibrium_condensation
is
ignored.
Output structure¶
The outout structure is defined as
struct FastChemOutput
{
std::vector<std::vector<double>> number_densities;
std::vector<double> total_element_density;
std::vector<double> mean_molecular_weight;
std::vector<std::vector<double>> number_densities_cond;
std::vector<std::vector<double>> element_cond_degree;
std::vector<std::vector<unsigned int>> element_conserved;
std::vector<unsigned int> nb_chemistry_iterations;
std::vector<unsigned int> nb_cond_iterations;
std::vector<unsigned int> nb_iterations;
std::vector<unsigned int> fastchem_flag;
};
It has the following variables:
std::vector<std::vector<double>> number_densities
The two-dimensional array contains the number densities in of all gas phase species (elements, molecules, ions). The first dimension refers to the temperature-pressure grid and has the same size as the temperature and pressure vectors of the input structure. The second dimension refers to the number of species and has a length of
FastChem.getGasSpeciesNumber()
(see here).std::vector<double> total_element_density
Contains the total number density of all atoms \(j\), i.e. \(n_\mathrm{tot} = \sum_j \left( n_j + \sum_i \nu_{ij} n_i + \sum_c \nu_{cj} n_c \right)\), summed over their atomic number densities, as well as the ones contained in all other molecules/ions \(j\) as well as condensate species \(c\). This quantity is usually only a diagnostic output and not relevant for other calculations. The dimension of the vector is equal to that of the input temperature and pressure vectors.
std::vector<double> mean_molecular_weight
Contains the mean molecular weight of the mixture in units of the unified atomic mass unit. For all practical purposes, this can also be converted into units of g/mol. The dimension of the vector is equal to that of the input temperature and pressure vectors.
std::vector<std::vector<double>> number_densities_cond
The two-dimensional array contains the fictitious number densities in of all condensate species. The first dimension refers to the temperature-pressure grid and has the same size as the temperature and pressure vectors of the input structure. The second dimension refers to the number of species and has a length of
FastChem.getCondSpeciesNumber()
(see here).std::vector<std::vector<double>> element_cond_degree
The two-dimensional array contains the degree of condensation for all elements. The first dimension refers to the temperature-pressure grid and has the same size as the temperature and pressure vectors of the input structure. The second dimension refers to the number of elements and has a length of
FastChem.getElementNumber()
(see here).std::vector<std::vector<unsigned int>> element_conserved
The two-dimensional array contains information on the state of element conservation. A value of 0 indicates that element conservation is violated, whereas a value of 1 means that the element has been conserved. The first dimension refers to the temperature-pressure grid and has the same size as the temperature and pressure vectors of the input structure. The second dimension refers to the number of elements and has a length of
FastChem.getElementNumber()
(see here).std::vector<unsigned int> nb_chemistry_iterations
Contains the total number of chemistry iterations that were required to solve the system for each temperature-pressure point. The dimension of the vector is equal to that of the input temperature and pressure vectors.
std::vector<unsigned int> nb_iterations
Contains the total number of coupled condensation-gas phase chemistry calculation iterations that were required to solve the system for each temperature-pressure point. The dimension of the vector is equal to that of the input temperature and pressure vectors.
std::vector<unsigned int> nb_chemistry_iterations
Contains the total number of chemistry iterations that were required to solve the system for each temperature-pressure point. The dimension of the vector is equal to that of the input temperature and pressure vectors.
std::vector<unsigned int> fastchem_flag
Contains flags that give information on potential issues of the chemistry calculation for each temperature-pressure point. The set of potential values is stated here. A string message for each corresponding flag can also be obtained from the constant
fastchem::FASTCHEM_MSG
vector of strings, viafastchem::FASTCHEM_MSG[flag]
. The dimension of the vector is equal to that of the input temperature and pressure vectors.
The vectors of the output structure don’t need to be pre-allocated. This
will be done internally within FastChem
when running the chemistry
calculations. If the vectors already contain data, their contents will
be overwritten.
Public methods of the FastChem object class¶
unsigned int FastChem.calcDensities(FastChemInput input,
FastChemOutput output)
Starts a chemistry calculation with the provided
FastChemInput
andFastChemOutput
structs. Returns anunsigned int
that represents the highest value from the flag vector within theFastChemOutput
struct.
void FastChem.setParameter(std::string param_name,
param_type param_value)
Sets an internal
FastChem
parameter with the nameparam_name
. Depending on the parameter, the variable typeparam_type
can either be anunsigned int
, abool
, or adouble
value. A list of parameters and their types can be found in the next section.
unsigned int FastChem.getGasSpeciesNumber()
Returns the total number of gas phase species (atoms, ions, molecules) as
unsigned int
unsigned int FastChem.getElementNumber()
Returns the total number of elements as
unsigned int
unsigned int FastChem.getMoleculeNumber()
Returns the total number of molecules and ions (anything other than elements) as
unsigned int
unsigned int FastChem.getCondSpeciesNumber()
Returns the total number of condensate species as
unsigned int
std::string FastChem.getGasSpeciesName(unsigned int species_index)
Returns the name of a gas phase species with index
species_index
asstd::string
; returns empty string if species does not exist
std::string FastChem.getGasSpeciesSymbol(unsigned int species_index)
Returns the symbol of an element or the formula of a molecule/ion with index
species_index
asstd::string
; returns empty string if species does not exist
unsigned int FastChem.getGasSpeciesIndex(std::string symbol)
Returns the index of a species (element/molecule/ion) with symbol/formula
symbol
asunsigned int
; returns the constantfastchem::FASTCHEM_UNKOWN_SPECIES
if species does not exist
std::string FastChem.getElementName(unsigned int species_index)
Returns the name of an element with index
species_index
asstd::string
; returns empty string if species does not exist
std::string FastChem.getElementSymbol(unsigned int species_index)
Returns the symbol of an element with index
species_index
asstd::string
; returns empty string if species does not exist
unsigned int FastChem.getElementIndex(std::string symbol)
Returns the index of an element with symbol
symbol
asunsigned int
; returns the constantfastchem::FASTCHEM_UNKOWN_SPECIES
if species does not exist
std::string FastChem.getCondSpeciesName(unsigned int species_index)
Returns the name of a condensate species with index
species_index
asstd::string
; returns empty string if species does not exist
std::string FastChem.getCondSpeciesSymbol(unsigned int species_index)
Returns the formula of a condensate species with index
species_index
asstd::string
; returns empty string if species does not exist
unsigned int FastChem.getCondSpeciesIndex(std::string symbol)
Returns the index of a condensate species formula
symbol
asunsigned int
; returns the constantfastchem::FASTCHEM_UNKOWN_SPECIES
if species does not exist
double FastChem.getElementAbundance(unsigned int species_index)
Returns the abundance of an element with index
species_index
asdouble
; returns 0 if element does not exist
std::vector<double> FastChem.getElementAbundance()
Returns the abundances of all elements as a vector of
double
; vector has a length ofFastChem.getElementNumber()
double FastChem.getGasSpeciesWeight(unsigned int species_index)
Returns the weight of a gas phase species (element/molecule/ion) with index
species_index
asdouble
; returns 0 if species does not exist; for an element this refers to the atomic weight
double FastChem.getElementWeight(unsigned int species_index)
Returns the atomic weight of an element with index
species_index
asdouble
; returns 0 if the element does not exist
double FastChem.getCondSpeciesWeight(unsigned int species_index)
Returns the weight of a condensate species with index species_index
as double
; returns 0 if species does not exist
void FastChem.setElementAbundances(std::vector<double> abundances)
Sets the abundances of all elements; the abundances are supplied as
std::vector<double>
, where the vector has to have a size ofFastChem.getElementNumber()
; if this is not the case,FastChem
will print an error message and leave the element abundances unchanged
void FastChem.setVerboseLevel(unsigned int level)
Sets the verbose level of
FastChem
, i.e. the amount of text output in the terminal. A value of 0 will result inFastChem
being almost silent, whereas a value of 4 would provide a lot of debug output. A value larger than 4 will be interpreted as 4. This value will overwrite the one from theFastChem
config file.