Source code for chempy.properties.sulfuric_acid_density_myhre_1998

# -*- coding: utf-8 -*-
"""
This module implements the denisty parameterisation of aqueous sulfuric acid
of Myhre et al. from 1998.
"""
from __future__ import (absolute_import, division, print_function)

import numpy as np
import warnings

from ..util import NoConvergence


_data = np.array([[999.8426, 0.03345402, -0.005691304, 0, 0],
                  [547.2659, -5.300445, 0.01187671, 0.0005990008, 0],
                  [5262.95, 37.20445, 0.1201909, -0.004148594, 1.197973E-5],
                  [-62139.58, -287.767, -0.4064638, 0.01119488, 3.607768E-5],
                  [409029.3, 1270.854, 0.326971, -0.01377435, -2.633585E-5],
                  [-1596989, -3062.836, 0.1366499, 0.006373031, 0],
                  [3857411, 4083.714, -0.1927785, 0, 0],
                  [-5808064, -2844.401, 0, 0, 0],
                  [5301976, 809.1053, 0, 0, 0],
                  [-2682616, 0, 0, 0, 0],
                  [576428.8, 0, 0, 0, 0]])


[docs]def sulfuric_acid_density(w, T=None, T0=None, units=None, warn=True): """ Density of sulfuric acid (kg/m³) as function of temperature (K) and mass fraction acid (w). Parameters ---------- w: float Acid mass fraction (0.1 <= w <= 0.9) T: float Temperature (in Kelvin) (273 <= T <= 323) (default: 298.15) T0: float Value of T for 0 degree Celsius (default: 273.15) units: object (optional) object with attributes: kelvin, meter, kilogram warn: bool (default: True) Emit UserWarning when outside T or w range. Returns ------- Density of sulfuric acid (float of kg/m³ if T is float and units is None) Examples -------- >>> print('%d' % sulfuric_acid_density(.5, 293)) 1396 References ---------- Cathrine E. L. Myhre , Claus J. Nielsen ,* and Ole W. Saastad "Density and Surface Tension of Aqueous H2SO4 at Low Temperature" J. Chem. Eng. Data, 1998, 43 (4), pp 617–622 http://pubs.acs.org/doi/abs/10.1021/je980013g DOI: 10.1021/je980013g """ if units is None: K = 1 m = 1 kg = 1 else: K = units.Kelvin m = units.meter kg = units.kilogram if T is None: T = 298.15*K m3 = m**3 if T0 is None: T0 = 273.15*K t = T - T0 if warn: if np.any(t < 0*K) or np.any(t > 50*K): warnings.warn("Temperature is outside range (0-50 degC)") if np.any(w < 0.1) or np.any(w > .9): warnings.warn("Mass fraction is outside range (0.1-0.9)") t_arr = np.array([float(t/K)**j for j in range(5)]).reshape((1, 5)) w_arr = np.array([w**i for i in range(11)]).reshape((11, 1)) return np.sum((t_arr*w_arr)*_data)*kg/m3 # Equation (2) in reference # generated at doi2bib.org:
bibtex = """ @article{Myhre1998, doi = {10.1021/je980013g}, url = {http://dx.doi.org/10.1021/je980013g}, year = {1998}, month = {jul}, publisher = {American Chemical Society ({ACS})}, volume = {43}, number = {4}, pages = {617--622}, author = {Cathrine E. L. Myhre and Claus J. Nielsen and Ole W. Saastad}, title = {Density and Surface Tension of Aqueous H2{SO}4 at Low Temperature}, journal = {Journal of Chemical {\&} Engineering Data} } """
[docs]def density_from_concentration(conc, T=None, molar_mass=None, rho_cb=sulfuric_acid_density, units=None, atol=None, maxiter=10, **kwargs): """ Calculates the density of a solution from its concentration Given a function which calculates the density of a solution from the mass fraction of the solute, this function calculates (iteratively) the density of said solution for a given concentration. Parameters ---------- conc: float (optionally with units) concentration (mol / m³) T: float (optionally with units) passed to ``rho_cb`` molar_mass: float (optionally with units) Molar mass of solute rho_cb: callback callback with signature f(w, T, units=None) -> rho (default: :func:`sulfuric_acid_density`) units: object (optional) object with attributes: meter, kilogram, mol atol: float (optionally with units) convergence criterion for fixed-point iteration (default: 1e-3 kg/m³) maxiter: int maximum number of iterations (when exceeded a NoConvergence excpetion is raised) \*\*kwargs: keyword arguments passed onto ``rho_cb`` Returns ------- Density of sulfuric acid (float of kg/m³ if T is float and units is None) Examples -------- >>> print('%d' % density_from_concentration(400, 293)) 1021 Raises ------ chempy.util.NoConvergence: When maxiter is exceeded """ if units is None: m = 1 kg = 1 mol = 1 else: m = units.meter kg = units.kilogram mol = units.mol kg_per_m3 = kg * m**-3 if atol is None: atol = 1e-3 * kg_per_m3 if molar_mass is None: molar_mass = (1.00794*2 + 32.066 + 4*15.9994)*1e-3 * kg / mol if units is not None: conc = conc.rescale(mol/m**3) molar_mass = molar_mass.rescale(kg/mol) rho = 1100 * kg_per_m3 delta_rho = float('inf') * kg_per_m3 iter_idx = 0 while atol < abs(delta_rho): # fixed point iteration new_rho = rho_cb(conc*molar_mass/rho, T, units=units, **kwargs) delta_rho = new_rho - rho rho = new_rho iter_idx += 1 if iter_idx > maxiter: raise NoConvergence("maxiter exceeded") return rho