Mixed units with boost::units - c++

In my program, I would like to take advantage of boost::units for type safe computations and automatic conversions. As a novice user of the library, I have a basic understanding of how it works, and why implicit type conversion is forbidden.
Right now I can write code like this
using namespace boost::units;
using namespace boost::units::si;
quantity<mass> my_mass(50 * kilogram);
quantity<force> my_force = my_mass * 9.81 * meter / pow<2>(second);
Where my_mass will be expressed in kilograms and my_force in Newton. But for convenience when interacting with other libraries which accept only double, I would prefer forces to be in kiloNewton (and, similarly, pressures in MegaPascal). So I do this:
typedef make_scaled_unit<force, scale<10, static_rational<3>>>::type kiloforce;
quantity<kiloforce> scaled_force(my_mass * 9.81 * meter / pow<2>(second));
Which works, but forces an explicit conversion. The following code, rightfully, does not compile:
quantity<kiloforce> scaled_force = my_mass * 9.81 * meter / pow<2>(second);
Because it represents an implicit conversion. My question is then: is there a way to configure the library so that quantities are expressed in the scaled unit of choice?
After all, this is the case for "kilogram", so I looked into scaled units, but I cannot seem to find a way to make it work. The idea would have been to define a custom system, but since mass, force and pressure are related to each other, this is not possible, as explained here.

The basic problem seems to be that you're looking for a dimensionless force in kilonewtons. That's not hard :
quantity<force> my_force = my_mass * 9.81 * meter / pow<2>(second);
double F = my_force / (kilo*newtons); // my_force in kN
The physics problem seems to be "kiloforce". That's not how physics works. Forces do not have prefixes, units do. E.g. length vs. meter/kilometer and mass vs gram/kilogram. Similarly, force vs Nnewton/kiloNewton.
That said, may I suggest
make_scaled_unit<acceleration, scale<10, static_rational<3>>>::type g(0.00981);
Don't ask me why you'd express the earth's acceleration in kilometers per second squared, but a kiloNewton is a kilometer kilogram per second squared.

Related

How to do numeric differentiation using Boost Units?

I would like to perform a numeric differentiation in C++. For type safety, I'd like to use boost::units to avoid mixing units but also boost::units::absolute to avoid mixing relative and absolute units.
A minimal example is to calculate the velocity as a function of the change in position divided by the change in time: v = dx/dt, which can be approximated as (x1 - x0)/(t1 - t0).
In this example v has an absolute unit (velocity), dx and dt relative ones (distance / duration).
While boost::units derives the correct unit if we simply take relative units everywhere,
static_assert(std::is_same<boost::units::divide_typeof_helper<
boost::units::si::length,
boost::units::si::time>::type,
boost::units::si::velocity>::value);
the static_assert fails if we want the result of our division being an absolute velocity:
static_assert(std::is_same<boost::units::divide_typeof_helper<
boost::units::si::length,
boost::units::si::time>::type,
boost::units::absolute<boost::units::si::velocity>>::value);
Am I doing a wrong assumption that the result of dividing two relative units should always yield an absolute one? Or is this an error in the implementation of boost::units?
From the docs on boost::units::absolute,
Description
A wrapper to represent absolute units (points rather than vectors).
Spacetime events are points (if not viewed as radius vectors), their differences are vectors. Velocity is also a vector. Thus, your assumption does indeed appear wrong.

Computing the Jacobian matrix in C++ (symbolic math)

Introduction
Let’s assume that I need the Jacobian matrix for the following set of ODE:
dxdt[ 0 ] = -90.0 * x[0] - 50.0 * x[1];
dxdt[ 1 ] = x[0] + 3*x[1];
dxdt[ 2 ] = x[1] + 50*x[2];
In Matlab/Octave this would be pretty easy:
syms x0 x1 x2;
f = [-90.0*x0-50.0*x1, x0+3*x1, x1+50*x2]
v=[x0, x1, x2]
fp = jacobian(f,v)
This would results with following output matrix:
[-90 -50 0 ]
[ 1 3 0 ]
[ 0 1 50]
What I need
Now I want to reproduce the same results in C++. I can’t compute the Jacobian before and hard-code it, as it will depend for example on user inputs and time. So my question is: How to do this? Usually for mathematics operations, I use the Boost library, however in this case I can’t find any solution. There’s only short note about this in implicit systems, but the following code doesn’t work:
sys.second( x , jacobi , t )
It also requests the time (t), so it probably doesn’t generate an analytic form of solution. Do I misunderstand the documentations? Or should I use another function? I would prefer to stay within Boost, as I need the Jacobian as ublas::matrix and I want to avoid conversion.
EDIT:
More specific I will use Jacobian inside rosenbrock4 ODE solver. Example here - lines 47-52. I need automatic generation of this structure as the ODE set may be changed later and I want to avoid manually rewriting Jacobian ever time. Also some variables inside ODE definitions are not constant in time.
I know this is long after the fact, but I have recently been wanting to do the same thing and have come across many auto differentiation (AD) libraries that do this pretty well. I have mostly been using Eigen's AD because I am already using Eigen everywhere. Here's an example of how you can use Eigen's AD to get the jacobian like you asked.
There's also a long list of c++ AD libraries on autodiff.org.
Hope this helps someone!
The Jacobian is based on derivatives of the function. If the function f is only known at run-time (and there are no constraints such as linearity), you have to automatise the differentiation. If you want this to happen exactly (as opposed to a numerical estimation), you need to use symbolic computation. Look for example here and here for libraries supporting this.
Note that the Jacobian usually depends on the state and the time, so it’s impossible to represent it as a constant matrix (such as in your example), unless your problem is so boring that you can solve it analytically anyway.

Type safe physics operations in C++

Does it make sens in C++ to define physics units as separate types and define valid operations between those types?
Is there any advantage in introducing a lot of types and a lot of operator overloading instead of using just plain floating point values to represent them?
Example:
class Time{...};
class Length{...};
class Speed{...};
...
Time operator""_s(long double val){...}
Length operator""_m(long double val){...}
...
Speed operator/(const Length&, const Time&){...}
Where Time, Length and Speed can be created only as a return type from different operators?
Does it make sens in C++ to define physics units as separate types and define valid operations between those types?
Absolutely. The standard Chrono library already does this for time points and durations.
Is there any advantage in introducing a lot of types and a lot of operator overloading instead of using just plain floating point values to represent them?
Yes: you can use the type system to catch errors like adding a mass to a distance at compile time, without adding any runtime overhead.
If you don't feel like defining the types and operators yourself, Boost has a Units library for that.
I would really recommend boost::units for this. It does all the conversion compile-time and also it gives you a compile time error if you're trying using erroneous dimensions
psuedo code example:
length l1, l2, l3;
area a1 = l1 * l2; // Compiles
area a2 = l1 * l2 * l3; // Compile time error, an area can't be the product of three lengths.
volume v1 = l1 * l2 * l3; // Compiles
I've gone down this road. The advantages are all the normal numerous and good advantages of type safety. The disadvantages I've run into:
You'll want to save off intermediate values in calculations... such as seconds squared. Having these values be a type is somewhat meaningless (seconds^2 obviously isn't a type like velocity is).
You'll want to do increasingly complex calculations which will require more and more overloads/operator defines to achieve.
At the end of the day, it's extremely clean for simple calculations and simple purposes. But when math gets complicated, it's hard to have a typed unit system play nice.
Everyone has mentioned the type-safety guarantees as a plus. Another HUGE plus is the ability to abstract the concept (length) from the units (meter).
So for example, a common issue when dealing with units is to mix SI with metric. When the concepts are abstracted as classes, this is no longer an issue:
Length width = Length::fromMeters(2.0);
Length height = Length::fromFeet(6.5);
Area area = width * height; //Area is computed correctly!
cout << "The total area is " << area.toInches() << " inches squared.";
The user of the class doesn't need to know what units the internal-representation uses... at least, as long as there are no severe rounding issues.
I really wish more trigonometry libraries did this with angles, because I always have to look up whether they're expecting degrees or radians...
For those looking for a powerful compile-time type-safe unit library, but are hesitant about dragging in a boost dependency, check out units. The library is implemented as a single .h file with no dependencies, and comes with a project to build unit tests/documentation. It's tested with msvc2013, 2015, and gcc-4.9.2, and should work with later versions of those compilers as well.
Full Disclosure: I'm the author of the library
Yes, it makes sense. Not only in physics, but in any discipline. In finance, e.g. interest rates are in units of inverse time intervals (typically express per year). Money has many different units. Converting between them can only be done with a cross-rate, has dimensions of one currency divided by another. Interest payments, dividend payments, principal payments, etc. ordinarily occur at a frequency.
It can prevent multiplying two values and ending up with an illegal value. It can prevent summing dollars and euros, etc.
I'm not saying you're wrong to do so, but we've gone overboard with that on the project I'm working on and frankly I doubt its benefits outweigh its hassle. Particularly if you're on a team, good variable naming (just spell the darn things out), code reviews, and unit testing will prevent any problems. On the other hand, if you can use Boost, units might be something to check into (I haven't).
To check for type safety, you can use a dedicated library.
The most wiedly use is boost::units, it works perfertly with no execution time overhead, a lot of features. If this library theoritically solve your problem. From a more practical point of vew, the interface is so awkward and badly documented that you may have problems. Morever the compilation time increase drastically with the number of dimensions, so clearly check that you can compile in a reasonable time a large project before using it.
doc : http://www.boost.org/doc/libs/1_56_0/doc/html/boost_units.html
An alternative is to use unit_lite. There are less features than the boost library but the compilation is faster, the interface simpler and errors messages are readables. This lib requires C++11.
code : https://github.com/pierreblavy2/unit_lite
The link to the doc is in the github description (I'm not allowed to post more than 2 links here !!!).
I gave a tutorial presentation at CPPcon 2015 on the Boost.Units library. It's a powerful library that every scientific application should be using. But it's hard to use due to poor documentation. Hopefully my tutorial helps with this. You can find the slides/code here:
If you want to use a very light weight header-only library based on c++20, you can use TU (Typesafe Units). It supports manipulation (*, /, +, -, sqrt, pow to arbitrary floating point numbers, unary operations on scalar units) for all SI units. It supports units with floating point dimensions like length^(d) where d is a decimal number. Moreover it is simple to define your own units. It also comes with a test suite...
...and yes, I'm the author of this library.

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.
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.

Predefinition of often used values in computations - does it change anything?

I'm auto generating C code to compute large expressions and try to figure out with simple examples whether it makes sense to predefine certain subparts in separate variables.
As a simple example, say we compute something of the form:
#include <cmath>
double test(double x, double y) {
const double c[9][9] = { ... }; // constants properly initialized, irrelevant
double expr = c[0][0]*x*y
+ c[1][0]*pow(x,2)*y + ... + c[8][0]*pow(x,9)*y
+ c[1][1]*pow(x,2)*pow(y,2) + ... + c[8][1]*pow(x,9)*pow(y,2)
+ ...
with all c[i][j] properly initialized. In reality those expressions contain tens of millions of multiplications and additions.
A colleague now proposed -- to reduce the number of calls to pow() and to cache often needed values in the expressions -- to define every power of x and y in a separate variable, which is no big deal as the code is auto generated anyway, like this:
double xp2 = pow(x,2);
double xp3 = pow(x,3);
double xp4 = pow(x,4);
// ...
// same for pow(y,n)
I think, however, that this is unnecessary, as the compiler should take care of these optimizations.
Unfortunately, I have no experience with reading and interpreting assembly but I think I see that all the calls to pow() are optimized out, is this right? Also, does the compiler cache the values for pow(x,2), pow(x,3), etc?
Thanks in advance for your input!
Using pow with integer arguments... ouch ! Typical implementations of pow are tuned for the general case of floating point arguments, which is why it is usually way slower to write
pow(x, 2) ( = exp(2 * log(x)) )
than
x * x
What I state here is very compiler dependant though. On one hand, some compilers may not even know that pow(x, 2) will yield the same value for a given x (after all, the extern function pow could have side effects), so you don't have any guarantee that common subexpressions will be eliminated. The pow function, on some (many ?) platforms/toolchains, is provided by a library the compiler has no control onto.
On other implementations though, the compiler may turn those pow calls into multiplications, or at least into intrinsics, which may in turn specialize for integer exponents. Your mileage will vary.
The first thing I'd do is to replace calls to pow by multiplications. For larger exponents, you may also do, eg.
double x2 = x * x;
double x3 = x * x2;
double x4 = x2 * x2;
Note that (credits to #Stephen Canon) doing repeated multiplications (with the above quick exponentiation scheme) will introduce roundoff error whose magnitude is proportional to the number of multiplications (ie. O(log exponent)). This error is typically tolerable, but pow guarantees exactness within one unit of least precision.
The compiler may perform common subexpression elimination- remember that it can't guarantee that all functions are re-entrant, but if pow is inlined, then it may well do this.
A good way to compute polynomials is Horner's rule. (eg here) which doesn't require pow() or any extra memory.
Your expression is x*y times a polynomial in y each of whose coefficients is a polynomial in x.
Each of these coefficients can be calculated using Horner with 8 multiplies and additions, and the polynomial in y with 8 more multiplies and additions for a total of 74 multiplies and 72 additions , whereas your sample code looks to me like more that 200 multiplications and more than a hundred calls to pow().
pow may be optimized away depending on the toolchain. The only way you can tell is to try it and see.
In the general case, unless the implementation of pow is visible to the compiler as a macro or inline, then the compiler can't cache the result as it doesn't know what side-effects the function may have.
Profile, find out where the bottlenecks are.
If the sub-expressions are used frequently, it may make sense to cache or store the intermediate values. However, accessing these values may take more time than letting the values sit in a data pipeline within the processor. Data fetches outside of the processor are much slower than fetching from its internal data cache.
Also try using Algebra to simplify the mathematical expressions. Perhaps even Linear Algebra to find some more efficient matrix expressions.
You may want to isolate the calculations to expressions involving one variable. Compilers can optimize code better when only one variable is used or changing at a time. For example, substitute the y variable with expressions involving x, if possible. This would reduce to an expression only involving x.
Also search the web for "data driven design" or "data oriented design". These sites show how to optimize code for data centric applications.