Skip to content

Commit

Permalink
Merge pull request #24 from chemics/dev
Browse files Browse the repository at this point in the history
Proximate and ultimate analysis bases
  • Loading branch information
wigging authored Jul 15, 2021
2 parents 79c9130 + fa77d97 commit 734b61c
Show file tree
Hide file tree
Showing 16 changed files with 338 additions and 225 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@

Version numbers use calendar versioning based on `YY.MM.MICRO`. See the [CalVer](https://calver.org) website for more information about this versioning convention. The format of this changelog follows the approach outlined on the [Keep a Changelog](https://keepachangelog.com) website.

## 21.7

#### Added

- `Proximate` and `Ultimate` analysis classes
- Tests and documentation for the above classes

#### Removed

- Deleted `proximate_bases()` and `ultimate_bases()` functions

## 21.5

#### Added
Expand Down
23 changes: 8 additions & 15 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,32 @@ The following is a set of guidelines for contributing to the Chemics Python pack

## Code style

All code in the Chemics package should adhere to the style enforced by the [Flake8][f8] tool. This will ensure a consistent code format throughout the package and prevent syntax errors during development. For the Flake8 style settings, ignore the E501, W503, W605 errors and warnings.
All code in the Chemics package should adhere to the style enforced by the [Flake8](https://pypi.org/project/flake8/) tool. This will ensure a consistent code format throughout the package and prevent syntax errors during development. For the Flake8 style settings, ignore the E501, W503, W605 errors and warnings.

## Docstrings

All functions, classes, and other Python components should contain docstrings with syntax and best practices outlined by the [NumPy docstring guide][np].
All functions, classes, and other Python components should contain docstrings with syntax and best practices outlined by the [NumPy docstring guide](https://numpydoc.readthedocs.io/en/latest/format.html).

## Example code
## Examples

A simple example of how to use a function or class should be included in its docstring. Along with an example in the docstring, a complete example is to be provided in the [chemics-examples][ce] repository.
A simple example of how to use a function or class should be included in its docstring. Along with an example in the docstring, please provide a complete example in the [examples](https://github.com/chemics/examples) repository.

## References

Within the docstring, a references section lists the original literature from which the function was developed.

## Tests

New functions for the Chemics package must include associated tests in the `tests/` folder. The [pytest][pt] framework is used to execute the test files.
New functions for the Chemics package must include associated tests in the `tests/` folder. The [pytest](https://docs.pytest.org/en/latest/) framework is used to execute the test files.

## Changelog

Don't forget to edit the changelog based on contributions. Follow the style on the [Keep a Changelog][cl] website.
Don't forget to edit the changelog based on your contributions. Follow the style on the [Keep a Changelog](https://keepachangelog.com) website.

## Sphinx documentation

Finally, new source code should be included in the [Sphinx documentation][sd] located in the `docs/` folder.
Finally, new source code should be included in the [Sphinx documentation](http://www.sphinx-doc.org/en/stable/) located in the `docs/` folder.

## Creating a Pull Request

All Pull Requests should be submitted to the `develop` branch; not to the `main` branch. When a new version is ready to be released the `develop` branch will be merged with the `main` branch.

[f8]: https://pypi.org/project/flake8/
[np]: https://numpydoc.readthedocs.io/en/latest/format.html
[ce]: https://github.com/chemics/chemics-examples
[cl]: https://keepachangelog.com
[sd]: http://www.sphinx-doc.org/en/stable/
[pt]: https://docs.pytest.org/en/latest/
All Pull Requests should be submitted to the `dev` branch; not to the `main` branch. When a new version is ready to be released the `dev` branch will be merged with the `main` branch.
4 changes: 2 additions & 2 deletions chemics/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@

from .pressure_drop import pressure_drop_ergun

from .proximate_bases import proximate_bases
from .proximate_analysis import Proximate

from .terminal_velocity import ut
from .terminal_velocity import ut_haider
Expand All @@ -73,7 +73,7 @@
from .transport_disengaging_height import tdh_horio
from .transport_velocity import utr

from .ultimate_bases import ultimate_bases
from .ultimate_analysis import Ultimate

from .wood_heat_capacity import cp_wood
from .wood_thermal_conductivity import k_wood
123 changes: 123 additions & 0 deletions chemics/proximate_analysis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import numpy as np


class Proximate:
"""
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 = 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'")

def __str__(self):
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])
82 changes: 0 additions & 82 deletions chemics/proximate_bases.py

This file was deleted.

Loading

0 comments on commit 734b61c

Please sign in to comment.