Search code examples
c++c++11boost-units

Using Boost.Units and Boost.Multiprecision


I am attempting to write a molecular dynamics program, and I thought that Boost.Units was a logical choice for the variables, and I also decided that Boost.Multiprecision offered a better option than double or long double with respect to round off errors. A combination of the two seems fairly straight forward until I attempt to use a constant, then it breaks down.

#include <boost/multiprecision/gmp.hpp>
#include <boost/units/io.hpp>
#include <boost/units/pow.hpp>
#include <boost/units/quantity.hpp>
#include <boost/units/systems/si.hpp>
#include <boost/units/systems/si/codata/physico-chemical_constants.hpp>

namespace units = boost::units;
namespace si = boost::si;
namespace mp = boost::multiprecision;

units::quantity<si::mass, mp::mpf_float_50> mass = 1.0 * si::kilogram;
units::quantity<si::temperature, mp::mpf_float_50> temperature = 300. * si::kelvin;
auto k_B = si::constants::codata::k_B;  // Boltzmann constant
units::quantity<si::velocity, mp::mpf_float_50> velocity = units::root<2>(temperature * k_B / mass);
std::cout << velocity << std::endl;

The output will be 1 M S^-1. If I use long double in lieu of mp::mpf_float_50, then the result is 2.87818e-11 m s^-1. I know that the problem likes within the conversion between the constant and the other data because the constant defaults to a double. I have thought about creating my own Boltzmann constant, but I prefer to use the predefined value if possible.

My question, therefore, is how do I go about using Boost.Multiprecision when I have predefined constants from Boost.Units? If I must concede to using double or long double, then I will, but I suspect that a way exists to convert or utilize the other on the constants.

I am working with Mac OS X 10.7, Xcode 4.6.2, Clang 3.2, Boost 1.53.0 and the C++11 extensions.

I appreciate any help that can be offered.


Solution

  • I'd advise you not to use multiple precision arithmetic for molecular dynamics simulations because the time-step integration will be painfully slow. If the goal is to preserve total energy as much as possible, then just use Verlet or any other symplectic integrator. Multiple precision arithmetic (or long double, or compensated summation with plain double) may be useful for aggregating ensemble averages, though.

    Besides, if you write your simulation code using dimensionless (reduced) units you will also get rid of the dependency on Boost.Units.