Species / Species List
**********************

In a Zacros simulation, species are necessary to describe the
chemistry involved in the system. If one atom is identical to another,
we can say they are the same chemical species. In the same way, if one
molecule is identical to another, we can say they are the same
chemical species. Thus, we can highlight two essential kinds of
species: 1) gas species and 2) surface or adsorbed species. A molecule
in the gas phase is a species itself, but when it interacts with a
catalytic surface, its properties generally change enough to be
different from its gas counterpart. However, once it is adsorbed on
the catalytic surface, its properties may not change enough to change
its identity as it moves on the surface. In that sense, for example,
for a CO molecule, we can identify two kinds of species: 1) CO in the
gas phase and 2) CO adsorbed. Here, the CO is the same species
independently if it is adsorbed, e.g., on an fcc or an hcp site.

For any kind of species, the only required parameter is the symbol
(e.g., ""CO""), and it can be created with the sentence
"pz.Species("CO")". The "Species" constructor allows specifying
different parameters like denticity, gas energy, kind, and mass. By
default, pyZacros parses the species symbol to get these parameters.
If the symbol contains the character "*", it assumes that the species
is a surface species ("kind=pz.Species.SURFACE") with a denticity
given by the number of times that "*" is found in the symbol; i.e.
"pz.Species("O2**")" is equivalent to
"pz.Species("O2**",denticity=2,kind=pz.Species.SURFACE)". On the other
hand, if the symbol doesn't contain any "*", it assumes that the
species is a gas species ("kind=pz.Species.GAS"), with the mass
calculated from the parsing of the symbol as a chemical formula
string; i.e. "pz.Species("O2")" is equivalent to
"pz.Species("O2",kind=pz.Species.GAS,mass=31.9898)".

For our example (see use case system), we need to create three gas
species (CO, O_2, and CO_2), and three surface species (*, CO*, O*).
This can be achieved by using the lines 1-10 of following code:

   # Gas species
   CO_g = pz.Species("CO")
   O2_g = pz.Species("O2")
   CO2_g = pz.Species("CO2", gas_energy=-2.337)

   # Surface species
   s0 = pz.Species("*")   # Empty adsorption site
   CO_s = pz.Species("CO*")
   O_s = pz.Species("O*", denticity=1)

   # Species List
   spl = pz.SpeciesList([CO_g,O2_g,CO2_g,s0,CO_s])
   spl.append( O_s )
   print(spl)

Notice that the species symbol "*" is reserved for the empty site
species (or pseudo-species).

In this script, we have also introduced the class "SpeciesList", which
represents nothing more than a list of species (see lines 11-13). But,
in particular, it is helpful to look at the Zacros code that will be
generated based on it by using the "print()" function (see line 14).
The execution of the previous script displays the following on the
standard output:

   n_gas_species    3
   gas_specs_names              CO           O2          CO2
   gas_energies        0.00000e+00  0.00000e+00 -2.33700e+00
   gas_molec_weights   2.79949e+01  3.19898e+01  4.39898e+01
   n_surf_species    2
   surf_specs_names         CO*        O*
   surf_specs_dent            1         1

Please consult Zacros' user guide
("$AMSHOME/scripting/scm/pyzacros/doc/ZacrosManual.pdf") for more
details about the specific meaning of the keywords used in the
previous lines.


API
===

class Species(symbol, denticity=None, gas_energy=None, kind=None, mass=None)

   Species class that represents a chemical species

   * "symbol" -- Species' symbol. If symbol contains the character
     '*', it is considered an adsorbed species. Otherwise it is
     considered a gas species. e.g. H2*

   * "denticity" -- Species' denticity e.g. 2. If None, it is set as
     the number of times that the character '*' is found in the
     symbol.

   * "gas_energy" -- Species' gas energy in eV. e.g. "0.0"

   * "kind" -- It can be "Species.SURFACE" (0), or "Species.GAS" (1).
     If None, it is selected from the symbol.

   * "mass" -- Specifies the mass in Da. If None, the mass is
     calculated from the symbol interpreted as a chemical formula. The
     mass of the most abundant isotopes of composing atoms is used for
     this calculation. For example, if "symbol='CH4'", the mass will
     be "16.0312" ("12.0000+4*1.0078").

   is_adsorbed()

      Returns True if the name of the species has the character '*'.

   is_gas()

      Returns True if the name of the species has no the character
      '*'.

   composition()

      Returns a dictionary containing the number of atoms of each
      kind.

   mass()

      Returns the mass of the species in Da.

class SpeciesList(data=[])

   Creates a new SpeciesList object which is formally a list of
   Species. It implements all python list operations.

   * "data" -- List of Species to initially include.

   gas_species()

      Returns the gas species.

   surface_species()

      Returns the adsorbed species.

   mass(entity_numbers=None)

      Returns the total mass as the sum of its all species (surface
      and gas) in Da.

      * "entity_numbers" -- Avoids double-counting species when they
        belong to the same entity,
           e.g., [0,0,1,2] means that the first and second species
           belong to the same entity. Applies only to surface species.

   __updateLabel()

      Updates the attribute 'label'

   label()

      Returns the label of the cluster

   remove_duplicates()

      Removes duplicate species. Two species are considered the same
      if they have the same symbol.
