batemaneq
=========

.. image:: http://hera.physchem.kth.se:8080/github.com/bjodah/batemaneq/status.svg?branch=master
   :target: http://hera.physchem.kth.se:8080/github.com/bjodah/batemaneq
   :alt: Build status
.. image:: https://img.shields.io/pypi/v/batemaneq.svg
   :target: https://pypi.python.org/pypi/batemaneq
   :alt: PyPI version
.. image:: https://img.shields.io/badge/python-2.7,3.4-blue.svg
   :target: https://www.python.org/
   :alt: Python version
.. image:: https://img.shields.io/pypi/l/batemaneq.svg
   :target: https://github.com/bjodah/batemaneq/blob/master/LICENSE
   :alt: License
.. image:: http://hera.physchem.kth.se/~batemaneq/branches/master/htmlcov/coverage.svg
   :target: http://hera.physchem.kth.se/~batemaneq/branches/master/htmlcov
   :alt: coverage


``batemaneq`` provides a `C++ implementation <include/bateman.hpp>`_ of the `Bateman equation <https://en.wikipedia.org/wiki/Bateman_Equation>`_,
and a `Python <http://www.python.org>`_ bidning thereof.

Documentation
-------------
Autogenerated API documentation is found here: `<https://pythonhosted.org/batemaneq>`_
(and dev docs are here: `<http://hera.physchem.kth.se/~batemaneq/branches/master/html>`_).

Installation
------------
Simplest way to install pyodesys and is to use `pip` (requires a C++11 compliant compiler to be installed for the C++ version):

::

   $ pip install batemaneq

or using the `conda package manager <http://conda.pydata.org/docs/>`_:

::

   $ conda install -c bjodah batemaneq pytest
   $ python -m pytest --pyargs batemaneq


Examples
--------
See `examples/ <https://github.com/bjodah/chempy/tree/master/examples>`_, and rendered jupyter notebooks here:
`<http://hera.physchem.kth.se/~chempy/branches/master/examples>`_


The Thorium series
^^^^^^^^^^^^^^^^^^
Half-lives shorter than 1h excluded from the `decay chain <https://en.wikipedia.org/wiki/Decay_chain>`_:

In Python:

.. code:: python

   >>> from batemaneq import bateman_parent
   >>> from math import log as ln
   >>> d = 1./365  # Th-232 Ra-228 Ac-228 Th-228
   >>> h = d/24    # Ra-224 Pb-212 Bi-212 (Pb-208)
   >>> Thalf = [1.405e10, 5.75, 6.25*h, 1.9116, 3.6319*d, 10.64*h, 60.55/60*h]
   >>> bateman_parent([ln(2)/x for x in Thalf], 100)  # 100 years
   [0.99999999506656811, 4.0925028658312447e-10, 5.0780510011876959e-14, 1.3605575316895603e-10, 7.0820811723290359e-13, 8.6448488319470398e-14, 8.1993357876381666e-15]

In C++:

.. code:: C++

   #include <cmath>
   #include <iostream>
   #include <iomanip>
   #include <vector>
   #include "bateman.hpp"

   using vec_t = std::vector<double>;
   double exp_cb(double arg){
       return std::exp(arg);
   }

   int main(){
      double one = 1;
      double d = one/365;
      double h = d/24;
      double ln2 = std::log(2);
      vec_t lmbd {{ ln2/1.405e10, ln2/5.75, ln2/(6.25*h),
          ln2/1.9116, ln2/(3.6319*d), ln2/(10.64*h), ln2/(60.55/60*h) }};
      auto p = bateman::bateman_parent(lmbd, 100.0, exp_cb);
      std::cout << std::setprecision(17);  // all significant digits
      for (auto v : p)
          std::cout << v << " ";
      std::cout << std::endl;
      return 0;
   }

::

   $ g++ -std=c++11 double.cpp -I../include
   $ ./a.out
   0.99999999506656811 4.0925028658312447e-10 5.0780510011876959e-14 1.3605575316895603e-10 7.0820811723290359e-13 8.6448488319470398e-14 8.1993357876381666e-15

In C++ using ``boost::multiprecision::cpp_dec_float_50``:

.. code:: C++

   #include <cmath>
   #include <iostream>
   #include <vector>
   #include <boost/multiprecision/cpp_dec_float.hpp>
   #include "bateman.hpp"

   using Real_t = boost::multiprecision::cpp_dec_float_50;
   using vec_t = std::vector<Real_t>;
   Real_t exp_cb(Real_t arg){
       return boost::multiprecision::exp(arg);
   }

   int main(){
      Real_t one = 1;
      Real_t d = one/365;
      Real_t h = d/24;
      Real_t ln2 = boost::multiprecision::log(2*one);
      vec_t lmbd {{ ln2/1.405e10, ln2/5.75, ln2/(6.25*h),
          ln2/1.9116, ln2/(3.6319*d), ln2/(10.64*h), ln2/(60.55/60*h) }};
      auto p = bateman::bateman_parent(lmbd, static_cast<Real_t>(100), exp_cb);
      std::cout << std::setprecision(30);  // show 30 of our 50 digits
      for (auto v : p)
          std::cout << v << " ";
      std::cout << std::endl;
      return 0;
   }


::

   $ g++ -std=c++11 multi.cpp -I../include
   $ ./a.out
   0.999999995066568122063002778128 4.09250286583124398565537707859e-10 5.07805100118769662240802082504e-14 1.3605575316895606205575997585e-10 7.08208117232903695657287769184e-13 8.6448488319470425326824303941e-14 8.19933578763816849146541981927e-15

We see that the concentration of the final nuclide only varies in the 15th decimal place (we had no catastropic cancelation in this example).

License
=======
The source code is Open Source and is released under the very permissive
"simplified (2-clause) BSD license". See ``LICENSE.txt`` for further details.

Contributors are welcome to suggest improvements at https://github.com/bjodah/batemaneq

Author
======
Björn I. Dahlgren, contact:

- gmail address: bjodah
- kth.se address: bda
