Usage

Getting started

Yamdb provides data collected from literature sources in currently three databases supplied with the distribution. Convenience functions to access these databases are available as

  • yamdb.get_from_metals() to access metals.yml

  • yamdb.get_from_salts() to access salts.yml

  • yamdb.get_from_Janz1992() to access the collection of molten salt data from [Janz1992]

The three commands listed below produce the density of sodium at its melting point:

import yamdb.yamdb as ydb
Na = ydb.get_from_metals('Na')
print('Na density at %f K is %f kg/m³' % (Na.Tm, Na.density(Na.Tm)))

Salt mixtures are characterized by their components and their molar ratios. The code below shows how to define a salt mixture object ‘CaCl2_NaCl’ from the data stored in salts.yml. The presence of the dash in the mixture designation triggers instantiation of a MixtureProperties object that - in contrast to a simple Property object - possesses composition information. Depending on the available data and equations this is often a fixed composition like “composition[‘15-85’]”, i.e. 15 mol% CaCl2 and 85 mol% NaCl, and less frequently a range. In the latter case, the property method (‘density’ in the present example) needs a second argument that provides the molar fraction of the first component CaCl2. The results of both independent calculations for the density of CaCl2-NaCl 15-85 at 1000 K match fairly well.

from yamdb import yamdb as ydb

CaCl2_NaCl = ydb.get_from_salts('CaCl2-NaCl')

T = 1020
st = CaCl2_NaCl.composition['20-80'].surface_tension(T)

print('CaCl₂-NaCl 20-80 surface tension at %d K is %4.3f N/m' % (T, st))

rho = CaCl2_NaCl.composition['range'].density(1090, 0.15)
# ρ = 1641 kg/m³

rho = CaCl2_NaCl.composition['15-85'].density(1090)
# ρ = 1635 kg/m³

It is essential to check the original sources before using material properties derived from Yamdb in calculations and publications should cite the original sources. To facilitate these tasks, Yamdb contains a module yamref and a BibTeX database with all references references.bib. Its usage requires the installation of bibtexparser. A simple case of looking up the reference for a density value is shown below:

from yamdb import yamdb as ydb
from yamdb import yamref as yrf

Ga = ydb.get_from_metals('Ga')

rho = Ga.density(273.15 + 50)

yrf.get_from_references(Ga.get_default_source('density'))
# 'Iida, Takamichi and Guthrie, Roderick I. L (1988)
# The Physical Properties of Liquid Metals.
# Clarendon Press. Oxford.'

“get default source(’density’)” returns the source key of the default source. It is ‘IidaGuthrie1988’ for Ga that gets expanded to the full citation by the call to yamref.get_from_references().

If bibtexparser is not available, the function get_from_references provided by yamdb.yamdb can be used instead. It resorts to references.yml generated by Pandoc from references.bib.

from yamdb import yamdb as ydb

Ga = ydb.get_from_metals('Ga')

rho = Ga.density(273.15 + 50)

ydb.get_from_references(Ga.get_default_source('density'))
# 'Iida, T., Guthrie, R.I.L., 1988. The physical properties
# of liquid metals. Clarendon Press, Oxford.'

Often, equations from different sources are available for a specific thermophysical property of a substance. The script below loops over the available sources for density and dynamic viscosity of sodium to calculate sodium’s kinematic viscosity. Typically, one would like to use an identical source for both properties and observe the range limits of the equations.

import numpy as np
import matplotlib.pyplot as plt
import yamdb.yamdb as ydb

Na = ydb.get_from_metals('Na')

dsources = Na.get_source_list('density')
vsources = Na.get_source_list('dynamic_viscosity')

T = np.linspace(Na.Tm, Na.Tb)

fig, ax = plt.subplots()

for dsource in dsources:
    for vsource in vsources:
        ax.plot(T,
                (Na.dynamic_viscosity(T, source=vsource) /
                 Na.density(T, source=dsource)),
                label="%s-%s" % (vsource, dsource))
ax.legend(frameon=False)
ax.set_xlabel("T / K")
ax.set_ylabel("ν / m s⁻¹")
ax.set_ylim([0.2E-06, 1E-06])

fig.savefig("kinematic_viscosity_Na.png")
_images/kinematic_viscosity_Na.png

Extending Yamdb

Yamdb was designed with the hope of being easily extensible. When new results on thermophysical properties of liquid metals and molten salts become available it should be not too much effort to incorporate them into Yamdb. The following sections describe the necessary steps to do this. It is arranged according to increasing order of complexity.

The (abridged) directory tree of yamdb is shown below:

|-- yamdb
|   |-- properties
|   `-- data
`-- tests
    |-- unit-tests
    |   |-- vapour_pressure
    |   |-- thermal_conductivity
    |   |-- surface-tension
    |   |-- sound_velocity
    |   |-- resistivity
    |   |-- heat_capacity
    |   |-- expansion_coefficient
    |   |-- dynamic_viscosity
    |   `-- density
    `-- integration-tests

Adding Coefficients for Existing Materials and Equations

  1. Select the database to be extended (metals.yml, salts.yml, your own file).

  2. Check, if the equation for the is already implemented or if the coefficients can easily be adjusted to use an already present equation.

  3. Extend the YAML database (yamdb/data/metals.yml in this case) with the new coefficients

    Pb:  # already present
      Tm: 600.55  # already present
      Tb: 2023.15  # already present
      M: 207.2  # already present
      density:  # already present
        ElAhrairah1972:
          rho_m: 10669.9
          lambda: 1.319
          equation: Steinberg1974
          comment: Fictional values, do not use!
          Tmin: 650
          Tmax: 1200
          uncertainty: 2%
    

    add a reference to yamdb/data/references.bib

    @article{ElAhrairah1972,
      author = {E. A. El-Ahrairah},
      title = {Density of liquid lead measured down by the river.},
      journal = {Journal of Irreproducible Results},
      volume = 169,
      number = 4,
      pages = {56-78},
      year = 1972,
    }
    

    and update yamdb/data/references.yml as well:

    bib2yaml.bash yamdb/data/references.bib > yamdb/data/references.yml
    

    Should you do not have access to Pandoc, edit references.yml by hand:

    ElAhrairah1972:
      "El-Ahrairah, E.A., 1972. Density of liquid lead measured
      down by the river. Journal of Irreproducible Results.
      169(4), 56-78."
    

    Data according to the new density source should now be available by calling (assuming that yamdb/data/metals.yml was extended):

    import yamdb.yamdb as ydb
    Pb = ydb.get_from_metals('Pb')
    T = 800  # K
    source = 'ElAhrairah1972'
    print('Pb density at %4.1f K according to %s is %6.1f kg/m³' % (T,
           source, Pb.density(T, source=source)))
    

    to obtain bibliographical information on the source use

    import yamdb.yamref as yrf
    yrf.get_from_references('ElAhrairah1972')
    

Adding New Materials

  1. Collect the melting point, the boiling point, and the molar mass of the new material. If one or more of them are not available, enter ‘null’ as value, it will be parsed to Python’s ‘None’.

  2. Enter the elemental symbol, the molecular formula, or the composition into the database as root node and add the keys and values from above. The example below is for unobtainium.

Un:
  Tm: 2345
  Tb: 9876
  M: 456.123987

Adding New Equations

  1. Find the right property module for the equation. Currently existing under yamdb/properties are:

    • density.py

    • dynamic_viscosity.py

    • expansion_coefficient.py

    • heat_capacity.py

    • resistivity.py

    • sound_velocity.py

    • surface_tension.py

    • thermal_conductivity.py

    • vapour_pressure.py

  2. If the right module is identified, add the equation. In this example we implement the temperature dependent density of adamantium according to Dr. Eisenbart. The docstring follows numpydoc conventions.

    def Eisenbart1803(Temp, coef=coef):
        r"""Return density according to Eisenbart (1803) p. 7, Eq. (5).
    
        .. math:: \rho = \rho_m + A \sin(2 \pi T/P)
    
        Parameters
        ----------
        Temp : float
            Temperature in K, single value or numpy array.
    
        coef : float
            List of coefficients, typically automatically extracted from YAML DB.
    
        Returns
        -------
        float
            Density in kg/m3.
    
        Raises
        ------
        LookupError
            If not all required keys/values are present in the coef dictionary.
    
        References
        ----------
        Eisenbart, J.D., 1803. The fabulous density of adamantium as a function
        of temperature. Journal of Irreproducible Results 1(1), 1-11.
    
        """
        try:
            rho_m = coef['rho_m']
            A = coef['A']
            P = coef['P']
        except LookupError as e:
            print("ERROR: Not all coefficients supplied, cannot compute values!\n"
                  "First missing coefficient: %s" % e)
            raise
        rho = rho_m + A*np.sin(2*np.pi*Temp/P)
        rho *= 1729.994  # oz/(cu in) -> kg/m3
        return rho
    
  3. Add the reference for the new equation to yamdb/data/references.bib

    @article{Eisenbart1803,
      author = {J. D. Eisenbart},
      title = {The fabulous density of adamantium as a function of temperature},
      journal = {Journal of Irreproducible Results},
      volume = 1,
      number = 1,
      pages = {1-11},
      year = 1803,
    }
    

    and update the corresponding YAML file (see item 1).

  4. Write a unit test in the corresponding directory, i.e. tests/unit-tests/density/Eisenbart1803_density_test.py.

    import sys
    sys.path.insert(0, '../../../')
    from pytest import approx
    
    from yamdb.properties.density import Eisenbart1803
    
    # Un from metals.yml
    coef = {
        'rho_m': 7.1362,
        'A': 1.3555,
        'P': 1234,
        }
    
    rho = Eisenbart1803(3000.0, coef=coef)
    
    def test():
        assert rho == approx(13329.104849, 1E-11)
    
  5. Check that the function is working as expected.

    cd tests
    pytest
    
  6. Add the function together with the coefficients (taken from Eisenbarth1803) to the YAML database, in our case yamdb/data/metals.yml. We describe here the density of adamantium with the equation from Eisenbart (1803).

    Ad:
      Tm: 987
      Tb: 2345
      M: 543.21987
      density:
        Eisenbart1803:
          rho_m: 6.5432
          A: 2.321
          P: 423
          equation: Eisenbart1803
          Tmin: 1000
          Tmax: 2000
          comment: complete nonsense, do not use!
          uncertainty: 100%
          default: true
    

Adding New Properties

You would like to add an additional materials property to the ones already available. In this example it is the price. Not exactly a thermophysical property but for the sake of the example, let’s assume that.

  1. Add a module (file price.py in yamdb/properties) for the property “price”.

    """Implements the price methods."""
    import numpy as np
    
    coef = None
    
  2. Add an equation to this module file and follow the subsequent steps described above for doing this (reference, unit test).

    """Implements the price methods."""
    import numpy as np
    
    coef = None
    
    def Scheuer2019(Temp, coef=coef):
        r"""Return price according to Scheuer (2019) p. 234, Eq. (11a).
    
        .. math:: p = A / (B - T)
    
        Parameters
        ----------
        Temp : float
            Temperature in K, single value or numpy array.
    
        coef : float
            List of coefficients, typically automatically extracted from YAML DB.
    
        Returns
        -------
        float
            Price in EURO/kg.
    
        Raises
        ------
        LookupError
            If not all required keys/values are present in the coef dictionary.
    
        References
        ----------
        Scheuer, A.A., 2019. Alles ist immer so teuer. Winkelhausener
        Anzeiger, 2019-11-11, p. 13.
    
        """
        try:
            A = coef['A']
            B = coef['B']
        except LookupError as e:
            print("ERROR: Not all coefficients supplied, cannot compute values!\n"
                  "First missing coefficient: %s" % e)
            raise
        p =  A / (B - Temp)
        return p
    
  3. Add a new wrapper method “_price” to the class Properties of yamdb/yamdb.py

def _price(self, Temp, *args, source=None):
    """Return the price of the substance at the specified temperature.

    Parameters
    ----------
    Temp : float
        temperature in K or numpy array of temperature values in K

    *args : float
        if applicable (e.g. for salt mixtures): concentration of the first constituent in mol%

    source : str
        reference/source for coefficient values

    Returns
    -------
    float
        Price in EURO/kg.
    """

    if source is None:
        source = self.get_default_source('price')
    return self._price_func_dict[source](Temp, *args)
  1. Add the ‘price’ module to the module_dict in yamdb/yamdb.py

    module_dict = {
        'density': None,
        'dynamic_viscosity': None,
        'expansion_coefficient': None,
        'heat_capacity': None,
        'resistivity': None,
        'sound_velocity': None,
        'surface_tension': None,
        'thermal_conductivity': None,
        'vapour_pressure': None,
        'price': None,
    }
    
  2. Add your newly defined property to one of the materials, we use again adamantium for the example

    Ad:
      Tm: 987
      Tb: 2345
      M: 543.21987
      density:
        Eisenbart1803:
          rho_m: 6.5432
          A: 2.321
          P: 423
          equation: Eisenbart1803
          Tmin: 1000
          Tmax: 2000
          comment: complete nonsense, do not use!
          uncertainty: 100%
          default: true
      price:
        Scheuer2019:
          A: 10000
          B: 2345
          equation: Scheuer2019
          Tmin: 987
          Tmax: 2345
          comment: completely made up out of thin air, never rely on this!
          uncertainty: 100%
          default: true
    

References

[Janz1992]

Janz, G.J., 1992. Data from: NIST properties of molten salts database (formerly SRD 27). https://doi.org/10.18434/MDS2-2298