FCSys.Utilities.Chemistry

Functions to support chemistry

Information

Extends from Modelica.Icons.Package (Icon for standard packages).

Package Content

NameDescription
FCSys.Utilities.Chemistry.charge charge Return the charge of a species given its chemical formula
FCSys.Utilities.Chemistry.countElements countElements Return the number of elements in a chemical formula
FCSys.Utilities.Chemistry.readElement readElement Return the symbol, coefficient, and charge of an element in a chemical formula
FCSys.Utilities.Chemistry.readSpecies readSpecies Return the symbols and coefficients of the elements in a chemical formula
FCSys.Utilities.Chemistry.stoich stoich Return stoichiometric coefficients of a reaction based on chemical formulas of reacting species

FCSys.Utilities.Chemistry.charge FCSys.Utilities.Chemistry.charge

Return the charge of a species given its chemical formula

Information

This function returns the net electrical charge associated with a species represented by a chemical formula (formula). If the charge number is not given explicitly in the formula, then it is assumed to be zero. A "+" or "-" without any immediately following digits is interpreted as a charge of +1 or -1, respectively. If there is an error in the chemical formula, then 0 is returned.

Example:
charge("Hg2+2") returns 2.

Extends from Modelica.Icons.Function (Icon for functions).

Inputs

TypeNameDefaultDescription
Stringformula Chemical formula

Outputs

TypeNameDescription
IntegerzCharge number

Modelica definition

function charge 
  "Return the charge of a species given its chemical formula"
  extends Modelica.Icons.Function;
  input String formula "Chemical formula";
  output Integer z "Charge number";

external"C";

end charge;

FCSys.Utilities.Chemistry.countElements FCSys.Utilities.Chemistry.countElements

Return the number of elements in a chemical formula

Information

This function returns the number of elements in a chemical formula. Electrons are counted as a present element (or rather particle) if the net charge is nonzero.

Examples:
countElements("C19HF37O5S-") returns 5 and countElements("H+") returns 2.

Please see the readElement function for details about the format of the chemical formula.

Extends from Modelica.Icons.Function (Icon for functions).

Inputs

TypeNameDefaultDescription
Stringformula Chemical formula

Outputs

TypeNameDescription
IntegernNumber of elements

Modelica definition

function countElements 
  "Return the number of elements in a chemical formula"
  extends Modelica.Icons.Function;
  input String formula "Chemical formula";
  output Integer n "Number of elements";

external"C";

end countElements;

FCSys.Utilities.Chemistry.readElement FCSys.Utilities.Chemistry.readElement

Return the symbol, coefficient, and charge of an element in a chemical formula

Information

This function returns the symbol (symbol), stoichiometric coefficient (n), and electrical charge (z) associated with an element as it appears in a chemical formula (formula). After any initial whitespace in the formula string, which is ignored, the symbol must begin with a letter and may continue with lowercase letters. The symbol may be followed by a positive integer and then a charge number (both independently optional). If present, the charge number must begin with "+" or "-" and may be followed by optional digits. The remainder output gives the remainder of the formula string after the symbol, coefficient, and charge have been extracted.

If the coefficient is not explicitly given, then it is assumed to be one. If the charge number is not given, then it is assumed to be zero. A "+" or "-" without following digits is interpreted as a charge of +1 or -1, respectively. If there is an error, then symbol will be an empty string.

Example:
(symbol, n, z, remainder) = readElement("Hg2+2") returns symbol="Hg", n=2, z=2, and remainder="".

Extends from Modelica.Icons.Function (Icon for functions).

Inputs

TypeNameDefaultDescription
Stringformula Chemical formula

Outputs

TypeNameDescription
StringsymbolName of element (empty if error)
IntegernStoichiometric coefficient
IntegerzCharge number
StringremainderRemainder of the chemical formula

Modelica definition

function readElement 
  "Return the symbol, coefficient, and charge of an element in a chemical formula"
  extends Modelica.Icons.Function;
  input String formula "Chemical formula";
  output String symbol "Name of element (empty if error)";
  output Integer n "Stoichiometric coefficient";
  output Integer z "Charge number";
  output String remainder "Remainder of the chemical formula";

external"C" readElement(
    formula,
    symbol,
    n,
    z,
    remainder);

end readElement;

FCSys.Utilities.Chemistry.readSpecies FCSys.Utilities.Chemistry.readSpecies

Return the symbols and coefficients of the elements in a chemical formula

Information

This function reads a chemical formula (formula) and returns the symbols (symbols) and coefficients (coeffs). Each element is interpreted according to the rules in the readElement function. Currently, formula may not contain parentheses or brackets.

The symbols correspond to chemical/physical elements or electrons ("e-"). Electrons are listed if the charge is nonzero.

Example:
(symbols, coeffs) = readSpecies("C19HF37O5S-") returns symbols={"C", "H", "F", "O", "S", "e-"} and coeffs={19, 1, 37, 5, 1, 1}.

Extends from Modelica.Icons.Function (Icon for functions).

Inputs

TypeNameDefaultDescription
Stringformula Chemical formula

Outputs

TypeNameDescription
Stringsymbols[countElements(formula)]Symbols of the elements
Integercoeffs[countElements(formula)]Coefficients of the elements

Modelica definition

function readSpecies 
  "Return the symbols and coefficients of the elements in a chemical formula"
  extends Modelica.Icons.Function;
  input String formula "Chemical formula";
  output String symbols[countElements(formula)] "Symbols of the elements";
  output Integer coeffs[countElements(formula)] "Coefficients of the elements";
  // Note:  coeffs[size(symbols, 1)] would save computation but fails
  // in Dymola 2014.

protected 
  Integer z "Charge number";
  Integer z_net=0 "Net charge";
  Integer i=1 "Index of element";
  String f=formula "Working copy of formula";

algorithm 
  // Read the elements.
  while f <> "" loop
    (symbols[i],coeffs[i],z,f) := readElement(f);
    assert(symbols[i] <> "", "The formula (" + formula + ") is invalid.");
    z_net := z_net + z;
    if symbols[i] <> "e" then
      i := i + 1;
      // Electrons are counted below.
    end if;
  end while;

  // Add electrons according to the charge.
  if z_net <> 0 then
    symbols[i] := "e-";
    coeffs[i] := -z_net;
  end if;
end readSpecies;

FCSys.Utilities.Chemistry.stoich FCSys.Utilities.Chemistry.stoich

Return stoichiometric coefficients of a reaction based on chemical formulas of reacting species

Information

This function returns a vector of stoichiometric coefficients (n) that balance a chemical reaction among the species given by a vector of chemical formulas (formulas). If the reaction is ill-posed or non-unique, then the function will fail with a message. Each formula is interpreted according to the rules in the readElement function.

Example:
stoich({"e-","H+","O2","H2O"}) returns {-4,-4,-1,2}, which indicates the reaction 4e- + 4H+ + O2 ⇌ 2H2O.

Extends from Modelica.Icons.Function (Icon for functions).

Inputs

TypeNameDefaultDescription
Stringformulas[:] Chemical formulas of the species

Outputs

TypeNameDescription
Integern[size(formulas, 1)]Stoichiometric coefficients

Modelica definition

function stoich 
  "Return stoichiometric coefficients of a reaction based on chemical formulas of reacting species"
  import Modelica.Math.Matrices.singularValues;
  extends Modelica.Icons.Function;
  input String formulas[:] "Chemical formulas of the species";
  output Integer n[size(formulas, 1)] "Stoichiometric coefficients";

protected 
  Integer n_species=size(formulas, 1) "Number of species";
  Integer n_elements[n_species]=countElements(formulas) 
    "Number of elements within each species";
  Integer n_tot=sum(n_elements) "Total number of elements";
  String allSymbols[n_tot] "Symbols of all the elementary components";
  String symbols[n_species, max(n_elements)] 
    "Symbols of the elements of each species";
  Integer coeffs[n_species, max(n_elements)] 
    "Coefficients of the elements of each species";
  Integer i "Index";
  Integer j=1 "Index";
  Real d[n_species] "Diagonal entries of SVD";
  Real u[n_species, n_species] "1st unitary matrix of SVD";
  Real v[n_species, n_species] "2nd unitary matrix of SVD";
  Real minabs 
    "Minimum magnitude of the unnormalized stoichiometric coefficients";
  Real elementCoeffs[n_species, n_tot] "Elementary coefficients";

algorithm 
  // Generate a list of all the symbols.
  for i in 1:n_species loop
    (symbols[i, 1:n_elements[i]],coeffs[i, 1:n_elements[i]]) := readSpecies(
      formulas[i]);
    allSymbols[j:j + n_elements[i] - 1] := symbols[i, 1:n_elements[i]];
    j := j + n_elements[i];
  end for;
  // Reduce the list to a (unique) set.
  i := 1;
  while i < n_tot loop
    j := i + 1;
    while j <= n_tot loop
      if allSymbols[i] == allSymbols[j] then
        allSymbols[j] := allSymbols[n_tot];
        n_tot := n_tot - 1;
      else
        j := j + 1;
      end if;
    end while;
    i := i + 1;
  end while;
  // Note:  While loops are used since the upper bound changes.
  // Find the elementary coefficients for each species in terms of the
  // unique list of symbols.
  elementCoeffs[:, 1:n_tot] := zeros(n_species, n_tot);
  for i in 1:n_species loop
    for j in 1:n_elements[i] loop
      for k in 1:n_tot loop
        if allSymbols[k] == symbols[i, j] then
          elementCoeffs[i, k] := coeffs[i, j];
          break;
        end if;
      end for;
    end for;
  end for;
  // Perform singular value decomposition (SVD).
  assert(n_species == n_tot + 1, "The reaction is ill-posed.
" + (if n_species > n_tot + 1 then "A species may be included more than once."
     else "A species may be missing or the wrong one has been entered."));
  (d,u,v) := singularValues(cat(
    2,
    elementCoeffs[:, 1:n_tot],
    zeros(n_species, 1)));
  // This approach is based on [Reichert2010].
  // Extract the stoichiometric coefficients and normalize them.
  minabs := min(abs(u[:, end]));
  assert(minabs > 0, "The reaction is ill-posed.
An unrelated species may be included.");
  n := round(u[:, end]/minabs);
end stoich;