Source code for chemics.proximate_analysis

"""
Class for proximate analysis.
"""

import numpy as np


[docs] class Proximate: """ Proximate analysis. Proximate analysis values expressed as different bases. Such bases are as-determined (ad), as-received (ar), dry (d), and dry ash-free (daf). Parameters ---------- vals : list Proximate analysis values given as weight percent (wt. %), μg/g (trace elements), or Btu/lb (gross calorific value). Order of values is [FC, VM, ash, moisture]. basis : str Basis of given proximate analysis values. Options are 'ad' for as-determined basis or 'ar' for as-received basis. ADL : float, optional Air-dry loss as weight percent. Default value is 16.36 weight percent. Attributes ---------- ad_basis : ndarray As-determined basis (ad) ar_basis : ndarray As-received basis (ar) d_basis : ndarray Dry basis (d) daf_basis : ndarray Dry ash-free basis (daf) Raises ------ ValueError If basis is not ad or ar Example ------- >>> prox = cm.Proximate([47.26, 40.05, 4.46, 8.23], 'ad') >>> prox.ar_basis array([39.52..., 33.49..., 3.73..., 23.24...]) References ---------- ASTM D3180-15, Standard Practice for Calculating Coal and Coke Analyses from As-Determined to Different Bases, ASTM International, West Conshohocken, PA, 2015. """ def __init__(self, vals, basis, ADL=16.36): self.ADL = ADL if basis == "ad": self.ad_basis = np.array(vals) self._convert_from_ad() elif basis == "ar": self.ar_basis = np.array(vals) self._convert_from_ar() else: raise ValueError("Basis must be 'ad' or 'ar'")
[docs] def __str__(self): """ Return string representation. """ ad = self.ad_basis ar = self.ar_basis d = self.d_basis daf = self.daf_basis s = ( ' ad ar d daf\n' f'FC {ad[0]:>10.2f}{ar[0]:>10.2f}{d[0]:>10.2f}{daf[0]:>10.2f}\n' f'VM {ad[1]:>10.2f}{ar[1]:>10.2f}{d[1]:>10.2f}{daf[1]:>10.2f}\n' f'ash {ad[2]:>10.2f}{ar[2]:>10.2f}{d[2]:>10.2f}{"-":>10}\n' f'moisture {ad[3]:>10.2f}{ar[3]:>10.2f}{"-":>10}{"-":>10}\n' f'total {sum(ad):>10.2f}{sum(ar):>10.2f}{sum(d):>10.2f}{sum(daf):>10.2f}' ) return s
def _convert_from_ad(self): FC_ad = self.ad_basis[0] VM_ad = self.ad_basis[1] ash_ad = self.ad_basis[2] M_ad = self.ad_basis[3] ADL = self.ADL # As-received basis (ar) M_ar = (M_ad * (100 - ADL) / 100) + ADL FC_ar = FC_ad * (100 - M_ar) / (100 - M_ad) VM_ar = VM_ad * (100 - M_ar) / (100 - M_ad) ash_ar = ash_ad * (100 - M_ar) / (100 - M_ad) self.ar_basis = np.array([FC_ar, VM_ar, ash_ar, M_ar]) # Dry basis (d) FC_d = FC_ad * 100 / (100 - M_ad) VM_d = VM_ad * 100 / (100 - M_ad) ash_d = ash_ad * 100 / (100 - M_ad) self.d_basis = np.array([FC_d, VM_d, ash_d]) # Dry ash-free basis (daf) FC_daf = FC_ad * 100 / (100 - M_ad - ash_ad) VM_daf = VM_ad * 100 / (100 - M_ad - ash_ad) self.daf_basis = np.array([FC_daf, VM_daf]) def _convert_from_ar(self): FC_ar = self.ar_basis[0] VM_ar = self.ar_basis[1] ash_ar = self.ar_basis[2] M_ar = self.ar_basis[3] ADL = self.ADL # As-determined basis (ad) M_ad = (M_ar - ADL) / ((100 - ADL) / 100) FC_ad = FC_ar * (100 - M_ad) / (100 - M_ar) VM_ad = VM_ar * (100 - M_ad) / (100 - M_ar) ash_ad = ash_ar * (100 - M_ad) / (100 - M_ar) self.ad_basis = np.array([FC_ad, VM_ad, ash_ad, M_ad]) # Dry basis (d) FC_d = FC_ar * 100 / (100 - M_ar) VM_d = VM_ar * 100 / (100 - M_ar) ash_d = ash_ar * 100 / (100 - M_ar) self.d_basis = np.array([FC_d, VM_d, ash_d]) # Dry ash-free basis (daf) FC_daf = FC_ar * 100 / (100 - M_ar - ash_ar) VM_daf = VM_ar * 100 / (100 - M_ar - ash_ar) self.daf_basis = np.array([FC_daf, VM_daf])